1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 by Jörg Hohensohn
12 * Autoring tool for the firmware image to be programmed into Flash ROM
13 * It composes the flash content with header, bootloader and image(s)
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
29 #define UINT8 unsigned char
30 #define UINT16 unsigned short
31 #define UINT32 unsigned long
36 // size of one flash sector, the granularity with which it can be erased
37 #define SECTORSIZE 4096
39 #define BOOTLOAD_DEST 0x0FFFF500 // for the "normal" one
40 #define FLASH_START 0x02000000
41 #define BOOTLOAD_SCR 0x02000100
42 #define ROCKBOX_DEST 0x09000000
43 #define ROCKBOX_EXEC 0x09000200
46 // place a 32 bit value into memory, big endian
47 void Write32(UINT8
* pByte
, UINT32 value
)
49 pByte
[0] = (UINT8
)(value
>> 24);
50 pByte
[1] = (UINT8
)(value
>> 16);
51 pByte
[2] = (UINT8
)(value
>> 8);
52 pByte
[3] = (UINT8
)(value
);
56 // read a 32 bit value from memory, big endian
57 UINT32
Read32(UINT8
* pByte
)
61 value
|= (UINT32
)pByte
[0] << 24;
62 value
|= (UINT32
)pByte
[1] << 16;
63 value
|= (UINT32
)pByte
[2] << 8;
64 value
|= (UINT32
)pByte
[3];
70 UINT32
CalcCRC32 (const UINT8
* buf
, UINT32 len
)
72 static const UINT32 crc_table
[256] =
73 { // CRC32 lookup table for polynomial 0x04C11DB7
74 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
75 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
76 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7,
77 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
78 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3,
79 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
80 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
81 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
82 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB,
83 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
84 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
85 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
86 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4,
87 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
88 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08,
89 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
90 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC,
91 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
92 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050,
93 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
94 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
95 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
96 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1,
97 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
98 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5,
99 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
100 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9,
101 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
102 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD,
103 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
104 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
105 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
106 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2,
107 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
108 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
109 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
110 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A,
111 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
112 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676,
113 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
114 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
115 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
116 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
119 UINT32 crc
= 0xffffffff;
121 for (i
= 0; i
< len
; i
++)
122 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 24) ^ *buf
++) & 0xFF];
128 UINT32
PlaceImage(char* filename
, UINT32 pos
, UINT8
* pFirmware
, UINT32 limit
)
134 UINT32 load_addr
= ROCKBOX_DEST
, exec_addr
= ROCKBOX_EXEC
; // defaults
136 // magic file header for compressed files
137 static const UINT8 magic
[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a };
138 UINT8 ucl_header
[26];
140 pFile
= fopen(filename
, "rb"); // open the current image
143 printf("Image file %s not found!\n", filename
);
147 fseek(pFile
, 0, SEEK_END
);
149 fseek(pFile
, 0, SEEK_SET
);
151 // determine if compressed
152 flags
= 0x00000000; // default: flags for uncompressed
153 fread(ucl_header
, 1, sizeof(ucl_header
), pFile
);
154 if (memcmp(magic
, ucl_header
, sizeof(magic
)) == 0)
156 if (ucl_header
[12] != 0x2E // check algorithm
157 && ucl_header
[12] != 0x2B) // or uncompressed
159 printf("UCL compressed files must use algorithm 2e, not %d\n", ucl_header
[12]);
160 printf("Generate with: uclpack --best --2e rockbox.bin %s\n", filename
);
164 size
= Read32(ucl_header
+ 22); // compressed size
165 if (Read32(ucl_header
+ 18) > size
) // compare with uncompressed size
167 flags
= 0x00000001; // flags for UCL compressed
170 if (ucl_header
[12] == 0x2B) // uncompressed means "ROMbox", for direct flash execution
174 fread(start_addr
, 1, sizeof(start_addr
), pFile
); // read the link address from image
175 fread(reset_vec
, 1, sizeof(reset_vec
), pFile
); // read the reset vector from image
176 fseek(pFile
, 0-sizeof(start_addr
)-sizeof(reset_vec
), SEEK_CUR
); // wind back
177 load_addr
= Read32(start_addr
);
178 if (load_addr
!= FLASH_START
+ pos
+ 16) // behind 16 byte header
180 printf("Error: Rombox .ucl file is linked to 0x%08X instead of 0x%08X\n", load_addr
, FLASH_START
+ pos
+ 16);
183 exec_addr
= Read32(reset_vec
);
188 fseek(pFile
, 0, SEEK_SET
); // go back
191 if (pos
+ 16 + size
> limit
) // enough space for all that?
193 printf("Exceeding maximum image size %d\n", limit
);
198 align
= (pos
+ 16 + size
+ SECTORSIZE
-1) & ~(SECTORSIZE
-1); // round up to next flash sector
199 Write32(pFirmware
+ pos
, load_addr
); // load address
200 Write32(pFirmware
+ pos
+ 4, align
- (pos
+ 16)); // image size
201 Write32(pFirmware
+ pos
+ 8, exec_addr
); // execution address
202 Write32(pFirmware
+ pos
+ 12, flags
); // compressed or not
206 read
= fread(pFirmware
+ pos
, 1, size
, pFile
);
209 printf("Read error, expecting %d bytes, got only %d\n", size
, read
);
220 int main(int argc
, char* argv
[])
222 static UINT8 aFirmware
[512*1024]; // maximum with exchanged chip
224 UINT32 size
; // size of loaded item
225 UINT32 pos
; // current position in firmware
226 UINT32 crc32
; // checksum of "payload"
227 BOOL hasBootRom
; // flag if regular boot ROM or directly starts from flash
228 UINT32 template_F8
, template_FC
; // my platform ID, mask and version
235 printf("make_firmware <output> <template.bin> <bootloader.ajz> <image1.ucl> {image2.ucl}\n");
236 printf("<template.bin> is the original firmware from your box\n");
237 printf("<bootloader.ajz> is the scrambled bootloader\n");
238 printf("<image1.ucl> is the first image, compressed (recommended) or uncompressed\n");
239 printf("<image1.ucl> is the second image, compressed (recommended) or uncompressed\n");
240 printf("More images may follow, but keep the flash size in mind!\n");
241 printf("Compression must be UCL, algorithm 2e.\n");
242 printf("Generated with: uclpack --best --2e rockbox.bin imageN.ucl\n");
246 memset(aFirmware
, 0xFF, sizeof(aFirmware
));
248 /******* process template *******/
250 pFile
= fopen(argv
[2], "rb"); // open the template
253 printf("Template file %s not found!\n", argv
[2]);
256 size
= fread(aFirmware
, 1, 256, pFile
); // need only the header
258 if (size
< 256) // need at least the firmware header
260 printf("Template file %s too small, need at least the header!\n", argv
[2]);
264 if (strncmp(aFirmware
, "ARCH", 4) == 0)
267 pos
= 256; // place bootloader after this "boot block"
269 else if (Read32(aFirmware
) == 0x0200)
272 pos
= 0; // directly start with the bootloader
273 template_F8
= Read32(aFirmware
+ 0xF8); // my platform ID and future info
274 template_FC
= Read32(aFirmware
+ 0xFC); // use mask+version from template
278 printf("Template file %s invalid!\n", argv
[2]);
282 /******* process bootloader *******/
284 pFile
= fopen(argv
[3], "rb"); // open the bootloader
287 printf("Bootloader file %s not found!\n", argv
[3]);
290 if (hasBootRom
&& fseek(pFile
, 6, SEEK_SET
)) // skip the ajz header
292 printf("Bootloader file %s too short!\n", argv
[3]);
296 // place bootloader after header
297 size
= fread(aFirmware
+ pos
, 1, sizeof(aFirmware
) - pos
, pFile
);
302 Write32(aFirmware
+ 4, BOOTLOAD_DEST
); // boot code destination address
304 for (i
=0x08; i
<=0x28; i
+=8)
306 Write32(aFirmware
+ i
, BOOTLOAD_SCR
); // boot code source address
307 Write32(aFirmware
+ i
+ 4, size
); // boot code size
312 Write32(aFirmware
+ 0xF8, template_F8
); // values from template
313 Write32(aFirmware
+ 0xFC, template_FC
); // mask and version
316 size
= (size
+ 3) & ~3; // make shure it's 32 bit aligned
317 pos
+= size
; // prepare position for first image
319 /******* process images *******/
320 for (i
= 4; i
< argc
; i
++)
322 pos
= PlaceImage(argv
[i
], pos
, aFirmware
, sizeof(aFirmware
));
325 { // not the last: round up to next flash sector
326 pos
= (pos
+ SECTORSIZE
-1) & ~(SECTORSIZE
-1);
331 /******* append CRC32 checksum *******/
332 crc32
= CalcCRC32(aFirmware
, pos
);
333 Write32(aFirmware
+ pos
, crc32
);
334 pos
+= sizeof(crc32
); // 4 bytes
337 /******* save result to output file *******/
339 pFile
= fopen(argv
[1], "wb"); // open the output file
342 printf("Output file %s cannot be created!\n", argv
[1]);
345 size
= fwrite(aFirmware
, 1, pos
, pFile
);
350 printf("Error writing %d bytes to output file %s!\n", pos
, argv
[1]);
354 printf("Firmware file generated with %d bytes.\n", pos
);