summaryrefslogtreecommitdiff
path: root/bootloader/ipod.c
diff options
context:
space:
mode:
authorBarry Wardell <rockbox@barrywardell.net>2007-01-28 18:42:11 +0000
committerBarry Wardell <rockbox@barrywardell.net>2007-01-28 18:42:11 +0000
commit84b509dc43cf84ef16fcd4a57b167351f146cd11 (patch)
tree57eca4b44db56e11c1a3d9dde5d0e4ef8e830686 /bootloader/ipod.c
parent6c3a44643590f8cbc925375c2dc8393cc7f9d55e (diff)
downloadrockbox-84b509dc43cf84ef16fcd4a57b167351f146cd11.tar.gz
rockbox-84b509dc43cf84ef16fcd4a57b167351f146cd11.zip
FS#6554. Move bootloader code into a common file. Only PortalPlayer devices (iPods, H10, Sansa) are affected for the moment. Someone with access to (and no fear of bricking) an X5, H100, H300 and Gigabeat should try to adapt those bootloaders to also use the code in common.c. The (non-working) patch in the tracker would be a good place to start with this.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12136 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'bootloader/ipod.c')
-rw-r--r--bootloader/ipod.c309
1 files changed, 69 insertions, 240 deletions
diff --git a/bootloader/ipod.c b/bootloader/ipod.c
index b1b3114ac9..73b4fffc71 100644
--- a/bootloader/ipod.c
+++ b/bootloader/ipod.c
@@ -39,16 +39,22 @@
39#include "panic.h" 39#include "panic.h"
40#include "power.h" 40#include "power.h"
41#include "file.h" 41#include "file.h"
42#include "common.h"
42 43
43#define XSC(X) #X 44#define XSC(X) #X
44#define SC(X) XSC(X) 45#define SC(X) XSC(X)
45 46
46#if (CONFIG_CPU == PP5020) 47/* Maximum allowed firmware image size. The largest known current
47#define DRAM_START 0x10000000 48 (December 2006) firmware is about 7.5MB (Apple's firmware for the ipod video)
48#else 49 so we set this to 8MB. */
49#define IPOD_LCD_BASE 0xc0001000 50#define MAX_LOADSIZE (8*1024*1024)
50#define DRAM_START 0x28000000 51
51#endif 52/* A buffer to load the Linux kernel or Rockbox into */
53unsigned char *loadbuffer = (unsigned char *)DRAM_START;
54
55/* Bootloader version */
56char version[] = APPSVERSION;
57
52#define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084))) 58#define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084)))
53 59
54/* We copy the hardware revision to the last four bytes of SDRAM and then 60/* We copy the hardware revision to the last four bytes of SDRAM and then
@@ -61,17 +67,6 @@
61#define BUTTON_PLAY 4 67#define BUTTON_PLAY 4
62#define BUTTON_HOLD 5 68#define BUTTON_HOLD 5
63 69
64/* Size of the buffer to store the loaded Rockbox/Linux/AppleOS image */
65
66/* The largest known current (December 2006) firmware is about 7.5MB
67 (Apple's firmware for the ipod video) so we set this to 8MB. */
68
69#define MAX_LOADSIZE (8*1024*1024)
70
71char version[] = APPSVERSION;
72
73int line=0;
74
75#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) 70#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
76/* check if number of seconds has past */ 71/* check if number of seconds has past */
77int timer_check(int clock_start, unsigned int usecs) 72int timer_check(int clock_start, unsigned int usecs)
@@ -157,54 +152,6 @@ int opto_keypad_read(void)
157} 152}
158#endif 153#endif
159 154
160char *strerror(int error)
161{
162 switch(error)
163 {
164 case 0:
165 return "OK";
166 case -1:
167 return "File not found";
168 case -2:
169 return "Read failed (chksum)";
170 case -3:
171 return "Read failed (model)";
172 case -4:
173 return "Read failed (image)";
174 case -5:
175 return "Bad checksum";
176 case -6:
177 return "File too big";
178 default:
179 return "Unknown";
180 }
181}
182
183char printfbuf[256];
184
185void reset_screen(void)
186{
187 lcd_clear_display();
188 line = 0;
189}
190
191void printf(const char *format, ...)
192{
193 int len;
194 unsigned char *ptr;
195 va_list ap;
196 va_start(ap, format);
197
198 ptr = printfbuf;
199 len = vsnprintf(ptr, sizeof(printfbuf), format, ap);
200 va_end(ap);
201
202 lcd_puts(0, line++, ptr);
203 lcd_update();
204 if(line >= (LCD_HEIGHT/SYSFONT_HEIGHT))
205 line = 0;
206}
207
208static int key_pressed(void) 155static int key_pressed(void)
209{ 156{
210 unsigned char state; 157 unsigned char state;
@@ -240,101 +187,9 @@ bool button_hold(void)
240 return (GPIOA_INPUT_VAL & 0x20)?false:true; 187 return (GPIOA_INPUT_VAL & 0x20)?false:true;
241} 188}
242 189
243int load_rockbox(unsigned char* buf, char* firmware)
244{
245 int fd;
246 int rc;
247 int len;
248 unsigned long chksum;
249 char model[5];
250 unsigned long sum;
251 int i;
252 char filename[MAX_PATH];
253
254 snprintf(filename,sizeof(filename),"/.rockbox/%s",firmware);
255 fd = open(filename, O_RDONLY);
256 if(fd < 0)
257 {
258 snprintf(filename,sizeof(filename),"/%s",firmware);
259 fd = open(filename, O_RDONLY);
260 if(fd < 0)
261 return -1;
262 }
263
264 len = filesize(fd) - 8;
265
266 if (len > MAX_LOADSIZE)
267 return -6;
268
269 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
270
271 rc = read(fd, &chksum, 4);
272 chksum=betoh32(chksum); /* Rockbox checksums are big-endian */
273 if(rc < 4)
274 return -2;
275
276 rc = read(fd, model, 4);
277 if(rc < 4)
278 return -3;
279
280 model[4] = 0;
281
282 printf("Model: %s", model);
283 printf("Checksum: %x", chksum);
284 printf("Loading %s", firmware);
285
286 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
287
288 rc = read(fd, buf, len);
289 if(rc < len)
290 return -4;
291
292 close(fd);
293
294 sum = MODEL_NUMBER;
295
296 for(i = 0;i < len;i++) {
297 sum += buf[i];
298 }
299
300 printf("Sum: %x", sum);
301
302 if(sum != chksum)
303 return -5;
304
305 return len;
306}
307
308
309int load_linux(unsigned char* buf) {
310 int fd;
311 int rc;
312 int len;
313
314 fd=open("/linux.bin",O_RDONLY);
315 if (fd < 0)
316 return -1;
317
318 len=filesize(fd);
319 if (len > MAX_LOADSIZE)
320 return -6;
321
322 rc=read(fd,buf,len);
323
324 if (rc < len)
325 return -4;
326
327 printf("Loaded Linux: %d bytes", len);
328
329 return len;
330}
331
332
333/* A buffer to load the Linux kernel or Rockbox into */
334unsigned char loadbuffer[MAX_LOADSIZE];
335
336void fatal_error(void) 190void fatal_error(void)
337{ 191{
192 extern int line;
338 bool holdstatus=false; 193 bool holdstatus=false;
339 194
340 /* System font is 6 pixels wide */ 195 /* System font is 6 pixels wide */
@@ -423,7 +278,6 @@ void* main(void)
423 button_init(); 278 button_init();
424#endif 279#endif
425 280
426 line=0;
427 281
428 lcd_setfont(FONT_SYSFIXED); 282 lcd_setfont(FONT_SYSFIXED);
429 283
@@ -459,95 +313,74 @@ void* main(void)
459 printf("Partition 1: 0x%02x %ld MB", 313 printf("Partition 1: 0x%02x %ld MB",
460 pinfo->type, pinfo->size / 2048); 314 pinfo->type, pinfo->size / 2048);
461 315
462 /* See if there is an Apple firmware image in RAM */ 316
463 haveretailos = (memcmp((void*)(DRAM_START+0x20),"portalplayer",12)==0); 317 /* Check for a keypress */
464 318 i=key_pressed();
465 /* We don't load Rockbox if the hold button is enabled. */
466 if (!button_was_held) {
467 /* Check for a keypress */
468 i=key_pressed();
469
470 if ((i!=BUTTON_MENU) && (i!=BUTTON_PLAY)) {
471 printf("Loading Rockbox...");
472 rc=load_rockbox(loadbuffer, BOOTFILE);
473 if (rc < 0) {
474 printf("Error!");
475 printf("Can't load rockbox.ipod:");
476 printf(strerror(rc));
477 } else {
478 printf("Rockbox loaded.");
479 memcpy((void*)DRAM_START,loadbuffer,rc);
480 return (void*)DRAM_START;
481 }
482 }
483 319
484 if (i==BUTTON_PLAY) { 320 if (button_was_held || (i==BUTTON_MENU)) {
485 printf("Loading Linux..."); 321 /* If either the hold switch was on, or the Menu button was held, then
486 rc=load_linux(loadbuffer); 322 try the Apple firmware */
487 if (rc < 0) { 323
488 printf("Error!"); 324 printf("Loading original firmware...");
489 printf("Can't load linux.bin:"); 325
490 printf(strerror(rc)); 326 /* First try an apple_os.ipod file on the FAT32 partition
491 } else { 327 (either in .rockbox or the root)
492 memcpy((void*)DRAM_START,loadbuffer,rc); 328 */
329
330 rc=load_firmware(loadbuffer, "apple_os.ipod", MAX_LOADSIZE);
331
332 if(rc==EFILE_NOT_FOUND) {
333 /* If apple_os.ipod doesn't exist, then check if there is an Apple
334 firmware image in RAM */
335 haveretailos = (memcmp((void*)(DRAM_START+0x20),"portalplayer",12)==0);
336 if (haveretailos) {
337 /* We have a copy of the retailos in RAM, lets just run it. */
493 return (void*)DRAM_START; 338 return (void*)DRAM_START;
494 } 339 }
340 } else if (rc < EFILE_NOT_FOUND) {
341 printf("Error!");
342 printf("Can't load apple_os.ipod:");
343 printf(strerror(rc));
344 } else if (rc > 0) {
345 printf("apple_os.ipod loaded.");
346 return (void*)DRAM_START;
347 }
348
349 /* Everything failed - just loop forever */
350 printf("No RetailOS detected");
351
352 } else if (i==BUTTON_PLAY) {
353 printf("Loading Linux...");
354 rc=load_raw_firmware(loadbuffer, "/linux.bin", MAX_LOADSIZE);
355 if (rc < EOK) {
356 printf("Error!");
357 printf("Can't load linux.bin:");
358 printf(strerror(rc));
359 } else {
360 return (void*)DRAM_START;
361 }
362 } else {
363 printf("Loading Rockbox...");
364 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
365 if (rc < EOK) {
366 printf("Error!");
367 printf("Can't load rockbox.ipod:");
368 printf(strerror(rc));
369 } else {
370 printf("Rockbox loaded.");
371 return (void*)DRAM_START;
495 } 372 }
496 } 373 }
497 374
498 375 /* If we get to here, then we haven't been able to load any firmware */
499 /* If either the hold switch was on, or loading Rockbox/IPL
500 failed, then try the Apple firmware */
501
502 printf("Loading original firmware...");
503
504 /* First try an apple_os.ipod file on the FAT32 partition
505 (either in .rockbox or the root)
506 */
507
508 rc=load_rockbox(loadbuffer, "apple_os.ipod");
509
510 /* Only report errors if the file was found */
511 if (rc < -1) {
512 printf("Error!");
513 printf("Can't load apple_os.ipod:");
514 printf(strerror(rc));
515 } else if (rc > 0) {
516 printf("apple_os.ipod loaded.");
517 memcpy((void*)DRAM_START,loadbuffer,rc);
518 return (void*)DRAM_START;
519 }
520
521 if (haveretailos) {
522 /* We have a copy of the retailos in RAM, lets just run it. */
523 return (void*)DRAM_START;
524 }
525
526 /* Everything failed - just loop forever */
527 printf("No RetailOS detected");
528
529 fatal_error(); 376 fatal_error();
530 377
531 /* We never get here, but keep gcc happy */ 378 /* We never get here, but keep gcc happy */
532 return (void*)0; 379 return (void*)0;
533} 380}
534 381
535/* These functions are present in the firmware library, but we reimplement 382/* These functions are present in the firmware library, but we reimplement
536 them here because the originals do a lot more than we want */ 383 them here because the originals do a lot more than we want */
537
538void reset_poweroff_timer(void)
539{
540}
541
542int dbg_ports(void)
543{
544 return 0;
545}
546
547void mpeg_stop(void)
548{
549}
550
551void usb_acknowledge(void) 384void usb_acknowledge(void)
552{ 385{
553} 386}
@@ -555,7 +388,3 @@ void usb_acknowledge(void)
555void usb_wait_for_disconnect(void) 388void usb_wait_for_disconnect(void)
556{ 389{
557} 390}
558
559void sys_poweroff(void)
560{
561}