summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/common.c105
-rw-r--r--bootloader/common.h12
-rw-r--r--bootloader/creativezvm.c15
-rw-r--r--bootloader/gigabeat-s.c11
-rw-r--r--bootloader/gigabeat.c13
-rw-r--r--bootloader/iaudio_coldfire.c34
-rw-r--r--bootloader/imx233.c4
-rw-r--r--bootloader/ipod.c16
-rw-r--r--bootloader/ipodnano2g.c6
-rw-r--r--bootloader/iriver_h1x0.c6
-rw-r--r--bootloader/iriver_h300.c8
-rw-r--r--bootloader/main-pp.c274
-rw-r--r--bootloader/mini2440.c17
-rw-r--r--bootloader/mpio_hd200_hd300.c26
-rw-r--r--bootloader/mrobe500.c14
-rw-r--r--bootloader/ondavx747.c8
-rw-r--r--bootloader/rk27xx.c10
-rw-r--r--bootloader/sansa_as3525.c4
-rw-r--r--bootloader/sansaconnect.c5
-rw-r--r--bootloader/telechips.c6
-rw-r--r--firmware/SOURCES7
-rw-r--r--firmware/common/loader_strerror.c63
-rw-r--r--firmware/common/rb-loader.c115
-rw-r--r--firmware/export/mi4-loader.h51
-rw-r--r--firmware/include/loader_strerror.h38
-rw-r--r--firmware/include/rb-loader.h22
-rw-r--r--firmware/rolo.c138
-rw-r--r--firmware/target/arm/pp/mi4-loader.c237
-rw-r--r--firmware/target/arm/rk27xx/rkw-loader.c72
29 files changed, 728 insertions, 609 deletions
diff --git a/bootloader/common.c b/bootloader/common.c
index 207d74ae9c..21b26e881c 100644
--- a/bootloader/common.c
+++ b/bootloader/common.c
@@ -35,6 +35,14 @@
35#include "string.h" 35#include "string.h"
36#include "usb.h" 36#include "usb.h"
37#include "file.h" 37#include "file.h"
38#include "loader_strerror.h"
39#if defined(MI4_FORMAT)
40#include "mi4-loader.h"
41#elif defined(RKW_FORMAT)
42#include "rkw-loader.h"
43#else
44#include "rb-loader.h"
45#endif
38 46
39/* TODO: Other bootloaders need to be adjusted to set this variable to true 47/* TODO: Other bootloaders need to be adjusted to set this variable to true
40 on a button press - currently only the ipod, H10, Vibe 500 and Sansa versions do. */ 48 on a button press - currently only the ipod, H10, Vibe 500 and Sansa versions do. */
@@ -94,31 +102,6 @@ int printf(const char *format, ...)
94 return len; 102 return len;
95} 103}
96 104
97char *strerror(int error)
98{
99 switch(error)
100 {
101 case EOK:
102 return "OK";
103 case EFILE_NOT_FOUND:
104 return "File not found";
105 case EREAD_CHKSUM_FAILED:
106 return "Read failed (chksum)";
107 case EREAD_MODEL_FAILED:
108 return "Read failed (model)";
109 case EREAD_IMAGE_FAILED:
110 return "Read failed (image)";
111 case EBAD_CHKSUM:
112 return "Bad checksum";
113 case EFILE_TOO_BIG:
114 return "File too big";
115 case EINVALID_FORMAT:
116 return "Invalid file format";
117 default:
118 return "Unknown";
119 }
120}
121
122void error(int errortype, int error, bool shutdown) 105void error(int errortype, int error, bool shutdown)
123{ 106{
124 switch(errortype) 107 switch(errortype)
@@ -132,85 +115,17 @@ void error(int errortype, int error, bool shutdown)
132 break; 115 break;
133 116
134 case EBOOTFILE: 117 case EBOOTFILE:
135 printf(strerror(error)); 118 printf(loader_strerror(error));
136 break; 119 break;
137 } 120 }
138 121
139 lcd_update(); 122 lcd_update();
140 sleep(5*HZ); 123 sleep(5*HZ);
124
141 if(shutdown) 125 if(shutdown)
142 power_off(); 126 power_off();
143} 127}
144 128
145/* Load firmware image in a format created by tools/scramble */
146int load_firmware(unsigned char* buf, char* firmware, int buffer_size)
147{
148 int fd;
149 int rc;
150 int len;
151 unsigned long chksum;
152 char model[5];
153 unsigned long sum;
154 int i;
155 char filename[MAX_PATH];
156
157 snprintf(filename,sizeof(filename), BOOTDIR "/%s",firmware);
158 fd = open(filename, O_RDONLY);
159 if(fd < 0)
160 {
161 snprintf(filename,sizeof(filename),"/%s",firmware);
162 fd = open(filename, O_RDONLY);
163 if(fd < 0)
164 return EFILE_NOT_FOUND;
165 }
166
167 len = filesize(fd) - 8;
168
169 printf("Length: %x", len);
170
171 if (len > buffer_size)
172 return EFILE_TOO_BIG;
173
174 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
175
176 rc = read(fd, &chksum, 4);
177 chksum=betoh32(chksum); /* Rockbox checksums are big-endian */
178 if(rc < 4)
179 return EREAD_CHKSUM_FAILED;
180
181 printf("Checksum: %x", chksum);
182
183 rc = read(fd, model, 4);
184 if(rc < 4)
185 return EREAD_MODEL_FAILED;
186
187 model[4] = '\0';
188
189 printf("Model name: %s", model);
190 printf("Loading %s", firmware);
191
192 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
193
194 rc = read(fd, buf, len);
195 if(rc < len)
196 return EREAD_IMAGE_FAILED;
197
198 close(fd);
199
200 sum = MODEL_NUMBER;
201
202 for(i = 0;i < len;i++) {
203 sum += buf[i];
204 }
205
206 printf("Sum: %x", sum);
207
208 if(sum != chksum)
209 return EBAD_CHKSUM;
210
211 return EOK;
212}
213
214/* Load raw binary image. */ 129/* Load raw binary image. */
215int load_raw_firmware(unsigned char* buf, char* firmware, int buffer_size) 130int load_raw_firmware(unsigned char* buf, char* firmware, int buffer_size)
216{ 131{
diff --git a/bootloader/common.h b/bootloader/common.h
index 7d5425c9c8..d09ff1a5ab 100644
--- a/bootloader/common.h
+++ b/bootloader/common.h
@@ -21,16 +21,6 @@
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23 23
24/* Error codes */
25#define EOK 0
26#define EFILE_NOT_FOUND -1
27#define EREAD_CHKSUM_FAILED -2
28#define EREAD_MODEL_FAILED -3
29#define EREAD_IMAGE_FAILED -4
30#define EBAD_CHKSUM -5
31#define EFILE_TOO_BIG -6
32#define EINVALID_FORMAT -7
33
34/* Set this to true to enable lcd_update() in the printf function */ 24/* Set this to true to enable lcd_update() in the printf function */
35extern bool verbose; 25extern bool verbose;
36 26
@@ -42,9 +32,7 @@ extern bool verbose;
42/* Functions common to all bootloaders */ 32/* Functions common to all bootloaders */
43void reset_screen(void); 33void reset_screen(void);
44int printf(const char *format, ...); 34int printf(const char *format, ...);
45char *strerror(int error);
46void error(int errortype, int error, bool shutdown); 35void error(int errortype, int error, bool shutdown);
47int load_firmware(unsigned char* buf, char* firmware, int buffer_size);
48int load_raw_firmware(unsigned char* buf, char* firmware, int buffer_size); 36int load_raw_firmware(unsigned char* buf, char* firmware, int buffer_size);
49#ifdef ROCKBOX_HAS_LOGF 37#ifdef ROCKBOX_HAS_LOGF
50void display_logf(void); 38void display_logf(void);
diff --git a/bootloader/creativezvm.c b/bootloader/creativezvm.c
index 7dcbac7dcc..76d72fe506 100644
--- a/bootloader/creativezvm.c
+++ b/bootloader/creativezvm.c
@@ -28,6 +28,8 @@
28#include "backlight.h" 28#include "backlight.h"
29#include "button.h" 29#include "button.h"
30#include "common.h" 30#include "common.h"
31#include "loader_strerror.h"
32#include "rb-loader.h"
31#include "usb.h" 33#include "usb.h"
32#include "version.h" 34#include "version.h"
33 35
@@ -104,15 +106,12 @@ void main(void)
104 buffer_size = (unsigned char*)0x01900000 - loadbuffer; 106 buffer_size = (unsigned char*)0x01900000 - loadbuffer;
105 107
106 ret = load_firmware(loadbuffer, BOOTFILE, buffer_size); 108 ret = load_firmware(loadbuffer, BOOTFILE, buffer_size);
107 if(ret < 0) 109 if(ret <= EFILE_EMPTY)
108 error(EBOOTFILE, ret, true); 110 error(EBOOTFILE, ret, true);
109 111
110 else if(ret == EOK) 112 kernel_entry = (void*) loadbuffer;
111 { 113 ret = kernel_entry();
112 kernel_entry = (void*) loadbuffer; 114 printf("FAILED!");
113 ret = kernel_entry();
114 printf("FAILED!");
115 }
116 } 115 }
117 116
118 storage_sleepnow(); 117 storage_sleepnow();
diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c
index 04c32423a0..5bc6bab720 100644
--- a/bootloader/gigabeat-s.c
+++ b/bootloader/gigabeat-s.c
@@ -30,6 +30,8 @@
30#include "dir.h" 30#include "dir.h"
31#include "disk.h" 31#include "disk.h"
32#include "common.h" 32#include "common.h"
33#include "rb-loader.h"
34#include "loader_strerror.h"
33#include "power.h" 35#include "power.h"
34#include "backlight.h" 36#include "backlight.h"
35#include "usb.h" 37#include "usb.h"
@@ -296,7 +298,7 @@ static void NORETURN_ATTR handle_firmware_load(void)
296{ 298{
297 int rc = load_firmware(load_buf, BOOTFILE, load_buf_size); 299 int rc = load_firmware(load_buf, BOOTFILE, load_buf_size);
298 300
299 if(rc < 0) 301 if(rc <= EFILE_EMPTY)
300 error(EBOOTFILE, rc, true); 302 error(EBOOTFILE, rc, true);
301 303
302 /* Pause to look at messages */ 304 /* Pause to look at messages */
@@ -321,11 +323,8 @@ static void NORETURN_ATTR handle_firmware_load(void)
321 storage_close(); 323 storage_close();
322 system_prepare_fw_start(); 324 system_prepare_fw_start();
323 325
324 if (rc == EOK) 326 commit_discard_idcache();
325 { 327 asm volatile ("bx %0": : "r"(start_addr));
326 commit_discard_idcache();
327 asm volatile ("bx %0": : "r"(start_addr));
328 }
329 328
330 /* Halt */ 329 /* Halt */
331 while (1) 330 while (1)
diff --git a/bootloader/gigabeat.c b/bootloader/gigabeat.c
index fb03f0ea4d..d77021571a 100644
--- a/bootloader/gigabeat.c
+++ b/bootloader/gigabeat.c
@@ -41,6 +41,8 @@
41#include "power.h" 41#include "power.h"
42#include "file.h" 42#include "file.h"
43#include "common.h" 43#include "common.h"
44#include "rb-loader.h"
45#include "loader_strerror.h"
44#include "rbunicode.h" 46#include "rbunicode.h"
45#include "usb.h" 47#include "usb.h"
46#include "mmu-arm.h" 48#include "mmu-arm.h"
@@ -201,18 +203,15 @@ void main(void)
201 buffer_size = (unsigned char*)0x31400000 - loadbuffer; 203 buffer_size = (unsigned char*)0x31400000 - loadbuffer;
202 204
203 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); 205 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size);
204 if(rc < 0) 206 if(rc <= EFILE_EMPTY)
205 error(EBOOTFILE, rc, true); 207 error(EBOOTFILE, rc, true);
206 208
207 storage_close(); 209 storage_close();
208 system_prepare_fw_start(); 210 system_prepare_fw_start();
209 211
210 if (rc == EOK) 212 commit_discard_idcache();
211 { 213 kernel_entry = (void*) loadbuffer;
212 commit_discard_idcache(); 214 rc = kernel_entry();
213 kernel_entry = (void*) loadbuffer;
214 rc = kernel_entry();
215 }
216 215
217#if 0 216#if 0
218 /* Halt */ 217 /* Halt */
diff --git a/bootloader/iaudio_coldfire.c b/bootloader/iaudio_coldfire.c
index b22af0e006..95060e458f 100644
--- a/bootloader/iaudio_coldfire.c
+++ b/bootloader/iaudio_coldfire.c
@@ -43,6 +43,8 @@
43#include "powermgmt.h" 43#include "powermgmt.h"
44#include "file.h" 44#include "file.h"
45#include "version.h" 45#include "version.h"
46#include "loader_strerror.h"
47#include "rb-loader.h"
46 48
47 49
48#include "pcf50606.h" 50#include "pcf50606.h"
@@ -129,7 +131,6 @@ int initial_gpio_read;
129 131
130void main(void) 132void main(void)
131{ 133{
132 int i;
133 int rc; 134 int rc;
134 bool rc_on_button = false; 135 bool rc_on_button = false;
135 bool on_button = false; 136 bool on_button = false;
@@ -194,35 +195,22 @@ void main(void)
194 195
195 rc = storage_init(); 196 rc = storage_init();
196 if(rc) 197 if(rc)
197 { 198 error(EATA, rc, true);
198 printf("ATA error: %d", rc);
199 sleep(HZ*5);
200 power_off();
201 }
202 199
203 disk_init(); 200 disk_init();
204 201
205 rc = disk_mount_all(); 202 rc = disk_mount_all();
206 if (rc<=0) 203 if (rc<=0)
207 { 204 error(EDISK, rc, true);
208 printf("No partition found");
209 sleep(HZ*5);
210 power_off();
211 }
212 205
213 printf("Loading firmware"); 206 printf("Loading firmware");
214 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE); 207
215 printf("Result: %s", strerror(i)); 208 rc = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE);
216 209
217 if (i < EOK) { 210 if (rc <= EFILE_EMPTY)
218 printf("Error!"); 211 error(EBOOTFILE, rc, true);
219 printf("Can't load " BOOTFILE ": "); 212
220 printf(strerror(rc)); 213 start_firmware();
221 sleep(HZ*3);
222 power_off();
223 } else {
224 start_firmware();
225 }
226} 214}
227 215
228/* These functions are present in the firmware library, but we reimplement 216/* These functions are present in the firmware library, but we reimplement
diff --git a/bootloader/imx233.c b/bootloader/imx233.c
index dfd4b0b28b..0923d8b699 100644
--- a/bootloader/imx233.c
+++ b/bootloader/imx233.c
@@ -31,6 +31,8 @@
31#include "backlight.h" 31#include "backlight.h"
32#include "button-target.h" 32#include "button-target.h"
33#include "common.h" 33#include "common.h"
34#include "rb-loader.h"
35#include "loader_strerror.h"
34#include "storage.h" 36#include "storage.h"
35#include "disk.h" 37#include "disk.h"
36#include "panic.h" 38#include "panic.h"
@@ -180,7 +182,7 @@ void main(uint32_t arg, uint32_t addr)
180 loadbuffer = (unsigned char*)loadaddress; 182 loadbuffer = (unsigned char*)loadaddress;
181 buffer_size = (int)(loadaddressend - loadaddress); 183 buffer_size = (int)(loadaddressend - loadaddress);
182 184
183 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) < 0) 185 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) <= EFILE_EMPTY)
184 { 186 {
185 error(EBOOTFILE, ret, true); 187 error(EBOOTFILE, ret, true);
186 } 188 }
diff --git a/bootloader/ipod.c b/bootloader/ipod.c
index af4c1576bb..3f9604ae4b 100644
--- a/bootloader/ipod.c
+++ b/bootloader/ipod.c
@@ -42,6 +42,8 @@
42#include "power.h" 42#include "power.h"
43#include "file.h" 43#include "file.h"
44#include "common.h" 44#include "common.h"
45#include "rb-loader.h"
46#include "loader_strerror.h"
45#include "hwcompat.h" 47#include "hwcompat.h"
46#include "usb.h" 48#include "usb.h"
47#include "version.h" 49#include "version.h"
@@ -376,7 +378,7 @@ void* main(void)
376 378
377 rc=load_firmware(loadbuffer, "apple_os.ipod", MAX_LOADSIZE); 379 rc=load_firmware(loadbuffer, "apple_os.ipod", MAX_LOADSIZE);
378 380
379 if (rc == EOK) { 381 if (rc > 0) {
380 printf("apple_os.ipod loaded."); 382 printf("apple_os.ipod loaded.");
381 return (void*)DRAM_START; 383 return (void*)DRAM_START;
382 } else if (rc == EFILE_NOT_FOUND) { 384 } else if (rc == EFILE_NOT_FOUND) {
@@ -387,10 +389,10 @@ void* main(void)
387 /* We have a copy of the retailos in RAM, lets just run it. */ 389 /* We have a copy of the retailos in RAM, lets just run it. */
388 return (void*)DRAM_START; 390 return (void*)DRAM_START;
389 } 391 }
390 } else if (rc < EFILE_NOT_FOUND) { 392 } else {
391 printf("Error!"); 393 printf("Error!");
392 printf("Can't load apple_os.ipod:"); 394 printf("Can't load apple_os.ipod:");
393 printf(strerror(rc)); 395 printf(loader_strerror(rc));
394 } 396 }
395 397
396 /* Everything failed - just loop forever */ 398 /* Everything failed - just loop forever */
@@ -399,17 +401,17 @@ void* main(void)
399 } else if (btn==BUTTON_PLAY) { 401 } else if (btn==BUTTON_PLAY) {
400 printf("Loading Linux..."); 402 printf("Loading Linux...");
401 rc=load_raw_firmware(loadbuffer, "/linux.bin", MAX_LOADSIZE); 403 rc=load_raw_firmware(loadbuffer, "/linux.bin", MAX_LOADSIZE);
402 if (rc < EOK) { 404 if (rc <= EFILE_EMPTY) {
403 printf("Error!"); 405 printf("Error!");
404 printf("Can't load linux.bin:"); 406 printf("Can't load linux.bin:");
405 printf(strerror(rc)); 407 printf(loader_strerror(rc));
406 } else { 408 } else {
407 return (void*)DRAM_START; 409 return (void*)DRAM_START;
408 } 410 }
409 } else { 411 } else {
410 printf("Loading Rockbox..."); 412 printf("Loading Rockbox...");
411 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE); 413 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
412 if (rc == EOK) { 414 if (rc > 0) {
413 printf("Rockbox loaded."); 415 printf("Rockbox loaded.");
414 return (void*)DRAM_START; 416 return (void*)DRAM_START;
415 } else if (rc == EFILE_NOT_FOUND) { 417 } else if (rc == EFILE_NOT_FOUND) {
@@ -424,7 +426,7 @@ void* main(void)
424 426
425 printf("Error!"); 427 printf("Error!");
426 printf("Can't load " BOOTFILE ": "); 428 printf("Can't load " BOOTFILE ": ");
427 printf(strerror(rc)); 429 printf(loader_strerror(rc));
428 } 430 }
429 431
430 /* If we get to here, then we haven't been able to load any firmware */ 432 /* If we get to here, then we haven't been able to load any firmware */
diff --git a/bootloader/ipodnano2g.c b/bootloader/ipodnano2g.c
index be714c6273..c5fa6e2e65 100644
--- a/bootloader/ipodnano2g.c
+++ b/bootloader/ipodnano2g.c
@@ -44,6 +44,8 @@
44#include "power.h" 44#include "power.h"
45#include "file.h" 45#include "file.h"
46#include "common.h" 46#include "common.h"
47#include "rb-loader.h"
48#include "loader_strerror.h"
47#include "version.h" 49#include "version.h"
48 50
49/* Safety measure - maximum allowed firmware image size. 51/* Safety measure - maximum allowed firmware image size.
@@ -238,10 +240,10 @@ void main(void)
238 printf("Loading Rockbox..."); 240 printf("Loading Rockbox...");
239 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE); 241 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
240 242
241 if (rc != EOK) { 243 if (rc <= EFILE_EMPTY) {
242 printf("Error!"); 244 printf("Error!");
243 printf("Can't load " BOOTFILE ": "); 245 printf("Can't load " BOOTFILE ": ");
244 printf(strerror(rc)); 246 printf(loader_strerror(rc));
245 fatal_error(); 247 fatal_error();
246 } 248 }
247 249
diff --git a/bootloader/iriver_h1x0.c b/bootloader/iriver_h1x0.c
index 9042737406..77624526e5 100644
--- a/bootloader/iriver_h1x0.c
+++ b/bootloader/iriver_h1x0.c
@@ -46,6 +46,8 @@
46#include "eeprom_settings.h" 46#include "eeprom_settings.h"
47#include "rbunicode.h" 47#include "rbunicode.h"
48#include "common.h" 48#include "common.h"
49#include "rb-loader.h"
50#include "loader_strerror.h"
49#include "version.h" 51#include "version.h"
50 52
51#include <stdarg.h> 53#include <stdarg.h>
@@ -608,9 +610,9 @@ void main(void)
608 printf("Loading firmware"); 610 printf("Loading firmware");
609 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE); 611 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE);
610 if(i < 0) 612 if(i < 0)
611 printf("Error: %s", strerror(i)); 613 printf("Error: %s", loader_strerror(i));
612 614
613 if (i == EOK) 615 if (i > 0)
614 start_firmware(); 616 start_firmware();
615 617
616 if (!detect_original_firmware()) 618 if (!detect_original_firmware())
diff --git a/bootloader/iriver_h300.c b/bootloader/iriver_h300.c
index b6d7da20fa..4b36e40e61 100644
--- a/bootloader/iriver_h300.c
+++ b/bootloader/iriver_h300.c
@@ -45,6 +45,8 @@
45#include "file.h" 45#include "file.h"
46#include "pcf50606.h" 46#include "pcf50606.h"
47#include "common.h" 47#include "common.h"
48#include "rb-loader.h"
49#include "loader_strerror.h"
48#include "rbunicode.h" 50#include "rbunicode.h"
49#include "isp1362.h" 51#include "isp1362.h"
50#include "version.h" 52#include "version.h"
@@ -361,10 +363,10 @@ void main(void)
361 363
362 printf("Loading firmware"); 364 printf("Loading firmware");
363 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE); 365 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE);
364 if(i < 0) 366 if(i <= EFILE_EMPTY)
365 printf("Error: %s", strerror(i)); 367 printf("Error: %s", loader_strerror(i));
366 368
367 if (i == EOK) 369 if (i > 0)
368 start_firmware(); 370 start_firmware();
369 371
370 if (!detect_original_firmware()) 372 if (!detect_original_firmware())
diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c
index 72d45712fc..b03a5a75c6 100644
--- a/bootloader/main-pp.c
+++ b/bootloader/main-pp.c
@@ -37,6 +37,8 @@
37#include "button.h" 37#include "button.h"
38#include "disk.h" 38#include "disk.h"
39#include "crc32-mi4.h" 39#include "crc32-mi4.h"
40#include "mi4-loader.h"
41#include "loader_strerror.h"
40#include <string.h> 42#include <string.h>
41#include "power.h" 43#include "power.h"
42#include "version.h" 44#include "version.h"
@@ -110,21 +112,6 @@ unsigned char *loadbuffer = (unsigned char *)DRAM_START;
110 112
111#define MI4_HEADER_SIZE 0x200 113#define MI4_HEADER_SIZE 0x200
112 114
113/* mi4 header structure */
114struct mi4header_t {
115 unsigned char magic[4];
116 uint32_t version;
117 uint32_t length;
118 uint32_t crc32;
119 uint32_t enctype;
120 uint32_t mi4size;
121 uint32_t plaintext;
122 uint32_t dsa_key[10];
123 uint32_t pad[109];
124 unsigned char type[4];
125 unsigned char model[4];
126};
127
128/* PPMI header structure */ 115/* PPMI header structure */
129struct ppmi_header_t { 116struct ppmi_header_t {
130 unsigned char magic[4]; 117 unsigned char magic[4];
@@ -132,236 +119,6 @@ struct ppmi_header_t {
132 uint32_t pad[126]; 119 uint32_t pad[126];
133}; 120};
134 121
135inline unsigned int le2int(unsigned char* buf)
136{
137 int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
138
139 return res;
140}
141
142inline void int2le(unsigned int val, unsigned char* addr)
143{
144 addr[0] = val & 0xFF;
145 addr[1] = (val >> 8) & 0xff;
146 addr[2] = (val >> 16) & 0xff;
147 addr[3] = (val >> 24) & 0xff;
148}
149
150struct tea_key {
151 const char * name;
152 uint32_t key[4];
153};
154
155#define NUM_KEYS (sizeof(tea_keytable)/sizeof(tea_keytable[0]))
156struct tea_key tea_keytable[] = {
157 { "default" , { 0x20d36cc0, 0x10e8c07d, 0xc0e7dcaa, 0x107eb080 } },
158 { "sansa", { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 } },
159 { "sansa_gh", { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 } },
160 { "sansa_103", { 0x1d29ddc0, 0x2579c2cd, 0xce339e1a, 0x75465dfe } },
161 { "rhapsody", { 0x7aa9c8dc, 0xbed0a82a, 0x16204cc7, 0x5904ef38 } },
162 { "p610", { 0x950e83dc, 0xec4907f9, 0x023734b9, 0x10cfb7c7 } },
163 { "p640", { 0x220c5f23, 0xd04df68e, 0x431b5e25, 0x4dcc1fa1 } },
164 { "virgin", { 0xe83c29a1, 0x04862973, 0xa9b3f0d4, 0x38be2a9c } },
165 { "20gc_eng", { 0x0240772c, 0x6f3329b5, 0x3ec9a6c5, 0xb0c9e493 } },
166 { "20gc_fre", { 0xbede8817, 0xb23bfe4f, 0x80aa682d, 0xd13f598c } },
167 { "elio_p722", { 0x6af3b9f8, 0x777483f5, 0xae8181cc, 0xfa6d8a84 } },
168 { "c200", { 0xbf2d06fa, 0xf0e23d59, 0x29738132, 0xe2d04ca7 } },
169 { "c200_103", { 0x2a7968de, 0x15127979, 0x142e60a7, 0xe49c1893 } },
170 { "c200_106", { 0xa913d139, 0xf842f398, 0x3e03f1a6, 0x060ee012 } },
171 { "view", { 0x70e19bda, 0x0c69ea7d, 0x2b8b1ad1, 0xe9767ced } },
172 { "sa9200", { 0x33ea0236, 0x9247bdc5, 0xdfaedf9f, 0xd67c9d30 } },
173 { "hdd1630/hdd63x0", { 0x04543ced, 0xcebfdbad, 0xf7477872, 0x0d12342e } },
174 { "vibe500", { 0xe3a66156, 0x77c6b67a, 0xe821dca5, 0xca8ca37c } },
175};
176
177/*
178
179tea_decrypt() from http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
180
181"Following is an adaptation of the reference encryption and decryption
182routines in C, released into the public domain by David Wheeler and
183Roger Needham:"
184
185*/
186
187/* NOTE: The mi4 version of TEA uses a different initial value to sum compared
188 to the reference implementation and the main loop is 8 iterations, not
189 32.
190*/
191
192static void tea_decrypt(uint32_t* v0, uint32_t* v1, uint32_t* k) {
193 uint32_t sum=0xF1BBCDC8, i; /* set up */
194 uint32_t delta=0x9E3779B9; /* a key schedule constant */
195 uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
196 for(i=0; i<8; i++) { /* basic cycle start */
197 *v1 -= ((*v0<<4) + k2) ^ (*v0 + sum) ^ ((*v0>>5) + k3);
198 *v0 -= ((*v1<<4) + k0) ^ (*v1 + sum) ^ ((*v1>>5) + k1);
199 sum -= delta; /* end cycle */
200 }
201}
202
203/* mi4 files are encrypted in 64-bit blocks (two little-endian 32-bit
204 integers) and the key is incremented after each block
205 */
206
207static void tea_decrypt_buf(unsigned char* src, unsigned char* dest, size_t n, uint32_t * key)
208{
209 uint32_t v0, v1;
210 unsigned int i;
211
212 for (i = 0; i < (n / 8); i++) {
213 v0 = le2int(src);
214 v1 = le2int(src+4);
215
216 tea_decrypt(&v0, &v1, key);
217
218 int2le(v0, dest);
219 int2le(v1, dest+4);
220
221 src += 8;
222 dest += 8;
223
224 /* Now increment the key */
225 key[0]++;
226 if (key[0]==0) {
227 key[1]++;
228 if (key[1]==0) {
229 key[2]++;
230 if (key[2]==0) {
231 key[3]++;
232 }
233 }
234 }
235 }
236}
237
238static int tea_find_key(struct mi4header_t *mi4header, unsigned char* buf)
239{
240 unsigned int i;
241 uint32_t key[4];
242 uint32_t keyinc;
243 unsigned char magic_dec[8];
244 int key_found = -1;
245 unsigned int magic_location = mi4header->length-4;
246 int unaligned = 0;
247
248 if ( (magic_location % 8) != 0 )
249 {
250 unaligned = 1;
251 magic_location -= 4;
252 }
253
254 printf("Searching for key:");
255
256 for (i=0; i < NUM_KEYS && (key_found<0) ; i++) {
257 key[0] = tea_keytable[i].key[0];
258 key[1] = tea_keytable[i].key[1];
259 key[2] = tea_keytable[i].key[2];
260 key[3] = tea_keytable[i].key[3];
261
262 /* Now increment the key */
263 keyinc = (magic_location-mi4header->plaintext)/8;
264 if ((key[0]+keyinc) < key[0]) key[1]++;
265 key[0] += keyinc;
266 if (key[1]==0) key[2]++;
267 if (key[2]==0) key[3]++;
268
269 /* Decrypt putative magic */
270 tea_decrypt_buf(&buf[magic_location], magic_dec, 8, key);
271
272 if (le2int(&magic_dec[4*unaligned]) == 0xaa55aa55)
273 {
274 key_found = i;
275 printf("%s...found", tea_keytable[i].name);
276 } else {
277 /* printf("%s...failed", tea_keytable[i].name); */
278 }
279 }
280
281 return key_found;
282}
283
284
285/* Load mi4 format firmware image */
286int load_mi4(unsigned char* buf, char* firmware, unsigned int buffer_size)
287{
288 int fd;
289 struct mi4header_t mi4header;
290 int rc;
291 unsigned long sum;
292 char filename[MAX_PATH];
293
294 snprintf(filename,sizeof(filename), BOOTDIR "/%s",firmware);
295 fd = open(filename, O_RDONLY);
296 if(fd < 0)
297 {
298 snprintf(filename,sizeof(filename),"/%s",firmware);
299 fd = open(filename, O_RDONLY);
300 if(fd < 0)
301 return EFILE_NOT_FOUND;
302 }
303
304 read(fd, &mi4header, MI4_HEADER_SIZE);
305
306 /* MI4 file size */
307 printf("mi4 size: %x", mi4header.mi4size);
308
309 if ((mi4header.mi4size-MI4_HEADER_SIZE) > buffer_size)
310 {
311 close(fd);
312 return EFILE_TOO_BIG;
313 }
314
315 /* CRC32 */
316 printf("CRC32: %x", mi4header.crc32);
317
318 /* Rockbox model id */
319 printf("Model id: %.4s", mi4header.model);
320
321 /* Read binary type (RBOS, RBBL) */
322 printf("Binary type: %.4s", mi4header.type);
323
324 /* Load firmware file */
325 lseek(fd, MI4_HEADER_SIZE, SEEK_SET);
326 rc = read(fd, buf, mi4header.mi4size-MI4_HEADER_SIZE);
327 close(fd);
328 if(rc < (int)mi4header.mi4size-MI4_HEADER_SIZE)
329 return EREAD_IMAGE_FAILED;
330
331 /* Check CRC32 to see if we have a valid file */
332 sum = chksum_crc32 (buf, mi4header.mi4size - MI4_HEADER_SIZE);
333
334 printf("Calculated CRC32: %x", sum);
335
336 if(sum != mi4header.crc32)
337 return EBAD_CHKSUM;
338
339 if( (mi4header.plaintext + MI4_HEADER_SIZE) != mi4header.mi4size)
340 {
341 /* Load encrypted firmware */
342 int key_index = tea_find_key(&mi4header, buf);
343
344 if (key_index < 0)
345 return EINVALID_FORMAT;
346
347 /* Plaintext part is already loaded */
348 buf += mi4header.plaintext;
349
350 /* Decrypt in-place */
351 tea_decrypt_buf(buf, buf,
352 mi4header.mi4size-(mi4header.plaintext+MI4_HEADER_SIZE),
353 tea_keytable[key_index].key);
354
355 printf("%s key used", tea_keytable[key_index].name);
356
357 /* Check decryption was successfull */
358 if(le2int(&buf[mi4header.length-mi4header.plaintext-4]) != 0xaa55aa55)
359 return EREAD_IMAGE_FAILED;
360 }
361
362 return EOK;
363}
364
365#if (CONFIG_STORAGE & STORAGE_SD) 122#if (CONFIG_STORAGE & STORAGE_SD)
366/* Load mi4 firmware from a hidden disk partition */ 123/* Load mi4 firmware from a hidden disk partition */
367int load_mi4_part(unsigned char* buf, struct partinfo* pinfo, 124int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
@@ -432,7 +189,7 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
432 (void) disable_rebuild; 189 (void) disable_rebuild;
433#endif 190#endif
434 191
435 return EOK; 192 return mi4header.mi4size-MI4_HEADER_SIZE;
436} 193}
437#endif /* (CONFIG_STORAGE & STORAGE_SD) */ 194#endif /* (CONFIG_STORAGE & STORAGE_SD) */
438 195
@@ -528,6 +285,7 @@ static int handle_usb(int connect_timeout)
528 285
529void* main(void) 286void* main(void)
530{ 287{
288 char filename[MAX_PATH];
531 int i; 289 int i;
532 int btn; 290 int btn;
533 int rc; 291 int rc;
@@ -642,13 +400,15 @@ void* main(void)
642 if((btn & BOOTLOADER_BOOT_OF) == 0) 400 if((btn & BOOTLOADER_BOOT_OF) == 0)
643 { 401 {
644 printf("Loading Rockbox..."); 402 printf("Loading Rockbox...");
645 rc = load_mi4(loadbuffer, BOOTFILE, MAX_LOADSIZE); 403 snprintf(filename,sizeof(filename), BOOTDIR "/%s", BOOTFILE);
646 if (rc < EOK) 404
405 rc = load_mi4(loadbuffer, filename, MAX_LOADSIZE);
406 if (rc <= EFILE_EMPTY)
647 { 407 {
648 bool old_verbose = verbose; 408 bool old_verbose = verbose;
649 verbose = true; 409 verbose = true;
650 printf("Can't load " BOOTFILE ": "); 410 printf("Can't load " BOOTFILE ": ");
651 printf(strerror(rc)); 411 printf(loader_strerror(rc));
652 verbose = old_verbose; 412 verbose = old_verbose;
653 btn |= BOOTLOADER_BOOT_OF; 413 btn |= BOOTLOADER_BOOT_OF;
654 sleep(5*HZ); 414 sleep(5*HZ);
@@ -676,9 +436,9 @@ void* main(void)
676 { 436 {
677 rc = load_mi4_part(loadbuffer, pinfo, MAX_LOADSIZE, 437 rc = load_mi4_part(loadbuffer, pinfo, MAX_LOADSIZE,
678 usb == USB_INSERTED); 438 usb == USB_INSERTED);
679 if (rc < EOK) { 439 if (rc <= EFILE_EMPTY) {
680 printf("Can't load from partition"); 440 printf("Can't load from partition");
681 printf(strerror(rc)); 441 printf(loader_strerror(rc));
682 } else { 442 } else {
683 goto main_exit; 443 goto main_exit;
684 } 444 }
@@ -690,9 +450,9 @@ void* main(void)
690#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || defined(PHILIPS_SA9200) 450#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || defined(PHILIPS_SA9200)
691 printf("Trying /System/OF.ebn"); 451 printf("Trying /System/OF.ebn");
692 rc=load_mi4(loadbuffer, "/System/OF.ebn", MAX_LOADSIZE); 452 rc=load_mi4(loadbuffer, "/System/OF.ebn", MAX_LOADSIZE);
693 if (rc < EOK) { 453 if (rc <= EFILE_EMPTY) {
694 printf("Can't load /System/OF.ebn"); 454 printf("Can't load /System/OF.ebn");
695 printf(strerror(rc)); 455 printf(loader_strerror(rc));
696 } else { 456 } else {
697 goto main_exit; 457 goto main_exit;
698 } 458 }
@@ -700,9 +460,9 @@ void* main(void)
700 460
701 printf("Trying /System/OF.mi4"); 461 printf("Trying /System/OF.mi4");
702 rc=load_mi4(loadbuffer, "/System/OF.mi4", MAX_LOADSIZE); 462 rc=load_mi4(loadbuffer, "/System/OF.mi4", MAX_LOADSIZE);
703 if (rc < EOK) { 463 if (rc <= EFILE_EMPTY) {
704 printf("Can't load /System/OF.mi4"); 464 printf("Can't load /System/OF.mi4");
705 printf(strerror(rc)); 465 printf(loader_strerror(rc));
706 } else { 466 } else {
707#if defined(SAMSUNG_YH925) 467#if defined(SAMSUNG_YH925)
708 lcd_reset(); 468 lcd_reset();
@@ -712,9 +472,9 @@ void* main(void)
712 472
713 printf("Trying /System/OF.bin"); 473 printf("Trying /System/OF.bin");
714 rc=load_raw_firmware(loadbuffer, "/System/OF.bin", MAX_LOADSIZE); 474 rc=load_raw_firmware(loadbuffer, "/System/OF.bin", MAX_LOADSIZE);
715 if (rc < EOK) { 475 if (rc <= EFILE_EMPTY) {
716 printf("Can't load /System/OF.bin"); 476 printf("Can't load /System/OF.bin");
717 printf(strerror(rc)); 477 printf(loader_strerror(rc));
718 } else { 478 } else {
719#if defined(SAMSUNG_YH925) 479#if defined(SAMSUNG_YH925)
720 lcd_reset(); 480 lcd_reset();
diff --git a/bootloader/mini2440.c b/bootloader/mini2440.c
index 2ff93a407e..7750d07559 100644
--- a/bootloader/mini2440.c
+++ b/bootloader/mini2440.c
@@ -39,6 +39,8 @@
39#include "power.h" 39#include "power.h"
40#include "file.h" 40#include "file.h"
41#include "common.h" 41#include "common.h"
42#include "rb-loader.h"
43#include "loader_strerror.h"
42#include "sd.h" 44#include "sd.h"
43#include "backlight-target.h" 45#include "backlight-target.h"
44#include "lcd-target.h" 46#include "lcd-target.h"
@@ -97,26 +99,23 @@ int main(void)
97 printf("Loading firmware"); 99 printf("Loading firmware");
98 100
99 /* Flush out anything pending first */ 101 /* Flush out anything pending first */
100 cpucache_invalidate(); 102 commit_discard_idcache();
101 103
102 loadbuffer = (unsigned char*) 0x31000000; 104 loadbuffer = (unsigned char*) 0x31000000;
103 buffer_size = (unsigned char*)0x31400000 - loadbuffer; 105 buffer_size = (unsigned char*)0x31400000 - loadbuffer;
104 106
105 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); 107 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size);
106 if(rc < 0) 108 if(rc <= 0)
107 error(EBOOTFILE, rc, true); 109 error(EBOOTFILE, rc, true);
108 110
109 printf("Loaded firmware %d\n", rc); 111 printf("Loaded firmware %d\n", rc);
110 112
111/* storage_close(); */ 113/* storage_close(); */
112 system_prepare_fw_start(); 114 system_prepare_fw_start();
113 115
114 if (rc == EOK) 116 commit_discard_idcache();
115 { 117 kernel_entry = (void*) loadbuffer;
116 cpucache_invalidate(); 118 rc = kernel_entry();
117 kernel_entry = (void*) loadbuffer;
118 rc = kernel_entry();
119 }
120 119
121 /* end stop - should not get here */ 120 /* end stop - should not get here */
122 led_flash(LED_ALL, LED_NONE); 121 led_flash(LED_ALL, LED_NONE);
diff --git a/bootloader/mpio_hd200_hd300.c b/bootloader/mpio_hd200_hd300.c
index 3e4ba76c83..1828907ea7 100644
--- a/bootloader/mpio_hd200_hd300.c
+++ b/bootloader/mpio_hd200_hd300.c
@@ -43,6 +43,8 @@
43#include "file.h" 43#include "file.h"
44 44
45#include "common.h" 45#include "common.h"
46#include "rb-loader.h"
47#include "loader_strerror.h"
46#include "version.h" 48#include "version.h"
47 49
48#include <stdarg.h> 50#include <stdarg.h>
@@ -199,35 +201,21 @@ static void rb_boot(void)
199 201
200 rc = storage_init(); 202 rc = storage_init();
201 if(rc) 203 if(rc)
202 { 204 error(EATA, rc, true);
203 printf("ATA error: %d", rc);
204 sleep(HZ*5);
205 return;
206 }
207 205
208 disk_init(); 206 disk_init();
209 207
210 rc = disk_mount_all(); 208 rc = disk_mount_all();
211 if (rc<=0) 209 if (rc <= 0)
212 { 210 error(EDISK, rc, true);
213 printf("No partition found");
214 sleep(HZ*5);
215 return;
216 }
217 211
218 printf("Loading firmware"); 212 printf("Loading firmware");
219 213
220 rc = load_firmware((unsigned char *)DRAM_START, 214 rc = load_firmware((unsigned char *)DRAM_START,
221 BOOTFILE, MAX_LOADSIZE); 215 BOOTFILE, MAX_LOADSIZE);
222 216
223 if (rc < EOK) 217 if (rc <= EFILE_EMPTY)
224 { 218 error(EBOOTFILE, rc, true);
225 printf("Error!");
226 printf("Can't load " BOOTFILE ": ");
227 printf("Result: %s", strerror(rc));
228 sleep(HZ*5);
229 return;
230 }
231 219
232 cpu_boost(false); 220 cpu_boost(false);
233 start_rockbox(); 221 start_rockbox();
diff --git a/bootloader/mrobe500.c b/bootloader/mrobe500.c
index 5b9c520d02..642945487d 100644
--- a/bootloader/mrobe500.c
+++ b/bootloader/mrobe500.c
@@ -38,6 +38,8 @@
38#include "power.h" 38#include "power.h"
39#include "file.h" 39#include "file.h"
40#include "common.h" 40#include "common.h"
41#include "rb-loader.h"
42#include "loader_strerror.h"
41#include "rbunicode.h" 43#include "rbunicode.h"
42#include "usb.h" 44#include "usb.h"
43#include "spi.h" 45#include "spi.h"
@@ -138,12 +140,12 @@ void main(void)
138 buffer_size = (unsigned char*)0x01900000 - loadbuffer; 140 buffer_size = (unsigned char*)0x01900000 - loadbuffer;
139 141
140 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); 142 rc = load_firmware(loadbuffer, BOOTFILE, buffer_size);
141 if(rc < 0) 143 if(rc <= EFILE_EMPTY)
142 error(EBOOTFILE, rc, true); 144 error(EBOOTFILE, rc, true);
143 145
144 if (rc == EOK) 146 kernel_entry = (void*) loadbuffer;
145 { 147 rc = kernel_entry();
146 kernel_entry = (void*) loadbuffer; 148
147 rc = kernel_entry(); 149 /* Should not get here! */
148 } 150 return rc;
149} 151}
diff --git a/bootloader/ondavx747.c b/bootloader/ondavx747.c
index 7b4615b10b..4d0bf4221c 100644
--- a/bootloader/ondavx747.c
+++ b/bootloader/ondavx747.c
@@ -29,6 +29,8 @@
29#include "system.h" 29#include "system.h"
30#include "button.h" 30#include "button.h"
31#include "common.h" 31#include "common.h"
32#include "rb-loader.h"
33#include "loader_strerror.h"
32#include "storage.h" 34#include "storage.h"
33#include "disk.h" 35#include "disk.h"
34#include "string.h" 36#include "string.h"
@@ -148,7 +150,7 @@ static int boot_rockbox(void)
148 150
149 printf("Loading firmware..."); 151 printf("Loading firmware...");
150 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000); 152 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
151 if(rc < 0) 153 if(rc <= EFILE_EMPTY)
152 return rc; 154 return rc;
153 else 155 else
154 { 156 {
@@ -303,8 +305,8 @@ int main(void)
303#endif 305#endif
304 rc = boot_rockbox(); 306 rc = boot_rockbox();
305 307
306 if(rc < 0) 308 if(rc <= EFILE_EMPTY)
307 printf("Error: %s", strerror(rc)); 309 printf("Error: %s", loader_strerror(rc));
308 310
309 /* Halt */ 311 /* Halt */
310 while (1) 312 while (1)
diff --git a/bootloader/rk27xx.c b/bootloader/rk27xx.c
index 552ec8a2d0..209004885f 100644
--- a/bootloader/rk27xx.c
+++ b/bootloader/rk27xx.c
@@ -20,6 +20,7 @@
20#include "rkw-loader.h" 20#include "rkw-loader.h"
21#include "version.h" 21#include "version.h"
22#include "i2c-rk27xx.h" 22#include "i2c-rk27xx.h"
23#include "loader_strerror.h"
23 24
24/* beginning of DRAM */ 25/* beginning of DRAM */
25#define DRAM_ORIG 0x60000000 26#define DRAM_ORIG 0x60000000
@@ -161,11 +162,10 @@ void main(void)
161 printf("Loading: %s", filename); 162 printf("Loading: %s", filename);
162 163
163 ret = load_rkw(loadbuffer, filename, LOAD_SIZE); 164 ret = load_rkw(loadbuffer, filename, LOAD_SIZE);
164 if (ret < 0) 165
166 if (ret <= EFILE_EMPTY)
165 { 167 {
166 printf(rkw_strerror(ret)); 168 error(EBOOTFILE, ret, false);
167 lcd_update();
168 sleep(5*HZ);
169 169
170 /* if we boot rockbox we shutdown on error 170 /* if we boot rockbox we shutdown on error
171 * if we boot OF we fall back to rkusb mode on error 171 * if we boot OF we fall back to rkusb mode on error
@@ -186,7 +186,7 @@ void main(void)
186 else 186 else
187 { 187 {
188 /* print 'Loading OK' */ 188 /* print 'Loading OK' */
189 printf(rkw_strerror(0)); 189 printf("Loading OK");
190 sleep(HZ); 190 sleep(HZ);
191 } 191 }
192 192
diff --git a/bootloader/sansa_as3525.c b/bootloader/sansa_as3525.c
index c21f51a7ad..b28ccf43e7 100644
--- a/bootloader/sansa_as3525.c
+++ b/bootloader/sansa_as3525.c
@@ -35,6 +35,8 @@
35#include "backlight.h" 35#include "backlight.h"
36#include "button-target.h" 36#include "button-target.h"
37#include "common.h" 37#include "common.h"
38#include "rb-loader.h"
39#include "loader_strerror.h"
38#include "storage.h" 40#include "storage.h"
39#include "disk.h" 41#include "disk.h"
40#include "panic.h" 42#include "panic.h"
@@ -147,7 +149,7 @@ void main(void)
147 loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */ 149 loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */
148 buffer_size = (int)(loadbuffer + (DRAM_SIZE) - TTB_SIZE); 150 buffer_size = (int)(loadbuffer + (DRAM_SIZE) - TTB_SIZE);
149 151
150 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) < 0) 152 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) <= EFILE_EMPTY)
151 { 153 {
152#ifdef USE_ROCKBOX_USB 154#ifdef USE_ROCKBOX_USB
153 error(EBOOTFILE, ret, false); 155 error(EBOOTFILE, ret, false);
diff --git a/bootloader/sansaconnect.c b/bootloader/sansaconnect.c
index 6b2a7e6124..bd6a4b78ff 100644
--- a/bootloader/sansaconnect.c
+++ b/bootloader/sansaconnect.c
@@ -27,6 +27,7 @@
27#include "backlight.h" 27#include "backlight.h"
28#include "button.h" 28#include "button.h"
29#include "common.h" 29#include "common.h"
30#include "rb-loader.h"
30#include "version.h" 31#include "version.h"
31#include "uart-target.h" 32#include "uart-target.h"
32#include "power.h" 33#include "power.h"
@@ -115,11 +116,11 @@ void main(void)
115 116
116 ret = load_firmware(loadbuffer, BOOTFILE, buffer_size); 117 ret = load_firmware(loadbuffer, BOOTFILE, buffer_size);
117 118
118 if(ret < 0) 119 if(ret <= EFILE_EMPTY)
119 { 120 {
120 error(EBOOTFILE, ret, true); 121 error(EBOOTFILE, ret, true);
121 } 122 }
122 else if(ret == EOK) 123 else
123 { 124 {
124 system_prepare_fw_start(); 125 system_prepare_fw_start();
125 126
diff --git a/bootloader/telechips.c b/bootloader/telechips.c
index fca475e20d..af4ec72bc4 100644
--- a/bootloader/telechips.c
+++ b/bootloader/telechips.c
@@ -43,6 +43,8 @@
43#include "power.h" 43#include "power.h"
44#include "file.h" 44#include "file.h"
45#include "common.h" 45#include "common.h"
46#include "rb-loader.h"
47#include "loader_strerror.h"
46#include "version.h" 48#include "version.h"
47 49
48/* Show the Rockbox logo - in show_logo.c */ 50/* Show the Rockbox logo - in show_logo.c */
@@ -170,11 +172,11 @@ void* main(void)
170 172
171 rc = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE); 173 rc = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE);
172 174
173 if (rc < 0) 175 if (rc <= EFILE_EMPTY)
174 { 176 {
175 error(EBOOTFILE,rc, true); 177 error(EBOOTFILE,rc, true);
176 } 178 }
177 else if (rc == EOK) 179 else
178 { 180 {
179 int(*kernel_entry)(void) = (void *) loadbuffer; 181 int(*kernel_entry)(void) = (void *) loadbuffer;
180 182
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 54e4530ea9..5f1ae3d31c 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -35,6 +35,9 @@ load_code.c
35#ifdef RB_PROFILE 35#ifdef RB_PROFILE
36profile.c 36profile.c
37#endif /* RB_PROFILE */ 37#endif /* RB_PROFILE */
38#if !defined(RKW_FORMAT) && !defined(MI4_FORMAT) && defined(MODEL_NUMBER)
39common/rb-loader.c
40#endif
38#if !defined(BOOTLOADER) || defined(CPU_SH) 41#if !defined(BOOTLOADER) || defined(CPU_SH)
39rolo.c 42rolo.c
40#endif /* !defined(BOOTLOADER) || defined(CPU_SH) */ 43#endif /* !defined(BOOTLOADER) || defined(CPU_SH) */
@@ -139,6 +142,9 @@ libc/gmtime.c
139common/version.c 142common/version.c
140common/config.c 143common/config.c
141common/crc32.c 144common/crc32.c
145#ifdef MODEL_NUMBER
146common/loader_strerror.c
147#endif
142#ifdef MI4_FORMAT 148#ifdef MI4_FORMAT
143common/crc32-mi4.c 149common/crc32-mi4.c
144#endif 150#endif
@@ -594,6 +600,7 @@ target/arm/as3525/pcm-as3525.c
594target/arm/pp/i2s-pp.c 600target/arm/pp/i2s-pp.c
595target/arm/pp/kernel-pp.c 601target/arm/pp/kernel-pp.c
596target/arm/pp/timer-pp.c 602target/arm/pp/timer-pp.c
603target/arm/pp/mi4-loader.c
597# if CONFIG_STORAGE & STORAGE_SD 604# if CONFIG_STORAGE & STORAGE_SD
598target/arm/pp/ata-sd-pp.c 605target/arm/pp/ata-sd-pp.c
599# endif 606# endif
diff --git a/firmware/common/loader_strerror.c b/firmware/common/loader_strerror.c
new file mode 100644
index 0000000000..8dcd19d18f
--- /dev/null
+++ b/firmware/common/loader_strerror.c
@@ -0,0 +1,63 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2013 Marcin Bukat
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "loader_strerror.h"
22
23char *loader_strerror(enum error_t error)
24{
25 switch(error)
26 {
27 case EFILE_EMPTY:
28 return "File empty";
29 case EFILE_NOT_FOUND:
30 return "File not found";
31 case EREAD_CHKSUM_FAILED:
32 return "Read failed (chksum)";
33 case EREAD_MODEL_FAILED:
34 return "Read failed (model)";
35 case EREAD_IMAGE_FAILED:
36 return "Read failed (image)";
37 case EBAD_CHKSUM:
38 return "Bad checksum";
39 case EFILE_TOO_BIG:
40 return "File too big";
41 case EINVALID_FORMAT:
42 return "Invalid file format";
43#if defined(MI4_FORMAT)
44 case EREAD_HEADER_FAILED:
45 return "Can't read mi4 header";
46 case EKEY_NOT_FOUND:
47 return "Can't find crypt key";
48 case EDECRYPT_FAILED:
49 return "Decryption failed";
50#elif defined(RKW_FORMAT)
51 case EREAD_HEADER_FAILED:
52 return "Can't read RKW header";
53 case EBAD_HEADER_CHKSUM:
54 return "RKW header CRC error";
55 case EINVALID_LOAD_ADDR:
56 return "RKW Load address mismatch";
57 case EBAD_MODEL:
58 return "Bad model number";
59#endif
60 default:
61 return "Unknown error";
62 }
63}
diff --git a/firmware/common/rb-loader.c b/firmware/common/rb-loader.c
new file mode 100644
index 0000000000..10807f9c96
--- /dev/null
+++ b/firmware/common/rb-loader.c
@@ -0,0 +1,115 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 by Linus Nielsen Feltzing
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 1
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include <stdio.h>
22#include "config.h"
23#include "system.h"
24#include "file.h"
25#include "rb-loader.h"
26#include "loader_strerror.h"
27
28/* Load firmware image in a format created by add method of tools/scramble
29 * on success we return size loaded image
30 * on error we return negative value which can be deciphered by means
31 * of strerror() function
32 */
33int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
34{
35 char filename[MAX_PATH];
36 int fd;
37 int rc;
38 int len;
39 int ret = 0;
40 unsigned long chksum;
41 unsigned long sum;
42 int i;
43
44 /* only filename passed */
45 if (firmware[0] != '/')
46 {
47 /* First check in BOOTDIR */
48 snprintf(filename, sizeof(filename), BOOTDIR "/%s",firmware);
49
50 fd = open(filename, O_RDONLY);
51 if(fd < 0)
52 {
53 /* Check in root dir */
54 snprintf(filename, sizeof(filename),"/%s",firmware);
55 fd = open(filename, O_RDONLY);
56
57 if (fd < 0)
58 return EFILE_NOT_FOUND;
59 }
60 }
61 else
62 {
63 /* full path passed */
64 fd = open(firmware, O_RDONLY);
65 if (fd < 0)
66 return EFILE_NOT_FOUND;
67 }
68
69 len = filesize(fd) - 8;
70
71 if (len > buffer_size)
72 {
73 ret = EFILE_TOO_BIG;
74 goto end;
75 }
76
77 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
78
79 rc = read(fd, &chksum, 4);
80 chksum = betoh32(chksum); /* Rockbox checksums are big-endian */
81 if(rc < 4)
82 {
83 ret = EREAD_CHKSUM_FAILED;
84 goto end;
85 }
86
87 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
88
89 rc = read(fd, buf, len);
90 if(rc < len)
91 {
92 ret = EREAD_IMAGE_FAILED;
93 goto end;
94 }
95
96 sum = MODEL_NUMBER;
97
98 for(i = 0;i < len;i++)
99 {
100 sum += buf[i];
101 }
102
103 if(sum != chksum)
104 {
105 ret = EBAD_CHKSUM;
106 goto end;
107 }
108
109 ret = len;
110
111end:
112 close(fd);
113 return ret;
114}
115
diff --git a/firmware/export/mi4-loader.h b/firmware/export/mi4-loader.h
new file mode 100644
index 0000000000..1b4a4b93b2
--- /dev/null
+++ b/firmware/export/mi4-loader.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2006 by Barry Wardell
10 *
11 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
12 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include <stdint.h>
25
26#define MI4_HEADER_SIZE 0x200
27
28/* mi4 header structure */
29struct mi4header_t {
30 unsigned char magic[4];
31 uint32_t version;
32 uint32_t length;
33 uint32_t crc32;
34 uint32_t enctype;
35 uint32_t mi4size;
36 uint32_t plaintext;
37 uint32_t dsa_key[10];
38 uint32_t pad[109];
39 unsigned char type[4];
40 unsigned char model[4];
41};
42
43struct tea_key {
44 const char * name;
45 uint32_t key[4];
46};
47
48#define NUM_KEYS (sizeof(tea_keytable)/sizeof(tea_keytable[0]))
49
50int load_mi4(unsigned char* buf, const char* firmware, unsigned int buffer_size);
51const char *mi4_strerror(int8_t errno);
diff --git a/firmware/include/loader_strerror.h b/firmware/include/loader_strerror.h
new file mode 100644
index 0000000000..e36036a8c0
--- /dev/null
+++ b/firmware/include/loader_strerror.h
@@ -0,0 +1,38 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2013 Marcin Bukat
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21enum error_t {
22 EFILE_EMPTY = 0,
23 EFILE_NOT_FOUND = -1,
24 EREAD_CHKSUM_FAILED = -2,
25 EREAD_MODEL_FAILED = -3,
26 EREAD_IMAGE_FAILED = -4,
27 EBAD_CHKSUM = -5,
28 EFILE_TOO_BIG = -6,
29 EINVALID_FORMAT = -7,
30 EKEY_NOT_FOUND = -8,
31 EDECRYPT_FAILED = -9,
32 EREAD_HEADER_FAILED = -10,
33 EBAD_HEADER_CHKSUM = -11,
34 EINVALID_LOAD_ADDR = -12,
35 EBAD_MODEL = -13
36};
37
38char *loader_strerror(enum error_t error);
diff --git a/firmware/include/rb-loader.h b/firmware/include/rb-loader.h
new file mode 100644
index 0000000000..e1e756dba9
--- /dev/null
+++ b/firmware/include/rb-loader.h
@@ -0,0 +1,22 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 by Linus Nielsen Feltzing
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 1
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21const char *rb_strerror(int8_t errno);
22int load_firmware(unsigned char* buf, const char* firmware, int buffer_size);
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 567c880bd4..325e17e97f 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -37,16 +37,17 @@
37#include "storage.h" 37#include "storage.h"
38#include "rolo.h" 38#include "rolo.h"
39 39
40#ifdef MI4_FORMAT 40#include "loader_strerror.h"
41#if defined(MI4_FORMAT)
41#include "crc32-mi4.h" 42#include "crc32-mi4.h"
42#undef FIRMWARE_OFFSET_FILE_CRC 43#include "mi4-loader.h"
43#undef FIRMWARE_OFFSET_FILE_DATA 44#define LOAD_FIRMWARE(a,b,c) load_mi4(a,b,c)
44#define FIRMWARE_OFFSET_FILE_CRC 0xC 45#elif defined(RKW_FORMAT)
45#define FIRMWARE_OFFSET_FILE_DATA 0x200
46#endif
47
48#ifdef RKW_FORMAT
49#include "rkw-loader.h" 46#include "rkw-loader.h"
47#define LOAD_FIRMWARE(a,b,c) load_rkw(a,b,c)
48#else
49#include "rb-loader.h"
50#define LOAD_FIRMWARE(a,b,c) load_firmware(a,b,c)
50#endif 51#endif
51 52
52#if !defined(IRIVER_IFP7XX_SERIES) 53#if !defined(IRIVER_IFP7XX_SERIES)
@@ -206,7 +207,7 @@ extern unsigned long loadaddress;
206 * Filename must be a fully defined filename including the path and extension 207 * Filename must be a fully defined filename including the path and extension
207 * 208 *
208 ***************************************************************************/ 209 ***************************************************************************/
209#ifdef RKW_FORMAT 210#if defined(CPU_COLDFIRE) || defined(CPU_ARM) || defined(CPU_MIPS)
210int rolo_load(const char* filename) 211int rolo_load(const char* filename)
211{ 212{
212 unsigned char* ramstart = (void*)&loadaddress; 213 unsigned char* ramstart = (void*)&loadaddress;
@@ -232,15 +233,26 @@ int rolo_load(const char* filename)
232 rolo_handle = core_alloc_maximum("rolo", &filebuf_size, NULL); 233 rolo_handle = core_alloc_maximum("rolo", &filebuf_size, NULL);
233 filebuf = core_get_data(rolo_handle); 234 filebuf = core_get_data(rolo_handle);
234 235
235 errno = load_rkw(filebuf, filename, filebuf_size); 236 errno = LOAD_FIRMWARE(filebuf, filename, filebuf_size);
236 if (errno < 0) 237
238 if (errno <= 0)
237 { 239 {
238 rolo_error(rkw_strerror(errno)); 240 rolo_error(loader_strerror(errno));
239 return -1; 241 return -1;
240 } 242 }
241 else 243 else
242 length = errno; 244 length = errno;
243 245
246#if defined(CPU_PP) && NUM_CORES > 1
247 lcd_puts(0, 2, "Waiting for coprocessor...");
248 lcd_update();
249 rolo_restart_cop();
250 /* Wait for COP to be in safe code */
251 while(cpu_reply != 1);
252 lcd_puts(0, 2, " ");
253 lcd_update();
254#endif
255
244#ifdef HAVE_STORAGE_FLUSH 256#ifdef HAVE_STORAGE_FLUSH
245 lcd_puts(0, 1, "Flushing storage buffers"); 257 lcd_puts(0, 1, "Flushing storage buffers");
246 lcd_update(); 258 lcd_update();
@@ -255,27 +267,29 @@ int rolo_load(const char* filename)
255#endif 267#endif
256 adc_close(); 268 adc_close();
257 269
270#if CONFIG_CPU != IMX31L /* We're not finished yet */
271#ifdef CPU_ARM
272 /* Should do these together since some ARM version should never have
273 * FIQ disabled and not IRQ (imx31 errata). */
258 disable_interrupt(IRQ_FIQ_STATUS); 274 disable_interrupt(IRQ_FIQ_STATUS);
275#else
276 /* Some targets have a higher disable level than HIGEST_IRQ_LEVEL */
277 set_irq_level(DISABLE_INTERRUPTS);
278#endif
279#endif /* CONFIG_CPU == IMX31L */
259 280
260 rolo_restart(filebuf, ramstart, length); 281 rolo_restart(filebuf, ramstart, length);
261 282
262 /* never reached */ 283 /* never reached */
263 return 0; 284 return 0;
264} 285}
265#else 286#else /* defined(CPU_SH) */
266int rolo_load(const char* filename) 287int rolo_load(const char* filename)
267{ 288{
268 int fd; 289 int fd;
269 long length; 290 long length;
270#if defined(CPU_COLDFIRE) || defined(CPU_ARM) || defined(CPU_MIPS)
271#if !defined(MI4_FORMAT)
272 int i;
273#endif
274 unsigned long checksum,file_checksum;
275#else
276 long file_length; 291 long file_length;
277 unsigned short checksum,file_checksum; 292 unsigned short checksum,file_checksum;
278#endif
279 unsigned char* ramstart = (void*)&loadaddress; 293 unsigned char* ramstart = (void*)&loadaddress;
280 unsigned char* filebuf; 294 unsigned char* filebuf;
281 size_t filebuf_size; 295 size_t filebuf_size;
@@ -306,87 +320,6 @@ int rolo_load(const char* filename)
306 rolo_handle = core_alloc_maximum("rolo", &filebuf_size, NULL); 320 rolo_handle = core_alloc_maximum("rolo", &filebuf_size, NULL);
307 filebuf = core_get_data(rolo_handle); 321 filebuf = core_get_data(rolo_handle);
308 322
309#if CONFIG_CPU != SH7034
310 /* Read and save checksum */
311 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
312 if (read(fd, &file_checksum, 4) != 4) {
313 rolo_error("Error Reading checksum");
314 return -1;
315 }
316
317#if !defined(MI4_FORMAT)
318 /* Rockbox checksums are big-endian */
319 file_checksum = betoh32(file_checksum);
320#endif
321
322#if defined(CPU_PP) && NUM_CORES > 1
323 lcd_puts(0, 2, "Waiting for coprocessor...");
324 lcd_update();
325 rolo_restart_cop();
326 /* Wait for COP to be in safe code */
327 while(cpu_reply != 1);
328 lcd_puts(0, 2, " ");
329 lcd_update();
330#endif
331
332 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
333
334 /* this shouldn't happen, but well */
335 if ((long)filebuf_size < length)
336 {
337 rolo_error("File too big");
338 return -1;
339 }
340
341 if (read(fd, filebuf, length) != length) {
342 rolo_error("Error Reading File");
343 return -1;
344 }
345
346#ifdef MI4_FORMAT
347 /* Check CRC32 to see if we have a valid file */
348 chksum_crc32gentab();
349 checksum = chksum_crc32 (filebuf, length);
350#else
351 checksum = MODEL_NUMBER;
352
353 for(i = 0;i < length;i++) {
354 checksum += filebuf[i];
355 }
356#endif
357
358 /* Verify checksum against file header */
359 if (checksum != file_checksum) {
360 rolo_error("Checksum Error");
361 return -1;
362 }
363
364#ifdef HAVE_STORAGE_FLUSH
365 lcd_puts(0, 1, "Flushing storage buffers");
366 lcd_update();
367 storage_flush();
368#endif
369
370 lcd_puts(0, 1, "Executing");
371 lcd_update();
372#ifdef HAVE_REMOTE_LCD
373 lcd_remote_puts(0, 1, "Executing");
374 lcd_remote_update();
375#endif
376 adc_close();
377
378#if CONFIG_CPU != IMX31L /* We're not finished yet */
379#ifdef CPU_ARM
380 /* Should do these together since some ARM version should never have
381 * FIQ disabled and not IRQ (imx31 errata). */
382 disable_interrupt(IRQ_FIQ_STATUS);
383#else
384 /* Some targets have a higher disable level than HIGEST_IRQ_LEVEL */
385 set_irq_level(DISABLE_INTERRUPTS);
386#endif
387#endif /* CONFIG_CPU == IMX31L */
388
389#else /* CONFIG_CPU == SH7034 */
390 /* Read file length from header and compare to real file length */ 323 /* Read file length from header and compare to real file length */
391 lseek(fd, FIRMWARE_OFFSET_FILE_LENGTH, SEEK_SET); 324 lseek(fd, FIRMWARE_OFFSET_FILE_LENGTH, SEEK_SET);
392 if(read(fd, &file_length, 4) != 4) { 325 if(read(fd, &file_length, 4) != 4) {
@@ -451,13 +384,12 @@ int rolo_load(const char* filename)
451 defined(ARCHOS_FMRECORDER) 384 defined(ARCHOS_FMRECORDER)
452 PAIOR = 0x0FA0; 385 PAIOR = 0x0FA0;
453#endif 386#endif
454#endif
455 rolo_restart(filebuf, ramstart, length); 387 rolo_restart(filebuf, ramstart, length);
456 388
457 return 0; /* this is never reached */ 389 return 0; /* this is never reached */
458 (void)checksum; (void)file_checksum; 390 (void)checksum; (void)file_checksum;
459} 391}
460#endif /* ifdef RKW_FORMAT */ 392#endif /* */
461#else /* !defined(IRIVER_IFP7XX_SERIES) */ 393#else /* !defined(IRIVER_IFP7XX_SERIES) */
462int rolo_load(const char* filename) 394int rolo_load(const char* filename)
463{ 395{
diff --git a/firmware/target/arm/pp/mi4-loader.c b/firmware/target/arm/pp/mi4-loader.c
new file mode 100644
index 0000000000..c465b898b4
--- /dev/null
+++ b/firmware/target/arm/pp/mi4-loader.c
@@ -0,0 +1,237 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2006 by Barry Wardell
10 *
11 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
12 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include <stdbool.h>
25#include <stdio.h>
26#include "config.h"
27#include "mi4-loader.h"
28#include "loader_strerror.h"
29#include "crc32-mi4.h"
30#include "file.h"
31
32static inline unsigned int le2int(unsigned char* buf)
33{
34 int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
35
36 return res;
37}
38
39static inline void int2le(unsigned int val, unsigned char* addr)
40{
41 addr[0] = val & 0xFF;
42 addr[1] = (val >> 8) & 0xff;
43 addr[2] = (val >> 16) & 0xff;
44 addr[3] = (val >> 24) & 0xff;
45}
46
47static struct tea_key tea_keytable[] = {
48 { "default" , { 0x20d36cc0, 0x10e8c07d, 0xc0e7dcaa, 0x107eb080 } },
49 { "sansa", { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 } },
50 { "sansa_gh", { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 } },
51 { "sansa_103", { 0x1d29ddc0, 0x2579c2cd, 0xce339e1a, 0x75465dfe } },
52 { "rhapsody", { 0x7aa9c8dc, 0xbed0a82a, 0x16204cc7, 0x5904ef38 } },
53 { "p610", { 0x950e83dc, 0xec4907f9, 0x023734b9, 0x10cfb7c7 } },
54 { "p640", { 0x220c5f23, 0xd04df68e, 0x431b5e25, 0x4dcc1fa1 } },
55 { "virgin", { 0xe83c29a1, 0x04862973, 0xa9b3f0d4, 0x38be2a9c } },
56 { "20gc_eng", { 0x0240772c, 0x6f3329b5, 0x3ec9a6c5, 0xb0c9e493 } },
57 { "20gc_fre", { 0xbede8817, 0xb23bfe4f, 0x80aa682d, 0xd13f598c } },
58 { "elio_p722", { 0x6af3b9f8, 0x777483f5, 0xae8181cc, 0xfa6d8a84 } },
59 { "c200", { 0xbf2d06fa, 0xf0e23d59, 0x29738132, 0xe2d04ca7 } },
60 { "c200_103", { 0x2a7968de, 0x15127979, 0x142e60a7, 0xe49c1893 } },
61 { "c200_106", { 0xa913d139, 0xf842f398, 0x3e03f1a6, 0x060ee012 } },
62 { "view", { 0x70e19bda, 0x0c69ea7d, 0x2b8b1ad1, 0xe9767ced } },
63 { "sa9200", { 0x33ea0236, 0x9247bdc5, 0xdfaedf9f, 0xd67c9d30 } },
64 { "hdd1630/hdd63x0", { 0x04543ced, 0xcebfdbad, 0xf7477872, 0x0d12342e } },
65 { "vibe500", { 0xe3a66156, 0x77c6b67a, 0xe821dca5, 0xca8ca37c } },
66};
67
68/*
69
70tea_decrypt() from http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
71
72"Following is an adaptation of the reference encryption and decryption
73routines in C, released into the public domain by David Wheeler and
74Roger Needham:"
75
76*/
77
78/* NOTE: The mi4 version of TEA uses a different initial value to sum compared
79 to the reference implementation and the main loop is 8 iterations, not
80 32.
81*/
82
83static void tea_decrypt(uint32_t* v0, uint32_t* v1, uint32_t* k) {
84 uint32_t sum=0xF1BBCDC8, i; /* set up */
85 uint32_t delta=0x9E3779B9; /* a key schedule constant */
86 uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
87 for(i=0; i<8; i++) { /* basic cycle start */
88 *v1 -= ((*v0<<4) + k2) ^ (*v0 + sum) ^ ((*v0>>5) + k3);
89 *v0 -= ((*v1<<4) + k0) ^ (*v1 + sum) ^ ((*v1>>5) + k1);
90 sum -= delta; /* end cycle */
91 }
92}
93
94/* mi4 files are encrypted in 64-bit blocks (two little-endian 32-bit
95 integers) and the key is incremented after each block
96 */
97
98static void tea_decrypt_buf(unsigned char* src,
99 unsigned char* dest,
100 size_t n, uint32_t * key)
101{
102 uint32_t v0, v1;
103 unsigned int i;
104
105 for (i = 0; i < (n / 8); i++) {
106 v0 = le2int(src);
107 v1 = le2int(src+4);
108
109 tea_decrypt(&v0, &v1, key);
110
111 int2le(v0, dest);
112 int2le(v1, dest+4);
113
114 src += 8;
115 dest += 8;
116
117 /* Now increment the key */
118 key[0]++;
119 if (key[0]==0) {
120 key[1]++;
121 if (key[1]==0) {
122 key[2]++;
123 if (key[2]==0) {
124 key[3]++;
125 }
126 }
127 }
128 }
129}
130
131static int tea_find_key(struct mi4header_t *mi4header, unsigned char* buf)
132{
133 unsigned int i;
134 uint32_t key[4];
135 uint32_t keyinc;
136 unsigned char magic_dec[8];
137 int key_found = -1;
138 unsigned int magic_location = mi4header->length-4;
139 int unaligned = 0;
140
141 if ( (magic_location % 8) != 0 )
142 {
143 unaligned = 1;
144 magic_location -= 4;
145 }
146
147 for (i=0; i < NUM_KEYS && (key_found<0) ; i++) {
148 key[0] = tea_keytable[i].key[0];
149 key[1] = tea_keytable[i].key[1];
150 key[2] = tea_keytable[i].key[2];
151 key[3] = tea_keytable[i].key[3];
152
153 /* Now increment the key */
154 keyinc = (magic_location-mi4header->plaintext)/8;
155 if ((key[0]+keyinc) < key[0]) key[1]++;
156 key[0] += keyinc;
157 if (key[1]==0) key[2]++;
158 if (key[2]==0) key[3]++;
159
160 /* Decrypt putative magic */
161 tea_decrypt_buf(&buf[magic_location], magic_dec, 8, key);
162
163 if (le2int(&magic_dec[4*unaligned]) == 0xaa55aa55)
164 {
165 key_found = i;
166 }
167 }
168
169 return key_found;
170}
171
172/* Load mi4 format firmware image */
173int load_mi4(unsigned char* buf,
174 const char* firmware,
175 unsigned int buffer_size)
176{
177 int fd;
178 struct mi4header_t mi4header;
179 int rc;
180 unsigned long sum;
181 char filename[MAX_PATH];
182
183 snprintf(filename,sizeof(filename), BOOTDIR "/%s",firmware);
184 fd = open(filename, O_RDONLY);
185 if(fd < 0)
186 {
187 snprintf(filename,sizeof(filename),"/%s",firmware);
188 fd = open(filename, O_RDONLY);
189 if(fd < 0)
190 return EFILE_NOT_FOUND;
191 }
192
193 read(fd, &mi4header, MI4_HEADER_SIZE);
194
195 /* MI4 file size */
196 if ((mi4header.mi4size-MI4_HEADER_SIZE) > buffer_size)
197 {
198 close(fd);
199 return EFILE_TOO_BIG;
200 }
201
202 /* Load firmware file */
203 lseek(fd, MI4_HEADER_SIZE, SEEK_SET);
204 rc = read(fd, buf, mi4header.mi4size-MI4_HEADER_SIZE);
205 close(fd);
206 if(rc < (int)mi4header.mi4size-MI4_HEADER_SIZE)
207 return EREAD_IMAGE_FAILED;
208
209 /* Check CRC32 to see if we have a valid file */
210 sum = chksum_crc32 (buf, mi4header.mi4size - MI4_HEADER_SIZE);
211
212 if(sum != mi4header.crc32)
213 return EBAD_CHKSUM;
214
215 if( (mi4header.plaintext + MI4_HEADER_SIZE) != mi4header.mi4size)
216 {
217 /* Load encrypted firmware */
218 int key_index = tea_find_key(&mi4header, buf);
219
220 if (key_index < 0)
221 return EINVALID_FORMAT;
222
223 /* Plaintext part is already loaded */
224 buf += mi4header.plaintext;
225
226 /* Decrypt in-place */
227 tea_decrypt_buf(buf, buf,
228 mi4header.mi4size-(mi4header.plaintext+MI4_HEADER_SIZE),
229 tea_keytable[key_index].key);
230
231 /* Check decryption was successfull */
232 if(le2int(&buf[mi4header.length-mi4header.plaintext-4]) != 0xaa55aa55)
233 return EREAD_IMAGE_FAILED;
234 }
235
236 return mi4header.mi4size - MI4_HEADER_SIZE;
237}
diff --git a/firmware/target/arm/rk27xx/rkw-loader.c b/firmware/target/arm/rk27xx/rkw-loader.c
index ed7e253f14..9b50e1b187 100644
--- a/firmware/target/arm/rk27xx/rkw-loader.c
+++ b/firmware/target/arm/rk27xx/rkw-loader.c
@@ -18,42 +18,22 @@
18 * 18 *
19 ****************************************************************************/ 19 ****************************************************************************/
20 20
21#include <stdio.h>
21#include "config.h" 22#include "config.h"
23#include "loader_strerror.h"
22#include "rkw-loader.h" 24#include "rkw-loader.h"
23#include "crc32-rkw.h" 25#include "crc32-rkw.h"
24#include "file.h" 26#include "file.h"
25#include "panic.h" 27#include "panic.h"
26 28
27/* error strings sorted by number */
28/* error 0 is empty */
29static const char *err_str[] = {
30 "Loading OK",
31 "Can't open RKW file",
32 "Can't read RKW header",
33 "Invalid RKW magic number",
34 "RKW header CRC error",
35 "RKW file too big",
36 "RKW Load address mismatch",
37 "Bad model number",
38 "Error Reading File",
39 "RKW firmware CRC error"
40};
41
42const char *rkw_strerror(int8_t errno)
43{
44 if ((uint8_t)-errno >= sizeof(err_str)/sizeof(err_str[0]) || errno > 0)
45 return "Unknown error";
46
47 return err_str[-errno];
48}
49
50/* loosely based on load_firmware() 29/* loosely based on load_firmware()
51 * on success we return size loaded image 30 * on success we return size of loaded image
52 * on error we return negative value which can be deciphered by means 31 * on error we return negative value which can be deciphered by means
53 * of rkw_strerror() function 32 * of rkw_strerror() function
54 */ 33 */
55int load_rkw(unsigned char* buf, const char* filename, int buffer_size) 34int load_rkw(unsigned char* buf, const char* firmware, int buffer_size)
56{ 35{
36 char filename[MAX_PATH];
57 int fd; 37 int fd;
58 int rc; 38 int rc;
59 int len; 39 int len;
@@ -61,22 +41,42 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
61 uint32_t crc, fw_crc; 41 uint32_t crc, fw_crc;
62 struct rkw_header_t rkw_info; 42 struct rkw_header_t rkw_info;
63 43
64 fd = open(filename, O_RDONLY); 44 /* only filename passed */
45 if (firmware[0] != '/')
46 {
47 /* First check in BOOTDIR */
48 snprintf(filename, sizeof(filename), BOOTDIR "/%s",firmware);
65 49
66 if(fd < 0) 50 fd = open(filename, O_RDONLY);
67 return -1; 51 if(fd < 0)
52 {
53 /* Check in root dir */
54 snprintf(filename, sizeof(filename),"/%s",firmware);
55 fd = open(filename, O_RDONLY);
56
57 if (fd < 0)
58 return EFILE_NOT_FOUND;
59 }
60 }
61 else
62 {
63 /* full path passed */
64 fd = open(firmware, O_RDONLY);
65 if (fd < 0)
66 return EFILE_NOT_FOUND;
67 }
68 68
69 rc = read(fd, &rkw_info, sizeof(rkw_info)); 69 rc = read(fd, &rkw_info, sizeof(rkw_info));
70 if (rc < (int)sizeof(rkw_info)) 70 if (rc < (int)sizeof(rkw_info))
71 { 71 {
72 ret = -2; 72 ret = EREAD_HEADER_FAILED;
73 goto end; 73 goto end;
74 } 74 }
75 75
76 /* check if RKW is valid */ 76 /* check if RKW is valid */
77 if (rkw_info.magic_number != RKLD_MAGIC) 77 if (rkw_info.magic_number != RKLD_MAGIC)
78 { 78 {
79 ret = -3; 79 ret = EINVALID_FORMAT;
80 goto end; 80 goto end;
81 } 81 }
82 82
@@ -86,7 +86,7 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
86 crc = crc32_rkw((uint8_t *)&rkw_info, sizeof(rkw_info)-sizeof(uint32_t)); 86 crc = crc32_rkw((uint8_t *)&rkw_info, sizeof(rkw_info)-sizeof(uint32_t));
87 if (rkw_info.crc != crc) 87 if (rkw_info.crc != crc)
88 { 88 {
89 ret = -4; 89 ret = EBAD_HEADER_CHKSUM;
90 goto end; 90 goto end;
91 } 91 }
92 } 92 }
@@ -95,14 +95,14 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
95 len = rkw_info.load_limit - rkw_info.load_address; 95 len = rkw_info.load_limit - rkw_info.load_address;
96 if (len > buffer_size) 96 if (len > buffer_size)
97 { 97 {
98 ret = -5; 98 ret = EFILE_TOO_BIG;
99 goto end; 99 goto end;
100 } 100 }
101 101
102 /* check load address - we support loading only at 0x60000000 */ 102 /* check load address - we support loading only at 0x60000000 */
103 if (rkw_info.load_address != 0x60000000) 103 if (rkw_info.load_address != 0x60000000)
104 { 104 {
105 ret = -6; 105 ret = EINVALID_LOAD_ADDR;
106 goto end; 106 goto end;
107 } 107 }
108 108
@@ -112,7 +112,7 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
112 */ 112 */
113 if (rkw_info.reserved0 != 0 && rkw_info.reserved0 != MODEL_NUMBER) 113 if (rkw_info.reserved0 != 0 && rkw_info.reserved0 != MODEL_NUMBER)
114 { 114 {
115 ret = -7; 115 ret = EBAD_MODEL;
116 goto end; 116 goto end;
117 } 117 }
118 118
@@ -124,7 +124,7 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
124 124
125 if(rc < len) 125 if(rc < len)
126 { 126 {
127 ret = -8; 127 ret = EREAD_IMAGE_FAILED;
128 goto end; 128 goto end;
129 } 129 }
130 130
@@ -136,7 +136,7 @@ int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
136 136
137 if (fw_crc != crc) 137 if (fw_crc != crc)
138 { 138 {
139 ret = -9; 139 ret = EBAD_CHKSUM;
140 goto end; 140 goto end;
141 } 141 }
142 } 142 }