rework imagetag firmware generator and MTD partition parser to accomodate with all known imagetag versions from Broadcom and vendors, patch from Daniel Dickinson (fixes #4987).

SVN-Revision: 16393
This commit is contained in:
Florian Fainelli 2009-06-09 08:04:52 +00:00
parent 67a444c462
commit 01118457e8
6 changed files with 699 additions and 143 deletions

View file

@ -43,39 +43,170 @@ static struct map_info bcm963xx_map = {
.bankwidth = BUSWIDTH,
};
static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS;
static uint32_t tagcrc32tab[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
static uint32_t tagcrc32(uint32_t crc, uint8_t *data, size_t len)
{
while (len--)
crc = (crc >> 8) ^ tagcrc32tab[(crc ^ *data++) & 0xFF];
return crc;
}
static int parse_cfe_partitions( struct mtd_info *master, struct mtd_partition **pparts)
{
int nrparts = 3, curpart = 0; /* CFE,NVRAM and global LINUX are always present. */
struct bcm_tag *buf;
union bcm_tag *buf;
struct mtd_partition *parts;
int ret;
size_t retlen;
unsigned int rootfsaddr, kerneladdr, spareaddr;
unsigned int rootfslen, kernellen, sparelen, totallen;
unsigned char *tagid;
int namelen = 0;
int i;
uint32_t tagidcrc;
uint32_t calctagidcrc;
bool tagid_match = false;
char *boardid;
char *tagversion;
char *matchtagid;
/* Allocate memory for buffer */
buf = vmalloc(sizeof(struct bcm_tag));
buf = vmalloc(sizeof(union bcm_tag));
if (!buf)
return -ENOMEM;
/* Get the tag */
ret = master->read(master,master->erasesize,sizeof(struct bcm_tag), &retlen, (void *)buf);
if (retlen != sizeof(struct bcm_tag)){
ret = master->read(master,master->erasesize,sizeof(union bcm_tag), &retlen, (void *)buf);
if (retlen != sizeof(union bcm_tag)){
vfree(buf);
return -EIO;
}
printk(KERN_INFO PFX "CFE boot tag found with version %s and board type %s.\n",buf->tagVersion,buf->boardid);
/* Get the values and calculate */
sscanf(buf->rootAddress,"%u", &rootfsaddr);
/* tagId isn't in the same location, so we check each tagid against the
* tagid CRC. If the CRC is valid we have found the right tag and so
* use that tag
*/
for (i = 0; i < NUM_TAGID; i++) {
switch(i) {
case 0:
matchtagid = "bccfe";
tagid = &(buf->bccfe.tagId[0]);
sscanf(buf->bccfe.rootAddress,"%u", &rootfsaddr);
sscanf(buf->bccfe.rootLength, "%u", &rootfslen);
sscanf(buf->bccfe.kernelAddress, "%u", &kerneladdr);
sscanf(buf->bccfe.kernelLength, "%u", &kernellen);
sscanf(buf->bccfe.totalLength, "%u", &totallen);
tagidcrc = buf->bccfe.tagIdCRC;
tagversion = &(buf->bccfe.tagVersion[0]);
boardid = &(buf->bccfe.boardid[0]);
break;
case 1:
matchtagid = "bc300";
tagid = &(buf->bc300.tagId[0]);
sscanf(buf->bc300.rootAddress,"%u", &rootfsaddr);
sscanf(buf->bc300.rootLength, "%u", &rootfslen);
sscanf(buf->bc300.kernelAddress, "%u", &kerneladdr);
sscanf(buf->bc300.kernelLength, "%u", &kernellen);
sscanf(buf->bc300.totalLength, "%u", &totallen);
tagidcrc = buf->bc300.tagIdCRC;
tagversion = &(buf->bc300.tagVersion[0]);
boardid = &(buf->bc300.boardid[0]);
break;
case 2:
matchtagid = "ag306";
tagid = &(buf->ag306.tagId[0]);
sscanf(buf->ag306.rootAddress,"%u", &rootfsaddr);
sscanf(buf->ag306.rootLength, "%u", &rootfslen);
sscanf(buf->ag306.kernelAddress, "%u", &kerneladdr);
sscanf(buf->ag306.kernelLength, "%u", &kernellen);
sscanf(buf->ag306.totalLength, "%u", &totallen);
tagidcrc = buf->ag306.tagIdCRC;
tagversion = &(buf->ag306.tagVersion[0]);
boardid = &(buf->ag306.boardid[0]);
break;
case 3:
matchtagid = "bc308";
tagid = &(buf->bc308.tagId[0]);
sscanf(buf->bc308.rootAddress,"%u", &rootfsaddr);
sscanf(buf->bc308.rootLength, "%u", &rootfslen);
sscanf(buf->bc308.kernelAddress, "%u", &kerneladdr);
sscanf(buf->bc308.kernelLength, "%u", &kernellen);
sscanf(buf->bc308.totalLength, "%u", &totallen);
tagidcrc = buf->bc308.tagIdCRC;
tagversion = &(buf->bc308.tagVersion[0]);
boardid = &(buf->bc308.boardid[0]);
break;
case 4:
matchtagid = "bc310";
tagid = &(buf->bc310.tagId[0]);
sscanf(buf->bc310.rootAddress,"%u", &rootfsaddr);
sscanf(buf->bc310.rootLength, "%u", &rootfslen);
sscanf(buf->bc310.kernelAddress, "%u", &kerneladdr);
sscanf(buf->bc310.kernelLength, "%u", &kernellen);
sscanf(buf->bc310.totalLength, "%u", &totallen);
tagidcrc = buf->bc310.tagIdCRC;
tagversion = &(buf->bc310.tagVersion[0]);
boardid = &(buf->bc310.boardid[0]);
break;
}
if (strncmp(tagid, matchtagid, TAGID_LEN) != 0) {
continue;
}
calctagidcrc = tagcrc32(IMAGETAG_CRC_START, tagid, TAGID_LEN);
if (tagidcrc = calctagidcrc) {
tagid_match = true;
break;
}
}
if (!tagid_match) {
printk(KERN_ERR PFX "Failed to find a valid tag id\n");
return -EIO;
}
printk(KERN_INFO PFX "CFE boot tag found with version %s, board type %s, and tagid %s.\n",tagversion,boardid,tagid);
rootfsaddr = rootfsaddr - EXTENDED_SIZE;
sscanf(buf->rootLength, "%u", &rootfslen);
sscanf(buf->kernelAddress, "%u", &kerneladdr);
kerneladdr = kerneladdr - EXTENDED_SIZE;
sscanf(buf->kernelLength, "%u", &kernellen);
sscanf(buf->totalLength, "%u", &totallen);
spareaddr = roundup(totallen,master->erasesize) + master->erasesize;
sparelen = master->size - spareaddr - master->erasesize;

View file

@ -3,32 +3,175 @@
#define IMAGE_LEN 10 /* Length of Length Field */
#define ADDRESS_LEN 12 /* Length of Address field */
#define TAGID_LEN 6 /* Length of tag ID */
#define TAGINFO_LEN 20 /* Length of vendor information field in tag */
#define TAGVER_LEN 4 /* Length of Tag Version */
struct bcm_tag {
unsigned char tagVersion[4]; // Version of the image tag
unsigned char sig_1[20]; // Company Line 1
unsigned char sig_2[14]; // Company Line 2
unsigned char chipid[6]; // Chip this image is for
unsigned char boardid[16]; // Board name
unsigned char big_endian[2]; // Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; //Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // Size of CFE
unsigned char cfeRootAddress[ADDRESS_LEN]; // Address in memory of rootfs
unsigned char cfeRootLength[IMAGE_LEN]; // Size of rootfs
unsigned char kernelAddress[ADDRESS_LEN]; // Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // Size of kernel
unsigned char dualImage[2]; // Unused at present
unsigned char inactiveFlag[2]; // Unused at present
unsigned char reserved1[74]; // Reserved area not in use
unsigned char imageCRC[4]; // CRC32 of images
// unsigned char reserved2[16]; // Unused at present
unsigned char reserved2[4]; //Unused
unsigned char rootAddress[ADDRESS_LEN]; // Address in memory of rootfs
unsigned char headerCRC[4]; // CRC32 of header excluding tagVersion
// unsigned char reserved3[16]; // Unused at present
unsigned char reserved3[6]; // Unused at present
unsigned char rootLength[IMAGE_LEN]; // Size of rootfs
#define NUM_TAGID 5
#define IMAGETAG_CRC_START 0xFFFFFFFF
struct tagiddesc_t {
char tagid[TAGID_LEN + 1];
char tagiddesc[80];
};
// what is called bc308 may actually be BT Voyager-specific
// bc310 should be right
#define TAGID_DEFINITIONS { \
{ "bccfe", "Broadcom CFE flash image" }, \
{ "bc300", "Broadcom code version 3.00-3.06 and all ftp/tftp flash" }, \
{ "ag306", "Alice Gate (Pirelli, based on Broadcom 3.06)" }, \
{ "bc308", "Broadcom code version 3.08" }, \
{ "bc310", "Broadcom code version 3.10-3.12" }, \
}
struct bcm_tag_bccfe {
unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
unsigned char sig_1[20]; // 4-23: Company Line 1
unsigned char sig_2[14]; // 24-37: Company Line 2
unsigned char chipid[6]; // 38-43: Chip this image is for
unsigned char boardid[16]; // 44-59: Board name
unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
unsigned char rootAddress[ADDRESS_LEN]; // 94-105: Address in memory of rootfs
unsigned char rootLength[IMAGE_LEN]; // 106-115: Size of rootfs
unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
unsigned char dualImage[2]; // 138-139: Unused at present
unsigned char inactiveFlag[2]; // 140-141: Unused at present
unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present
unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced
unsigned char tagIdCRC[4]; // 168-171: CRC32 of tagId
unsigned char reserved1[44]; // 172-215: Reserved area not in use
unsigned char imageCRC[4]; // 216-219: CRC32 of images
unsigned char reserved2[16]; // 220-235: Unused at present
unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
unsigned char reserved3[16]; // 240-255: Unused at present
};
struct bcm_tag_bc300 {
unsigned char tagVersion[4]; // 0-3: Version of the image tag
unsigned char sig_1[20]; // 4-23: Company Line 1
unsigned char sig_2[14]; // 24-37: Company Line 2
unsigned char chipid[6]; // 38-43: Chip this image is for
unsigned char boardid[16]; // 44-59: Board name
unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image)
unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image)
unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
unsigned char dualImage[2]; // 138-139: Unused at present
unsigned char inactiveFlag[2]; // 140-141: Unused at present
unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present
unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced
unsigned char tagIdCRC[4]; // 168-173: CRC32 to ensure validity of tagId
unsigned char rootAddress[ADDRESS_LEN]; // 174-183: Address in memory of rootfs partition
unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition
unsigned char reserved1[22]; // 194-215: Reserved area not in use
unsigned char imageCRC[4]; // 216-219: CRC32 of images
unsigned char reserved2[16]; // 220-235: Unused at present
unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
unsigned char reserved3[16]; // 240-255: Unused at present
};
struct bcm_tag_ag306 {
unsigned char tagVersion[4]; // 0-3: Version of the image tag
unsigned char sig_1[20]; // 4-23: Company Line 1
unsigned char sig_2[14]; // 24-37: Company Line 2
unsigned char chipid[6]; // 38-43: Chip this image is for
unsigned char boardid[16]; // 44-59: Board name
unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image)
unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image)
unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
unsigned char dualImage[2]; // 138-139: Unused at present
unsigned char inactiveFlag[2]; // 140-141: Unused at present
unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present
unsigned char information2[54]; // 162-215: Compilation and related information (not generated/used by OpenWRT)
unsigned char kernelCRC[4] ; // 216-219: CRC32 of images
unsigned char rootAddress[ADDRESS_LEN]; // 220-231: Address in memory of rootfs partition
unsigned char tagIdCRC[4]; // 232-235: Checksum to ensure validity of tagId
unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
unsigned char rootLength[IMAGE_LEN]; // 240-249: Size of rootfs
unsigned char tagId[TAGID_LEN]; // 250-255: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced
};
struct bcm_tag_bc308 {
unsigned char tagVersion[4]; // 0-3: Version of the image tag
unsigned char sig_1[20]; // 4-23: Company Line 1
unsigned char sig_2[14]; // 24-37: Company Line 2
unsigned char chipid[6]; // 38-43: Chip this image is for
unsigned char boardid[16]; // 44-59: Board name
unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image)
unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image)
unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
unsigned char dualImage[2]; // 138-139: Unused at present
unsigned char inactiveFlag[2]; // 140-141: Unused at present
unsigned char information1[TAGINFO_LEN+2]; // 142-163: Unused at present
unsigned char tagId[TAGID_LEN]; // 164-169: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced
unsigned char rootAddress[ADDRESS_LEN]; // 170-181: Address in memory of rootfs partition
unsigned char rootLength[IMAGE_LEN]; // 182-191: Size of rootfs partition
unsigned char flashLayoutVer[2]; // 192-193: Version flash layout
unsigned char curflashLayoutVer[2]; // 194-195: Unused at present
unsigned char kernelCRC[4]; // 196-199: Guessed to be kernel CRC
unsigned char reserved4[16]; // 200-215: Reserved area; unused at present
unsigned char imageCRC[4]; // 216-219: CRC32 of images
unsigned char reserved2[12]; // 220-231: Unused at present
unsigned char tagIdCRC[4]; // 232-235: CRC32 to ensure validity of tagId
unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
unsigned char reserved3[16]; // 240-255: Unused at present
};
struct bcm_tag_bc310 {
unsigned char tagVersion[4]; // 0-3: Version of the image tag
unsigned char sig_1[20]; // 4-23: Company Line 1
unsigned char sig_2[14]; // 24-37: Company Line 2
unsigned char chipid[6]; // 38-43: Chip this image is for
unsigned char boardid[16]; // 44-59: Board name
unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE
unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image
unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image)
unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image)
unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
unsigned char dualImage[2]; // 138-139: Unused at present
unsigned char inactiveFlag[2]; // 140-141: Unused at present
unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present; Some vendors use this for optional information
unsigned char tagId[6]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced
unsigned char tagIdCRC[4]; // 168-171: CRC32 to ensure validity of tagId
unsigned char rootAddress[ADDRESS_LEN]; // 172-183: Address in memory of rootfs partition
unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition
unsigned char reserved1[22]; // 193-215: Reserved area not in use
unsigned char imageCRC[4]; // 216-219: CRC32 of images
unsigned char rootfsCRC[4]; // 220-227: CRC32 of rootfs partition
unsigned char kernelCRC[4]; // 224-227: CRC32 of kernel partition
unsigned char reserved2[8]; // 228-235: Unused at present
unsigned char headerCRC[4]; // 235-239: CRC32 of header excluding tagVersion
unsigned char reserved3[16]; // 240-255: Unused at present
};
union bcm_tag {
struct bcm_tag_bccfe bccfe;
struct bcm_tag_bc300 bc300;
struct bcm_tag_ag306 ag306;
struct bcm_tag_bc308 bc308;
struct bcm_tag_bc310 bc310;
};
#endif /* __BCM63XX_TAG_H */

