diff options
author | Dave Chapman <dave@dchapman.com> | 2007-11-27 01:25:11 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2007-11-27 01:25:11 +0000 |
commit | 4fb825eed983c6fb3d76b3efbc61014f69969a87 (patch) | |
tree | 9a243b7006718cc661ff9019c5342a762c94efdc | |
parent | a8b388fb86096b265780ac682adddcec22005f79 (diff) | |
download | rockbox-4fb825eed983c6fb3d76b3efbc61014f69969a87.tar.gz rockbox-4fb825eed983c6fb3d76b3efbc61014f69969a87.zip |
Make the Gigabeat-S bootloader dual-boot. The hold switch is used to choose what to boot - because it is a simple GPIO test.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15828 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/boot.lds | 2 | ||||
-rw-r--r-- | tools/mknkboot.c | 58 |
2 files changed, 53 insertions, 7 deletions
diff --git a/firmware/boot.lds b/firmware/boot.lds index d4c72b5846..108660f2af 100644 --- a/firmware/boot.lds +++ b/firmware/boot.lds | |||
@@ -292,7 +292,7 @@ SECTIONS | |||
292 | } | 292 | } |
293 | #elif (CONFIG_CPU==IMX31L) | 293 | #elif (CONFIG_CPU==IMX31L) |
294 | { | 294 | { |
295 | . = 0x88201000; | 295 | . = 0x8a000000; |
296 | .vectors : | 296 | .vectors : |
297 | { | 297 | { |
298 | KEEP(*(.vectors*)); | 298 | KEEP(*(.vectors*)); |
diff --git a/tools/mknkboot.c b/tools/mknkboot.c index c5e89f6834..dfb3c99767 100644 --- a/tools/mknkboot.c +++ b/tools/mknkboot.c | |||
@@ -27,6 +27,12 @@ | |||
27 | #include <unistd.h> | 27 | #include <unistd.h> |
28 | #include <inttypes.h> | 28 | #include <inttypes.h> |
29 | 29 | ||
30 | /* New entry point for nk.bin - where our dualboot code is inserted */ | ||
31 | #define NK_ENTRY_POINT 0x88200000 | ||
32 | |||
33 | /* Entry point (and load address) for the main Rockbox bootloader */ | ||
34 | #define BL_ENTRY_POINT 0x8a000000 | ||
35 | |||
30 | /* | 36 | /* |
31 | 37 | ||
32 | Description of nk.bin from | 38 | Description of nk.bin from |
@@ -65,11 +71,30 @@ mknkboot.c appends two images: | |||
65 | #define O_BINARY 0 | 71 | #define O_BINARY 0 |
66 | #endif | 72 | #endif |
67 | 73 | ||
68 | |||
69 | #define DISABLE_ADDR 0x88065A10 /* in EBoot */ | 74 | #define DISABLE_ADDR 0x88065A10 /* in EBoot */ |
70 | #define DISABLE_INSN 0xe3a00001 | 75 | #define DISABLE_INSN 0xe3a00001 |
71 | #define DISABLE_SUM (0xe3+0xa0+0x00+0x01) | 76 | #define DISABLE_SUM (0xe3+0xa0+0x00+0x01) |
72 | 77 | ||
78 | /* Code to dual-boot - this is inserted at NK_ENTRY_POINT */ | ||
79 | static uint32_t dualboot[] = | ||
80 | { | ||
81 | 0xe59f900c, /* ldr r9, [pc, #12] -> 0x53fa4000 */ | ||
82 | 0xe5999000, /* ldr r9, [r9] */ | ||
83 | 0xe3190010, /* tst r9, #16 ; 0x10 */ | ||
84 | #if 1 | ||
85 | /* Branch to Rockbox if hold is on */ | ||
86 | 0x159ff004, /* ldrne pc, [pc, #4] -> 0x89000000 */ | ||
87 | #else | ||
88 | /* Branch to Rockbox if hold is off */ | ||
89 | 0x059ff004, /* ldreq pc, [pc, #4] -> 0x89000000 */ | ||
90 | #endif | ||
91 | /* Branch to original firmware */ | ||
92 | 0xea0003fa, /* b 0x1000 */ | ||
93 | |||
94 | 0x53fa4000, /* GPIO3_DR */ | ||
95 | BL_ENTRY_POINT /* RB bootloader load address/entry point */ | ||
96 | }; | ||
97 | |||
73 | static void put_uint32le(uint32_t x, unsigned char* p) | 98 | static void put_uint32le(uint32_t x, unsigned char* p) |
74 | { | 99 | { |
75 | p[0] = x & 0xff; | 100 | p[0] = x & 0xff; |
@@ -105,6 +130,7 @@ int main(int argc, char *argv[]) | |||
105 | int inlength,bootlength,newlength; | 130 | int inlength,bootlength,newlength; |
106 | unsigned char* buf; | 131 | unsigned char* buf; |
107 | unsigned char* boot; | 132 | unsigned char* boot; |
133 | unsigned char* boot2; | ||
108 | unsigned char* disable; | 134 | unsigned char* disable; |
109 | uint32_t sum; | 135 | uint32_t sum; |
110 | 136 | ||
@@ -133,9 +159,9 @@ int main(int argc, char *argv[]) | |||
133 | bootlength = filesize(fdboot); | 159 | bootlength = filesize(fdboot); |
134 | 160 | ||
135 | /* Create buffer for original nk.bin, plus our bootloader (with 12 | 161 | /* Create buffer for original nk.bin, plus our bootloader (with 12 |
136 | byte header), plus the 16-byte "disable record" */ | 162 | byte header), plus the 16-byte "disable record", plus our dual-boot code */ |
137 | 163 | ||
138 | newlength = inlength + (bootlength + 12) + 16; | 164 | newlength = inlength + (bootlength + 12) + 16 + (12 + 28); |
139 | buf = malloc(newlength); | 165 | buf = malloc(newlength); |
140 | 166 | ||
141 | if (buf==NULL) | 167 | if (buf==NULL) |
@@ -156,6 +182,8 @@ int main(int argc, char *argv[]) | |||
156 | /****** STEP 2 - Move EOF record to the new EOF */ | 182 | /****** STEP 2 - Move EOF record to the new EOF */ |
157 | memcpy(buf + newlength - 12, buf + inlength - 12, 12); | 183 | memcpy(buf + newlength - 12, buf + inlength - 12, 12); |
158 | 184 | ||
185 | /* Overwrite default entry point with NK_ENTRY_POINT */ | ||
186 | put_uint32le(NK_ENTRY_POINT, buf + newlength - 8); | ||
159 | 187 | ||
160 | /****** STEP 3 - Create a record to disable the firmware signature | 188 | /****** STEP 3 - Create a record to disable the firmware signature |
161 | check in EBoot */ | 189 | check in EBoot */ |
@@ -177,17 +205,35 @@ int main(int argc, char *argv[]) | |||
177 | 205 | ||
178 | /****** STEP 5 - Create header for bootloader record */ | 206 | /****** STEP 5 - Create header for bootloader record */ |
179 | 207 | ||
180 | /* Calculate simple checksum */ | 208 | /* Calculate checksum */ |
181 | sum = 0; | 209 | sum = 0; |
182 | for (i = 0; i < bootlength; i++) { | 210 | for (i = 0; i < bootlength; i++) { |
183 | sum += boot[12 + i]; | 211 | sum += boot[12 + i]; |
184 | } | 212 | } |
185 | 213 | ||
186 | put_uint32le(0x88201000, boot); /* nk.exe start address */ | 214 | put_uint32le(BL_ENTRY_POINT, boot); /* Our entry point */ |
187 | put_uint32le(bootlength, boot + 4); | 215 | put_uint32le(bootlength, boot + 4); |
188 | put_uint32le(sum, boot + 8); | 216 | put_uint32le(sum, boot + 8); |
189 | 217 | ||
190 | /****** STEP 6 - Now write the output file */ | 218 | /****** STEP 6 - Insert our dual-boot code */ |
219 | boot2 = boot + bootlength + 12; | ||
220 | |||
221 | /* Copy dual-boot code in an endian-safe way */ | ||
222 | for (i = 0; i < sizeof(dualboot) / 4; i++) { | ||
223 | put_uint32le(dualboot[i], boot2 + 12 + i*4); | ||
224 | } | ||
225 | |||
226 | /* Calculate checksum */ | ||
227 | sum = 0; | ||
228 | for (i = 0; i < sizeof(dualboot); i++) { | ||
229 | sum += boot2[i+12]; | ||
230 | } | ||
231 | |||
232 | put_uint32le(NK_ENTRY_POINT, boot2); /* New entry point for our nk.bin */ | ||
233 | put_uint32le(sizeof(dualboot), boot2 + 4); | ||
234 | put_uint32le(sum, boot2 + 8); | ||
235 | |||
236 | /****** STEP 7 - Now write the output file */ | ||
191 | 237 | ||
192 | fdout = open(outfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); | 238 | fdout = open(outfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); |
193 | if (fdout < 0) | 239 | if (fdout < 0) |