diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/AMS/hacking/mkamsboot.c | 88 | ||||
-rw-r--r-- | utils/AMS/hacking/test.S | 21 |
2 files changed, 52 insertions, 57 deletions
diff --git a/utils/AMS/hacking/mkamsboot.c b/utils/AMS/hacking/mkamsboot.c index 47738ebdde..52ead58b69 100644 --- a/utils/AMS/hacking/mkamsboot.c +++ b/utils/AMS/hacking/mkamsboot.c | |||
@@ -26,34 +26,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | |||
26 | 26 | ||
27 | Insert a Rockbox bootloader into an AMS original firmware file. | 27 | Insert a Rockbox bootloader into an AMS original firmware file. |
28 | 28 | ||
29 | We replace the main firmware block (bytes 0x400..padded_firmware_size+0x400) | 29 | We replace the main firmware block (bytes 0x400..0x400+firmware_size) |
30 | with the following: | 30 | as follows: |
31 | 31 | ||
32 | Bytes 0..(firmware_size-ucl_size) - Our bootloader code | 32 | |
33 | Bytes (firmware_size-ucl_size)..firmware_size - UCL compressed OF image | 33 | --------------------- 0x0 |
34 | Bytes firmware_size..padded_firmware_size - UCL decompress function | 34 | | | |
35 | 35 | | Rockbox bootloader | | |
36 | mkamsboot writes the following values at offsets into our bootloader code: | 36 | | | |
37 | 37 | |---------------------| | |
38 | 0x20 - Entry point (plus 1 - for thumb mode) of the ucl_unpack function | 38 | | EMPTY SPACE | |
39 | 0x24 - Location of the UCL compressed version of the original firmware block | 39 | |---------------------| |
40 | 40 | | ucl unpack function | | |
41 | mkamsboot then corrects the length (to include the UCL decompress | 41 | |---------------------| |
42 | function) and checksum in the main firmware headers (both copies), | 42 | | | |
43 | creating a new legal firmware file which can be installed on the | 43 | | compressed OF image | |
44 | device. | 44 | | | |
45 | | | | ||
46 | --------------------- | ||
47 | |||
48 | This entire block fits into the space previously occupied by the main | ||
49 | firmware block, and gives about 40KB of space to store the Rockbox | ||
50 | bootloader. This could be increased if we also UCL compress the | ||
51 | Rockbox bootloader. | ||
52 | |||
53 | mkamsboot then corrects the checksums and writes a new legal firmware | ||
54 | file which can be installed on the device. | ||
45 | 55 | ||
46 | Our bootloader first checks for the "dual-boot" keypress, and then either: | 56 | Our bootloader first checks for the "dual-boot" keypress, and then either: |
47 | 57 | ||
48 | a) Branches to the ucl_unpack function, which will then branch to 0x0 after | 58 | a) Copies the ucl unpack function and compressed OF image to an unused |
49 | decompressing the OF. | 59 | part of RAM and then branches to the ucl_unpack function, which |
60 | will then branch to 0x0 after decompressing the OF to that location. | ||
50 | 61 | ||
51 | b) Continues running with our test code | 62 | b) Continues running with our test code |
52 | 63 | ||
53 | This method uses no RAM outside the padded area of the original | ||
54 | firmware block - the UCL compression can happen in-place when the | ||
55 | compressed image is stored at the end of the destination buffer. | ||
56 | |||
57 | */ | 64 | */ |
58 | 65 | ||
59 | 66 | ||
@@ -142,6 +149,7 @@ int main(int argc, char* argv[]) | |||
142 | uint32_t firmware_paddedsize; | 149 | uint32_t firmware_paddedsize; |
143 | uint32_t bootloader_size; | 150 | uint32_t bootloader_size; |
144 | uint32_t ucl_size; | 151 | uint32_t ucl_size; |
152 | uint32_t ucl_paddedsize; | ||
145 | uint32_t uclunpack_size; | 153 | uint32_t uclunpack_size; |
146 | uint32_t sum,filesum; | 154 | uint32_t sum,filesum; |
147 | uint32_t i; | 155 | uint32_t i; |
@@ -204,6 +212,7 @@ int main(int argc, char* argv[]) | |||
204 | return 1; | 212 | return 1; |
205 | } | 213 | } |
206 | ucl_size = get_uint32be(&uclheader[22]) + 8; | 214 | ucl_size = get_uint32be(&uclheader[22]) + 8; |
215 | ucl_paddedsize = (ucl_size + 3) & ~0x3; | ||
207 | 216 | ||
208 | if (ucl_size + 26 > (unsigned)filesize(fducl)) { | 217 | if (ucl_size + 26 > (unsigned)filesize(fducl)) { |
209 | fprintf(stderr, "[ERR] Size mismatch in UCL file\n"); | 218 | fprintf(stderr, "[ERR] Size mismatch in UCL file\n"); |
@@ -246,26 +255,15 @@ int main(int argc, char* argv[]) | |||
246 | fprintf(stderr,"Original firmware size - %d bytes\n",firmware_size); | 255 | fprintf(stderr,"Original firmware size - %d bytes\n",firmware_size); |
247 | fprintf(stderr,"Padded firmware size - %d bytes\n",firmware_paddedsize); | 256 | fprintf(stderr,"Padded firmware size - %d bytes\n",firmware_paddedsize); |
248 | fprintf(stderr,"Bootloader size - %d bytes\n",bootloader_size); | 257 | fprintf(stderr,"Bootloader size - %d bytes\n",bootloader_size); |
249 | fprintf(stderr,"UCL image size - %d bytes\n",ucl_size); | 258 | fprintf(stderr,"UCL image size - %d bytes (%d bytes padded)\n",ucl_size,ucl_paddedsize); |
250 | fprintf(stderr,"UCL unpack function size - %d bytes\n",uclunpack_size); | 259 | fprintf(stderr,"UCL unpack function size - %d bytes\n",uclunpack_size); |
251 | fprintf(stderr,"Original total size of firmware - %d bytes\n",(int)len); | 260 | fprintf(stderr,"Original total size of firmware - %d bytes\n",(int)len); |
252 | 261 | ||
253 | /* Check we have room for our bootloader - in the future, we could UCL | 262 | /* Check we have room for our bootloader - in the future, we could UCL |
254 | pack this image as well if we need to. */ | 263 | pack this image as well if we need to. */ |
255 | if (bootloader_size > (firmware_size - ucl_size)) { | 264 | if (bootloader_size > (firmware_size - ucl_paddedsize - uclunpack_size)) { |
256 | fprintf(stderr,"[ERR] Bootloader too large (%d bytes, %d available)\n", | 265 | fprintf(stderr,"[ERR] Bootloader too large (%d bytes, %d available)\n", |
257 | bootloader_size, firmware_size - ucl_size); | 266 | bootloader_size, firmware_size - ucl_paddedsize - uclunpack_size); |
258 | return 1; | ||
259 | } | ||
260 | |||
261 | /* Check we have enough room for the UCL unpack function. This | ||
262 | needs to be outside the firmware block, so if we wanted to | ||
263 | support every firmware version, we could store this function in | ||
264 | the main firmware block, and then copy it to an unused part of | ||
265 | RAM. */ | ||
266 | if (uclunpack_size > (firmware_paddedsize - firmware_size)) { | ||
267 | fprintf(stderr,"[ERR] UCL unpack function too large (%d bytes, %d available)\n", | ||
268 | uclunpack_size, firmware_paddedsize - firmware_size); | ||
269 | return 1; | 267 | return 1; |
270 | } | 268 | } |
271 | 269 | ||
@@ -283,7 +281,7 @@ int main(int argc, char* argv[]) | |||
283 | 281 | ||
284 | /* Locate the compressed image of the original firmware block at the end | 282 | /* Locate the compressed image of the original firmware block at the end |
285 | of the firmware block */ | 283 | of the firmware block */ |
286 | n = read(fducl, buf + 0x400 + firmware_size - ucl_size, ucl_size); | 284 | n = read(fducl, buf + 0x400 + firmware_size - ucl_paddedsize, ucl_size); |
287 | 285 | ||
288 | if (n != ucl_size) { | 286 | if (n != ucl_size) { |
289 | fprintf(stderr,"[ERR] Could not load ucl file\n"); | 287 | fprintf(stderr,"[ERR] Could not load ucl file\n"); |
@@ -292,8 +290,8 @@ int main(int argc, char* argv[]) | |||
292 | close(fducl); | 290 | close(fducl); |
293 | 291 | ||
294 | 292 | ||
295 | /* Locate our UCL unpack function in the padding after the firmware block */ | 293 | /* Locate our UCL unpack function before copy of the compressed firmware */ |
296 | n = read(fduclunpack, buf + 0x400 + firmware_size, uclunpack_size); | 294 | n = read(fduclunpack, buf + 0x400 + firmware_size - ucl_paddedsize - uclunpack_size, uclunpack_size); |
297 | 295 | ||
298 | if (n != uclunpack_size) { | 296 | if (n != uclunpack_size) { |
299 | fprintf(stderr,"[ERR] Could not load uclunpack file\n"); | 297 | fprintf(stderr,"[ERR] Could not load uclunpack file\n"); |
@@ -301,20 +299,18 @@ int main(int argc, char* argv[]) | |||
301 | } | 299 | } |
302 | close(fduclunpack); | 300 | close(fduclunpack); |
303 | 301 | ||
304 | put_uint32le(&buf[0x420], firmware_size + 1); /* UCL unpack entry point */ | 302 | put_uint32le(&buf[0x420], 0x40000 - ucl_paddedsize - uclunpack_size + 1); /* UCL unpack entry point */ |
305 | put_uint32le(&buf[0x424], firmware_size - ucl_size); /* Location of OF */ | 303 | put_uint32le(&buf[0x424], 0x40000 - ucl_paddedsize); /* Location of OF */ |
306 | put_uint32le(&buf[0x428], ucl_size); /* Size of UCL image */ | 304 | put_uint32le(&buf[0x428], ucl_size); /* Size of UCL image */ |
305 | put_uint32le(&buf[0x42c], firmware_size - uclunpack_size - ucl_paddedsize); /* Start of data to copy */ | ||
306 | put_uint32le(&buf[0x430], uclunpack_size + ucl_paddedsize); /* Size of data to copy */ | ||
307 | 307 | ||
308 | /* Update checksum */ | 308 | /* Update checksum */ |
309 | sum = calc_checksum(buf + 0x400,firmware_size + uclunpack_size); | 309 | sum = calc_checksum(buf + 0x400,firmware_size); |
310 | 310 | ||
311 | put_uint32le(&buf[0x04], sum); | 311 | put_uint32le(&buf[0x04], sum); |
312 | put_uint32le(&buf[0x204], sum); | 312 | put_uint32le(&buf[0x204], sum); |
313 | 313 | ||
314 | /* Update firmware size */ | ||
315 | put_uint32le(&buf[0x0c], firmware_size + uclunpack_size); | ||
316 | put_uint32le(&buf[0x20c], firmware_size + uclunpack_size); | ||
317 | |||
318 | /* Update the whole-file checksum */ | 314 | /* Update the whole-file checksum */ |
319 | filesum = 0; | 315 | filesum = 0; |
320 | for (i=0;i < (unsigned)len - 4; i+=4) | 316 | for (i=0;i < (unsigned)len - 4; i+=4) |
diff --git a/utils/AMS/hacking/test.S b/utils/AMS/hacking/test.S index 79d23deb6a..a4757b44ce 100644 --- a/utils/AMS/hacking/test.S +++ b/utils/AMS/hacking/test.S | |||
@@ -16,10 +16,11 @@ | |||
16 | .word 0 | 16 | .word 0 |
17 | 17 | ||
18 | /* These values are filled in by mkamsboot - don't move them from offset 0x20 */ | 18 | /* These values are filled in by mkamsboot - don't move them from offset 0x20 */ |
19 | ucl_unpack: .word 0 /* Entry point (plus 1 - for thumb) of ucl_unpack */ | 19 | ucl_unpack: .word 0 /* Entry point (plus 1 - for thumb) of ucl_unpack after copy*/ |
20 | ucl_start: .word 0 /* Start of the ucl-compressed OF image */ | 20 | ucl_start: .word 0 /* Start of the ucl-compressed OF image after copy */ |
21 | ucl_size: .word 0 /* Length in bytes of the compressed OF image */ | 21 | ucl_size: .word 0 /* Length in bytes of the compressed OF image */ |
22 | 22 | copy_start: .word 0 /* Start of the copy of the ucl_unpack function */ | |
23 | copy_size: .word 0 /* uclunpack_size + ucl_paddedsize */ | ||
23 | 24 | ||
24 | start: | 25 | start: |
25 | /* A delay loop - just to prove we're running */ | 26 | /* A delay loop - just to prove we're running */ |
@@ -29,25 +30,23 @@ loop: subs r1, r1, #1 | |||
29 | 30 | ||
30 | /* First copy the compressed firmware to unused RAM */ | 31 | /* First copy the compressed firmware to unused RAM */ |
31 | 32 | ||
32 | ldr r0, ucl_start /* Source */ | 33 | ldr r0, copy_start /* Source */ |
33 | ldr r1, ucl_size /* Source length */ | 34 | ldr r1, copy_size /* Source length */ |
34 | 35 | ||
35 | mov r2, #0x40000 /* Destination end */ | 36 | mov r2, #0x40000 /* Destination end */ |
36 | sub r2, r2, r1 | 37 | sub r2, r2, r1 |
37 | 38 | ||
38 | memcpy: | 39 | memcpy: |
39 | ldrb r3, [r0] | 40 | ldrb r3, [r0], #1 |
40 | strb r3, [r2] | 41 | strb r3, [r2], #1 |
41 | adds r0, r0, #1 | ||
42 | adds r2, r2, #1 | ||
43 | cmp r2, #0x40000 /* Stop when we reached dest_end */ | 42 | cmp r2, #0x40000 /* Stop when we reached dest_end */ |
44 | bne memcpy | 43 | bne memcpy |
45 | 44 | ||
46 | sub r0, r2, r1 /* Point to the compressed firmware */ | ||
47 | |||
48 | /* Call the ucl decompress function, which will branch to 0x0 */ | 45 | /* Call the ucl decompress function, which will branch to 0x0 */ |
49 | /* on completion */ | 46 | /* on completion */ |
50 | 47 | ||
48 | ldr r0, ucl_start /* Address of compressed image */ | ||
49 | ldr r1, ucl_size /* Compressed size */ | ||
51 | mov r2, #0 /* Destination */ | 50 | mov r2, #0 /* Destination */ |
52 | 51 | ||
53 | ldr r3, ucl_unpack | 52 | ldr r3, ucl_unpack |