View file

@ -17,6 +17,8 @@ LOADER_MAKEOPTS= \
KERNEL_ENTRY=$(KERNEL_ENTRY) \
RAMSIZE=$(RAMSIZE)
SVN_REVISION=r$(shell svn info|grep Revision|cut -f1 -d\ )
define trxalign/jffs2-128k
-a 0x20000
endef
@ -30,8 +32,9 @@ endef
define Image/Build/CFE
# Generate the tagged image
$(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
-o $(BIN_DIR)/openwrt-$(2)-$(1)-cfe.bin \
-b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR)
-o $(BIN_DIR)/openwrt-$(2)-$(1)-$(6)-cfe.bin \
-b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \
-t $(4) -d "$(5)"
# -b $(2) -c $(3) -e $(KERNEL_ENTRY) -l $(LOADADDR)
endef
@ -39,9 +42,9 @@ endef
define Image/Build/CFEAGPF
# Generate the tagged image
$(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
-o $(BIN_DIR)/openwrt-$(2)-$(1)-cfe.bin \
-o $(BIN_DIR)/openwrt-$(2)-$(1)-$(7)-cfe.bin \
-b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \
-v 8 -m IMAGE -k 0x20000 -n $(4) -p alice
-v 8 -m IMAGE -k 0x20000 -n $(4) -t $(5)
endef
define Image/Build/RedBoot
@ -95,24 +98,42 @@ endef
define Image/Build
$(STAGING_DIR_HOST)/bin/trx -o $(BIN_DIR)/openwrt-$(BOARD)-$(1).trx -f $(KDIR)/loader.gz -f $(KDIR)/vmlinux.lzma $(call trxalign/$(1)) -f $(KDIR)/root.$(1)
dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-root.$(1) bs=128k conv=sync
$(call Image/Build/CFE,$(1),96345GW2,6345)
$(call Image/Build/CFE,$(1),96348GW,6348)
# Various routers
$(call Image/Build/CFE,$(1),96345GW2,6345,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),96345GW2,6345,bc300,,bc300)
$(call Image/Build/CFE,$(1),96345GW2,6345,bc310,OpenWRT-$(SVN_REVISION),bc310)
$(call Image/Build/CFE,$(1),96348GW,6348,bccfe,,bcfe)
# BT Voyager V2500V
$(call Image/Build/CFE,$(1),V2500V_BB,6348,bc308,,btvgr)
# Tecom GW6000
$(call Image/Build/CFE,$(1),96348GW,6348,bc300,,bc300)
# Tecom GW6200
$(call Image/Build/CFE,$(1),96348GW,6348,bc310,$(shell printf '\x99'),gw6200)
# Neufbox4
$(call Image/Build/CFE,$(1),96358VW,6358)
# Comtrend 536
$(call Image/Build/CFE,$(1),96348GW-11,6348)
$(call Image/Build/CFE,$(1),96358VW,6358,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),96358VW,6358,bc310,OpenWRT-$(SVN_REVISION),nb4)
# Comtrend 536, 5621
$(call Image/Build/CFE,$(1),96348GW-11,6348,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),96348GW-11,6348,bc300,,bc300)
# Davolink DV201AMR
$(call Image/Build/CFEOLD,$(1),DV201AMR,6348)
# USR 9108
$(call Image/Build/CFE,$(1),96348GW-A,6348)
# DG834GT
$(call Image/Build/CFE,$(1),96348GW-10,6348)
$(call Image/Build/CFE,$(1),96348GW-A,6348,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),96348GW-A,6348,bc300,,bc300)
$(call Image/Build/CFE,$(1),96348GW-A,6348,bc310,OpenWRT-$(SVN_REVISION),bc310)
# NetGear DG834GT
$(call Image/Build/CFE,$(1),96348GW-10,6348,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),96348GW-10,6348,bc300,,bc300)
# Sagem F@ST2404
$(call Image/Build/CFE,$(1),F@ST2404,6348)
$(call Image/Build/CFE,$(1),F@ST2404,6348,bccfe,,bccfe)
$(call Image/Build/CFE,$(1),F@ST2404,6348,bc300,,bc300)
$(call Image/Build/CFE,$(1),F@ST2404,6348,bc310,OpenWRT-$(SVN_REVISION),bc310)
# Inventel Livebox
$(call Image/Build/RedBoot,livebox)
# Pirelli Alice Gate VoIP 2 Plus Wi-Fi AGPF-S0
$(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000)
$(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,bccfe,,bccfe)
$(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,ag306,,agv2+w)
endef
$(eval $(call BuildImage))

