summaryrefslogtreecommitdiff
path: root/bootloader/ipod.c
diff options
context:
space:
mode:
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}