summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2007-11-27 01:25:11 +0000
committerDave Chapman <dave@dchapman.com>2007-11-27 01:25:11 +0000
commit4fb825eed983c6fb3d76b3efbc61014f69969a87 (patch)
tree9a243b7006718cc661ff9019c5342a762c94efdc
parenta8b388fb86096b265780ac682adddcec22005f79 (diff)
downloadrockbox-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.lds2
-rw-r--r--tools/mknkboot.c58
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
32Description of nk.bin from 38Description 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 */
79static 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
73static void put_uint32le(uint32_t x, unsigned char* p) 98static 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)