View file

@ -0,0 +1,91 @@
The image neede to flash onto a Broadcom 63xx-series board depends on the
board, method you are using to flash, and, for web-based flash, on the version
of the Broadcom code your router uses.
There are two major revisions of the Broadcom code as far as imagetags are
concerned, before 3.08 and after 3.08, however there are some variations
within in that, either due to vendor differences or due to changes at
Broadcom (it's not clear yet which is the case). In addtion Pirelli modified
the Broadcom code, so Alice Gate models use a different imagetag than any
other vendor.
The imagetag format for flashing via CFE is the same for almost all the
boards, and is the same for all images generated by the imagetag utility.
Images flashable using cfe are labelled openwrt-<board>-<filesystem>-cfe.bin
The imagetags for tftp/ftp flashing is based on Broadcom 3.00-3.04 imagetags
and is known to be correct as the source code GPL and is available for reading.
Broadcom 3.00-3.02 flashing has been tested on Comtrend CT-5261, CT-536 and
Tecom GW6000, and is the version of the flashing that was present before the
imagetags were split by broadcom code version (early June 2009)
3.04 is guessed to be the same as 3.00-3.02 based on available information
Broadom 3.06 is thought to be the same as 3.00-3.02, however the only 3.06
this author (Daniel Dickinson) has seen is the Alice Gate (Pirelli) firmware
which is known to be different due to vendor (Pirelli) modifications to the
Broadcom code.
Broadcom 3.08 introduced changes to the imagetag to deal with TR69 (a remote
router management system developed by the DSL Forum). The version we are
using as 3.08 is based on the BT Voyager firmware image I looked at. It may
in fact be BT Voyager-specific, and may in fact not be 3.08, but modified 3.06
and not apply to all 3.08 versions.
Broadcom 3.10 uses an imagetag that is believed to apply to all 3.10 and 3.12
versions, and has been tested on the Tecom GW6200. It is similar to 3.08.
There is a field for vendor-specific information, that at least in some cases
is not optional. It is based on the hexedit of a neufbox4 firmware image, the
information in https://dev.openwrt.org/ticket/4987, and the hexedit of a Tecom
GW6200 image.
Some boards share the same tag format, but require vendor-specific fields in
the board. In that case the tagid is shared, but the filename of the generated
image reflects the router for which the image was created.
router |method| codever |tagid |filename
+----------+------+---------+------+-------------------------------------------
|any |cfe | any |bccfe |openwrt-<board>-<filesystem>-bccfe-cfe.bin
|any |t/ftp | any |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
| |web |3.00-3.06|bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
| |web |3.08 |bc308 |openwrt-<board>-<filesystem>-bc308-cfe.bin
| |web |3.10-3.12|bc310 |openwrt-<board>-<filesystem>-bc310-cfe.bin
|CT536 |web |3.02 |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|CT5621 |web |3.02 |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|GW6000 |web |3.00 |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|USR9108? |web |? |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|USR9108? |web |? |bc310 |openwrt-<board>-<filesystem>-bc310-cfe.bin
|DG834GT |web |3.02 |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|V2500V |web |3.08 |bc308 |openwrt-<board>-<filesystem>-btvgr-cfe.bin
|GW6200 |web |3.10 |bc310 |openwrt-<board>-<filesystem>-gw6200-cfe.bin
|Neufbox4 |web |3.12 |bc310 |openwrt-<board>-<filesystem>-nb4-cfe.bin
|F@ST2404 |web |? |bc300 |openwrt-<board>-<filesystem>-bc300-cfe.bin
|F@ST2404 |web |? |bc310 |openwrt-<board>-<filesystem>-bc310-cfe.bin
|AGVoIP2+Wi|web |alice3.06|ag306 |openwrt-<board>-<filesystem>-agv2+w-cfe.bin
Old imagetag routers
--------------------
Davolink DV201AMR
Redboot routers
---------------
Inventel Livebox
Known router->code versions
---------------------------
Vendor |Model |Code Ver
---------------------------+------------------------------------------+--------
Comtrend |CT-5261 |3.02
Comtrend |CT-536 |3.02
Tecom |GW6000 |3.00
Tecom |GW6200 |3.10
Pirelli |Alice Gate Wi-Fi (+VoIP models?) |ag 3.06
? |TD-88xx |3.06
BT |Voyager V2500V |3.08 (?)
Belkin |F5D7633 |3.10
Neuf ? |Neufbox 4 |3.12
NetGear |DG834GT |3.02
Sagem |F@ST2404 |?
USR |9108 |?

View file

@ -10,6 +10,8 @@ PKG_NAME := firmware-utils
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/kernel.mk
define cc
$(CC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/bin/$(1) src/$(1).c $(2)
endef
@ -18,6 +20,11 @@ define cc2
$(CC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/bin/$(firstword $(1)) $(foreach src,$(1),src/$(src).c) $(2)
endef
define cc3
$(CC) $(HOST_CFLAGS) -I$(CURDIR)/../../target/linux/brcm63xx/files/include/asm-mips/mach-bcm63xx -include endian.h -o $(HOST_BUILD_DIR)/bin/$(1) src/$(1).c $(2)
endef
define Host/Compile
mkdir -p $(HOST_BUILD_DIR)/bin
$(call cc,addpattern)
@ -35,7 +42,7 @@ define Host/Compile
$(call cc,mkcasfw)
$(call cc,mkfwimage,-lz)
$(call cc,mkfwimage2,-lz)
$(call cc,imagetag)
$(call cc3,imagetag)
$(call cc,add_header)
$(call cc,makeamitbin)
$(call cc,encode_crc)

View file

@ -4,6 +4,7 @@
* for more details.
*
* Copyright (C) 2008 Axel Gembe <ago@bastart.eu.org>
* Copyright (C) 2009 Daniel Dickinson <crazycshore@gmail.com>
*/
#include <stdio.h>
@ -15,16 +16,26 @@
#include <sys/stat.h>
#include <netinet/in.h>
#include "bcm_tag.h"
#define IMAGETAG_MAGIC1 "Broadcom Corporatio"
#define IMAGETAG_MAGIC2 "ver. 2.0"
#define IMAGETAG_VER "6"
#define IMAGETAG_DEFAULT_LOADADDR 0x80010000
#define IMAGETAG_CRC_START 0xFFFFFFFF
#define DEFAULT_FW_OFFSET 0x10000
#define DEFAULT_FLASH_START 0xBFC00000
#define DEFAULT_FLASH_BS (64 * 1024)
#define DEADCODE 0xDEADC0DE
union int2char {
uint32_t input;
unsigned char output[4];
};
/* This appears to be necessary due to alignment issues */
#define int2tag(tag, value) intchar.input = htonl(value); \
strncpy(tag, intchar.output, sizeof(union int2char))
/* Kernel header */
struct kernelhdr {
uint32_t loadaddr; /* Kernel load address */
@ -32,36 +43,7 @@ struct kernelhdr {
uint32_t lzmalen; /* Compressed length of the LZMA data that follows */
};
/* Image component */
struct imagecomp {
uint8_t address[12]; /* Address of this component as ASCII */
uint8_t len[10]; /* Length of this component as ASCII */
};
/* Image tag */
struct imagetag {
uint8_t tagver[4]; /* 0 - 3: Version of the tag as ASCII (2) */
uint8_t sig1[20]; /* 4 - 23: BCM_MAGIC_1 */
uint8_t sig2[14]; /* 24 - 37: BCM_MAGIC_2 */
uint8_t chipid[6]; /* 38 - 43: Chip id as ASCII (6345) */
uint8_t boardid[16]; /* 44 - 59: Board id as ASCII (96345GW2, etc...) */
uint8_t bigendian[2]; /* 60 - 61: "1" for big endian, "0" for little endian */
uint8_t imagelen[10]; /* 62 - 71: The length of all data that follows */
struct imagecomp cfe; /* 72 - 93: The offset and length of CFE */
struct imagecomp rootfs; /* 94 - 115: The offset and length of the root file system */
struct imagecomp kernel; /* 116 - 137: The offset and length of the kernel */
uint8_t dualimage[2]; /* 138 - 139: use "0" here */
uint8_t inactive[2]; /* 140 - 141: use "0" here */
uint8_t reserved1[74]; /* 142 - 215: reserved */
uint32_t imagecrc; /* 216 - 219: crc of the images (net byte order) */
// uint8_t reserved2[16]; /* 220 - 235: reserved */
uint8_t reserved2[4]; /* 220 - 223: reserved */
uint8_t wrtrootfsaddr[12]; /* 224 - 235: wrt rootfs address */
uint32_t headercrc; /* 236 - 239: crc starting from sig1 until headercrc (net byte order) */
// uint8_t reserved3[16]; /* 240 - 255: reserved */
uint8_t reserved3[6]; /* 240 - 245: reserved */
uint8_t wrtrootfslen[10]; /* 246 - 255: wrt rootfs lenght */
};
static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS;
static uint32_t crc32tab[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@ -148,24 +130,31 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin,
const char *boardid, const char *chipid, const uint32_t fwaddr,
const uint32_t loadaddr, const uint32_t entry,
const char *ver, const char *magic2, const uint32_t flash_bs,
const char *profile)
const char *tagid, const char *information)
{
struct imagetag tag;
union bcm_tag tag;
struct kernelhdr khdr;
FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile;
size_t kerneloff, kernellen, rootfsoff, rootfslen, read, imagelen, rootfsoffpadlen;
uint8_t readbuf[1024];
uint32_t crc = IMAGETAG_CRC_START;
uint32_t imagecrc = IMAGETAG_CRC_START;
uint32_t kernelcrc = IMAGETAG_CRC_START;
uint32_t rootfscrc = IMAGETAG_CRC_START;
const uint32_t deadcode = htonl(DEADCODE);
union int2char intchar;
memset(&tag, 0, sizeof(struct imagetag));
memset(&tag, 0, sizeof(union bcm_tag));
if (strlen(boardid) >= sizeof(tag.boardid)) {
/* All imagetags have boardid in the same location and of the same
* size, so we just use the bccfe one
*/
if (strlen(boardid) >= sizeof(tag.bccfe.boardid)) {
fprintf(stderr, "Board id is too long!\n");
return 1;
}
if (strlen(chipid) >= sizeof(tag.chipid)) {
/* Likewise chipid */
if (strlen(chipid) >= sizeof(tag.bccfe.chipid)) {
fprintf(stderr, "Chip id is too long!\n");
return 1;
}
@ -201,7 +190,7 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin,
rootfsoff = kerneloff + kernellen;
rootfsoff = (rootfsoff % flash_bs) > 0 ? (((rootfsoff / flash_bs) + 1) * flash_bs) : rootfsoff;
rootfslen = getlen(rootfsfile);
rootfslen = (rootfslen % flash_bs) > 0 ? (((rootfslen / flash_bs) + 1) * flash_bs) : rootfslen;
rootfslen = ( (rootfslen % flash_bs) > 0 ? (((rootfslen / flash_bs) + 1) * flash_bs) : rootfslen );
imagelen = rootfsoff + rootfslen - kerneloff + sizeof(deadcode);
rootfsoffpadlen = rootfsoff - (kerneloff + kernellen);
@ -231,48 +220,199 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin,
/* Choose and compute the CRC32 that should be inserted in the tag */
/* and fill reserved tag following profile specification */
if ( profile && (strcmp(profile, "alice") == 0)) {
crc = compute_crc32(crc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen);
/* Should fill alice_data and put them on reserved1 */
}
else {
if ( tagid && ( (strncmp(tagid, "bccfe", TAGID_LEN) == 0)) || ( strncmp(tagid, "bc300", TAGID_LEN) == 0)) {
/* Compute the crc32 of the entire image (deadC0de included) */
crc = compute_crc32(crc, binfile, kerneloff - fwaddr, imagelen);
imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen);
} else if ( tagid && (strncmp(tagid, "ag306", TAGID_LEN) == 0)) {
/* Compute the crc32 of the kernel and padding between kernel and rootfs) */
kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen);
} else if ( tagid && ( (strncmp(tagid, "bc308", TAGID_LEN) == 0))) {
/* Compute the crc32 of the entire image (deadC0de included) */
imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen);
/* Compute the crc32 of the kernel and padding between kernel and rootfs) */
kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen);
} else if ( tagid && (strncmp(tagid, "bc310", TAGID_LEN) == 0) ) {
/* Compute the crc32 of the entire image (deadC0de included) */
imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen);
/* Compute the crc32 of the kernel and padding between kernel and rootfs) */
kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen);
/* Compute the crc32 of the flashImageStart to rootLength.
* The broadcom firmware assumes the rootfs starts the image,
* therefore uses the rootfs start to determine where to flash
* the image. Since we have the kernel first we have to give
* it the kernel address, but the crc uses the length
* associated with this address, which is added to the kernel
* length to determine the length of image to flash and thus
* needs to be rootfs + deadcode
*/
rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode));
}
/* Close the files */
fclose(kernelfile);
fclose(rootfsfile);
if ( tagid && (strcmp(tagid, "bccfe") == 0)) {
/* Build the tag */
strcpy(tag.tagver, ver);
strncpy(tag.sig1, IMAGETAG_MAGIC1, sizeof(tag.sig1) - 1);
strncpy(tag.sig2, magic2, sizeof(tag.sig2) - 1);
strcpy(tag.chipid, chipid);
strcpy(tag.boardid, boardid);
strcpy(tag.bigendian, "1");
sprintf(tag.imagelen, "%lu", imagelen);
strncpy(tag.bccfe.tagVersion, ver, TAGVER_LEN);
strncpy(tag.bccfe.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bccfe.sig_1) - 1);
strncpy(tag.bccfe.sig_2, magic2, sizeof(tag.bccfe.sig_2) - 1);
strcpy(tag.bccfe.chipid, chipid);
strcpy(tag.bccfe.boardid, boardid);
strcpy(tag.bccfe.big_endian, "1");
sprintf(tag.bccfe.totalLength, "%lu", imagelen);
/* We don't include CFE */
strcpy(tag.cfe.address, "0");
strcpy(tag.cfe.len, "0");
strcpy(tag.bccfe.cfeAddress, "0");
strcpy(tag.bccfe.cfeLength, "0");
if (kernelfile) {
sprintf(tag.kernel.address, "%lu", kerneloff);
sprintf(tag.kernel.len, "%lu", kernellen + rootfsoffpadlen);
sprintf(tag.bccfe.kernelAddress, "%lu", kerneloff);
sprintf(tag.bccfe.kernelLength, "%lu", kernellen + rootfsoffpadlen);
}
if (rootfsfile) {
sprintf(tag.rootfs.address, "%lu", kerneloff);
sprintf(tag.rootfs.len, "%lu", rootfslen + sizeof(deadcode));
sprintf(tag.wrtrootfsaddr, "%lu", rootfsoff);
sprintf(tag.wrtrootfslen, "%lu", rootfslen);
sprintf(tag.bccfe.rootAddress, "%lu", rootfsoff);
sprintf(tag.bccfe.rootLength, "%lu", rootfslen);
}
tag.imagecrc = htonl(crc);
tag.headercrc = htonl(crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
strncpy(tag.bccfe.tagId, "bccfe", TAGID_LEN);
int2tag(tag.bccfe.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bccfe.tagId[0]), TAGID_LEN));
int2tag(tag.bccfe.imageCRC, imagecrc);
int2tag(tag.bccfe.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
} else if ( tagid && (strcmp(tagid, "bc300") == 0)) {
/* Build the tag */
strncpy(tag.bc300.tagVersion, ver, TAGVER_LEN);
strncpy(tag.bc300.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc300.sig_1) - 1);
strncpy(tag.bc300.sig_2, magic2, sizeof(tag.bc300.sig_2) - 1);
strcpy(tag.bc300.chipid, chipid);
strcpy(tag.bc300.boardid, boardid);
strcpy(tag.bc300.big_endian, "1");
sprintf(tag.bc300.totalLength, "%lu", imagelen);
/* We don't include CFE */
strcpy(tag.bc300.cfeAddress, "0");
strcpy(tag.bc300.cfeLength, "0");
if (kernelfile) {
sprintf(tag.bc300.kernelAddress, "%lu", kerneloff);
sprintf(tag.bc300.kernelLength, "%lu", kernellen + rootfsoffpadlen);
}
if (rootfsfile) {
sprintf(tag.bc300.flashImageStart, "%lu", kerneloff);
sprintf(tag.bc300.flashRootLength, "%lu", rootfslen + sizeof(deadcode));
sprintf(tag.bc300.rootAddress, "%lu", rootfsoff);
sprintf(tag.bc300.rootLength, "%lu", rootfslen);
}
strncpy(tag.bc300.tagId, "bc300", TAGID_LEN);
int2tag(tag.bc300.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc300.tagId[0]), TAGID_LEN));
int2tag(tag.bc300.imageCRC, imagecrc);
int2tag(tag.bc300.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
} else if ( tagid && (strcmp(tagid, "ag306") == 0)) {
/* Build the tag */
strncpy(tag.ag306.tagVersion, ver, TAGVER_LEN);
strncpy(tag.ag306.sig_1, IMAGETAG_MAGIC1, sizeof(tag.ag306.sig_1) - 1);
strncpy(tag.ag306.sig_2, magic2, sizeof(tag.ag306.sig_2) - 1);
strcpy(tag.ag306.chipid, chipid);
strcpy(tag.ag306.boardid, boardid);
strcpy(tag.ag306.big_endian, "1");
sprintf(tag.ag306.totalLength, "%lu", imagelen);
/* We don't include CFE */
strcpy(tag.ag306.cfeAddress, "0");
strcpy(tag.ag306.cfeLength, "0");
if (kernelfile) {
sprintf(tag.ag306.kernelAddress, "%lu", kerneloff);
sprintf(tag.ag306.kernelLength, "%lu", kernellen + rootfsoffpadlen);
}
if (rootfsfile) {
sprintf(tag.ag306.flashImageStart, "%lu", kerneloff);
sprintf(tag.ag306.flashRootLength, "%lu", rootfslen + sizeof(deadcode));
sprintf(tag.ag306.rootAddress, "%lu", rootfsoff);
sprintf(tag.ag306.rootLength, "%lu", rootfslen);
}
strncpy(tag.ag306.tagId, "ag306", TAGID_LEN);
int2tag(tag.ag306.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.ag306.tagId[0]), TAGID_LEN));
int2tag(tag.ag306.kernelCRC, kernelcrc);
int2tag(tag.ag306.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
} else if ( tagid && (strcmp(tagid, "bc308") == 0)) {
/* Build the tag */
strncpy(tag.bc308.tagVersion, ver, TAGVER_LEN);
strncpy(tag.bc308.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc308.sig_1) - 1);
strncpy(tag.bc308.sig_2, magic2, sizeof(tag.bc308.sig_2) - 1);
strcpy(tag.bc308.chipid, chipid);
strcpy(tag.bc308.boardid, boardid);
strcpy(tag.bc308.big_endian, "1");
sprintf(tag.bc308.totalLength, "%lu", imagelen);
/* We don't include CFE */
strcpy(tag.bc308.cfeAddress, "0");
strcpy(tag.bc308.cfeLength, "0");
if (kernelfile) {
sprintf(tag.bc308.kernelAddress, "%lu", kerneloff);
sprintf(tag.bc308.kernelLength, "%lu", kernellen + rootfsoffpadlen);
}
if (rootfsfile) {
sprintf(tag.bc308.flashImageStart, "%lu", kerneloff);
sprintf(tag.bc308.flashRootLength, "%lu", rootfslen + sizeof(deadcode));
sprintf(tag.bc308.rootAddress, "%lu", rootfsoff);
sprintf(tag.bc308.rootLength, "%lu", rootfslen);
}
strncpy(tag.bc308.tagId, "bc308", TAGID_LEN);
strcpy(tag.bc308.flashLayoutVer, "5"); // This is needed at least for BT Voyager
int2tag(tag.bc308.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc308.tagId[0]), TAGID_LEN));
int2tag(tag.bc308.imageCRC, imagecrc);
int2tag(tag.bc308.kernelCRC, kernelcrc);
int2tag(tag.bc308.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
} else if ( tagid && (strcmp(tagid, "bc310") == 0)) {
/* Build the tag */
strncpy(tag.bc310.tagVersion, ver, TAGVER_LEN);
strncpy(tag.bc310.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc310.sig_1) - 1);
strncpy(tag.bc310.sig_2, magic2, sizeof(tag.bc310.sig_2) - 1);
strcpy(tag.bc310.chipid, chipid);
strcpy(tag.bc310.boardid, boardid);
strcpy(tag.bc310.big_endian, "1");
sprintf(tag.bc310.totalLength, "%lu", imagelen);
/* We don't include CFE */
strcpy(tag.bc310.cfeAddress, "0");
strcpy(tag.bc310.cfeLength, "0");
if (kernelfile) {
sprintf(tag.bc310.kernelAddress, "%lu", kerneloff);
sprintf(tag.bc310.kernelLength, "%lu", kernellen + rootfsoffpadlen);
}
if (rootfsfile) {
sprintf(tag.bc310.flashImageStart, "%lu", kerneloff);
sprintf(tag.bc310.flashRootLength, "%lu", rootfslen + sizeof(deadcode));
sprintf(tag.bc310.rootAddress, "%lu", rootfsoff);
sprintf(tag.bc310.rootLength, "%lu", rootfslen);
}
strncpy(tag.bc310.tagId, "bc310", TAGID_LEN);
if (information) {
strncpy(tag.bc310.information1, information, TAGINFO_LEN);
}
int2tag(tag.bc310.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc310.tagId[0]), TAGID_LEN));
int2tag(tag.bc310.imageCRC, imagecrc);
int2tag(tag.bc310.kernelCRC, kernelcrc);
int2tag(tag.bc310.rootfsCRC, rootfscrc);
int2tag(tag.bc310.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
}
fseek(binfile, 0L, SEEK_SET);
fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile);
@ -284,12 +424,13 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin,
int main(int argc, char **argv)
{
int c;
char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *profile;
int c, i;
char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *information;
uint32_t flashstart, fwoffset, loadaddr, entry;
uint32_t fwaddr, flash_bs;
int tagidfound = 0;
kernel = rootfs = bin = boardid = chipid = magic2 = ver = profile = NULL;
kernel = rootfs = bin = boardid = chipid = magic2 = ver = tagid = information = NULL;
entry = 0;
flashstart = DEFAULT_FLASH_START;
@ -297,10 +438,11 @@ int main(int argc, char **argv)
loadaddr = IMAGETAG_DEFAULT_LOADADDR;
flash_bs = DEFAULT_FLASH_BS;
printf("Broadcom image tagger - v0.1.2\n");
printf("Broadcom image tagger - v0.2.0\n");
printf("Copyright (C) 2008 Axel Gembe\n");
printf("Copyright (C) 2009 Daniel Dickinson\n");
while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:p:")) != -1) {
while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:t:d:")) != -1) {
switch (c) {
case 'i':
kernel = optarg;
@ -338,8 +480,11 @@ int main(int argc, char **argv)
case 'e':
entry = strtoul(optarg, NULL, 16);
break;
case 'p':
profile = optarg;
case 't':
tagid = optarg;
break;
case 'd':
information = optarg;
break;
case 'h':
default:
@ -356,7 +501,8 @@ int main(int argc, char **argv)
fprintf(stderr, " -k <flash_bs> - flash erase block size\n");
fprintf(stderr, " -l <loadaddr> - Address where the kernel expects to be loaded (defaults to 0x80010000)\n");
fprintf(stderr, " -e <entry> - Address where the kernel entry point will end up\n");
fprintf(stderr, " -p <profile> - Specify profile for particular devices, use 'list' to see available devices\n");
fprintf(stderr, " -t <tagid> - type if imagetag to create, use 'list' to see available choices");
fprintf(stderr, " -d <information> - vendor specific information, for those that need it");
fprintf(stderr, " -h - Displays this text\n\n");
return 1;
}
@ -372,20 +518,37 @@ int main(int argc, char **argv)
return 1;
}
if (profile && (strcmp(profile, "list") == 0)) {
tagidfound = 0;
if (!tagid) {
fprintf(stderr, "You must specify a tagid (-t)\n");
} else {
if (strncmp(tagid, "list", 4) == 0) {
fprintf(stderr, "\n----------------------------------------\n");
fprintf(stderr, "\tAvailable Profiles:");
fprintf(stderr, "\tAvailable tagId:");
fprintf(stderr, "\n\n");
fprintf(stderr, "\t'alice'\tALICE GATE VoIP 2 Plus Wi-Fi Business");
for (i = 0; i < NUM_TAGID; i++) {
fprintf(stderr, "\t%s\t%s", tagidtab[i].tagid, tagidtab[i].tagiddesc);
}
fprintf(stderr, "\n----------------------------------------\n");
return 0;
}
}
/* If the profile increase should found another way of testing the validity */
if (profile && !(strcmp(profile, "alice") == 0)) {
fprintf(stderr, "You specified an inexistent profile %s, see the list of availables options\n", profile);
if (tagid) {
for(i = 0; i < NUM_TAGID; i++) {
if (strncmp(tagid, tagidtab[i].tagid, TAGID_LEN) == 0) {
tagidfound = 1;
break;
}
}
if (!tagidfound) {
if (tagid) {
fprintf(stderr, "The tagid you selected '%s' does't exist.\n", tagid);
}
fprintf(stderr, "Use -t list to see the list of available ids");
return 1;
}
}
/* Fallback to defaults */
@ -410,5 +573,5 @@ int main(int argc, char **argv)
}
return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, profile);
return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, tagid, information);
}