1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Dave Chapman
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
37 #include "backlight.h"
45 #if (CONFIG_CPU == PP5020)
46 #define DRAM_START 0x10000000
48 #define IPOD_LCD_BASE 0xc0001000
49 #define DRAM_START 0x28000000
51 #define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084)))
53 /* We copy the hardware revision to the last four bytes of SDRAM and then
54 re-read it after we have re-mapped SDRAM to 0x0 in Rockbox */
55 #define TMP_IPOD_HW_REVISION (*((volatile unsigned long*)(0x11fffffc)))
59 #define BUTTON_RIGHT 3
63 /* Size of the buffer to store the loaded Rockbox/Linux image */
64 #define MAX_LOADSIZE (4*1024*1024)
66 char version
[] = APPSVERSION
;
68 typedef struct _image
{
69 unsigned type
; /* '' */
71 unsigned pad1
; /* 0000 0000 */
72 unsigned devOffset
; /* byte offset of start of image code */
73 unsigned len
; /* length in bytes of image */
74 void *addr
; /* load address */
75 unsigned entryOffset
; /* execution start within image */
76 unsigned chksum
; /* checksum for image */
77 unsigned vers
; /* image version */
78 unsigned loadAddr
; /* load address for image */
81 extern image_t boot_table
[];
85 static void memmove16(void *dest
, const void *src
, unsigned count
)
92 count
= (count
+ 15) >> 4;
93 d
= (struct bufstr
*) dest
;
94 s
= (struct bufstr
*) src
;
98 count
= (count
+ 15) >> 4;
99 d
= (struct bufstr
*)(dest
+ (count
<<4));
100 s
= (struct bufstr
*)(src
+ (count
<<4));
106 #if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI)
107 /* check if number of seconds has past */
108 int timer_check(int clock_start
, unsigned int usecs
)
110 if ((USEC_TIMER
- clock_start
) >= usecs
) {
117 static void ser_opto_keypad_cfg(int val
)
121 outl(inl(0x6000d004) & ~0x80, 0x6000d004);
123 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
124 outl(val
, 0x7000c120);
125 outl(inl(0x7000c100) | 0x80000000, 0x7000c100);
127 outl(inl(0x6000d024) & ~0x10, 0x6000d024);
128 outl(inl(0x6000d014) | 0x10, 0x6000d014);
130 start_time
= USEC_TIMER
;
132 if ((inl(0x7000c104) & 0x80000000) == 0) {
135 } while (timer_check(start_time
, 1500) != 0);
137 outl(inl(0x7000c100) & ~0x80000000, 0x7000c100);
139 outl(inl(0x6000d004) | 0x80, 0x6000d004);
140 outl(inl(0x6000d024) | 0x10, 0x6000d024);
141 outl(inl(0x6000d014) & ~0x10, 0x6000d014);
143 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
144 outl(inl(0x7000c100) | 0x60000000, 0x7000c100);
147 int opto_keypad_read(void)
149 int loop_cnt
, had_io
= 0;
151 for (loop_cnt
= 5; loop_cnt
!= 0;)
155 unsigned int key_pad_val
;
157 ser_opto_keypad_cfg(0x8000023a);
159 start_time
= USEC_TIMER
;
161 if (inl(0x7000c104) & 0x4000000) {
169 } while (timer_check(start_time
, 1500) != 0);
171 key_pad_val
= inl(0x7000c140);
172 if ((key_pad_val
& ~0x7fff0000) != 0x8000023a) {
175 key_pad_val
= (key_pad_val
<< 11) >> 27;
179 outl(inl(0x7000c100) | 0x60000000, 0x7000c100);
180 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
182 if (key_pressed
!= 0) {
183 return key_pad_val
^ 0x1f;
191 static int key_pressed(void)
195 #if CONFIG_KEYPAD == IPOD_4G_PAD
196 #ifdef IPOD_MINI /* mini 1G only */
197 state
= GPIOA_INPUT_VAL
& 0x3f;
198 if ((state
& 0x10) == 0) return BUTTON_LEFT
;
199 if ((state
& 0x2) == 0) return BUTTON_MENU
;
200 if ((state
& 0x4) == 0) return BUTTON_PLAY
;
201 if ((state
& 0x8) == 0) return BUTTON_RIGHT
;
203 state
= opto_keypad_read();
204 if ((state
& 0x4) == 0) return BUTTON_LEFT
;
205 if ((state
& 0x10) == 0) return BUTTON_MENU
;
206 if ((state
& 0x8) == 0) return BUTTON_PLAY
;
207 if ((state
& 0x2) == 0) return BUTTON_RIGHT
;
209 #elif CONFIG_KEYPAD == IPOD_3G_PAD
210 state
= inb(0xcf000030);
211 if (((state
& 0x20) == 0)) return BUTTON_HOLD
; /* hold on */
212 if ((state
& 0x08) == 0) return BUTTON_LEFT
;
213 if ((state
& 0x10) == 0) return BUTTON_MENU
;
214 if ((state
& 0x04) == 0) return BUTTON_PLAY
;
215 if ((state
& 0x01) == 0) return BUTTON_RIGHT
;
220 int load_rockbox(unsigned char* buf
)
225 unsigned long chksum
;
231 fd
= open("/.rockbox/" BOOTFILE
, O_RDONLY
);
234 fd
= open("/" BOOTFILE
, O_RDONLY
);
239 len
= filesize(fd
) - 8;
241 if (len
> MAX_LOADSIZE
)
244 lseek(fd
, FIRMWARE_OFFSET_FILE_CRC
, SEEK_SET
);
246 rc
= read(fd
, &chksum
, 4);
247 chksum
=betoh32(chksum
); /* Rockbox checksums are big-endian */
251 rc
= read(fd
, model
, 4);
257 snprintf(str
, 80, "Model: %s", model
);
258 lcd_puts(0, line
++, str
);
259 snprintf(str
, 80, "Checksum: %x", chksum
);
260 lcd_puts(0, line
++, str
);
263 lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
265 rc
= read(fd
, buf
, len
);
273 for(i
= 0;i
< len
;i
++) {
277 snprintf(str
, 80, "Sum: %x", sum
);
278 lcd_puts(0, line
++, str
);
288 int load_linux(unsigned char* buf
) {
294 fd
=open("/linux.bin",O_RDONLY
);
299 if (len
> MAX_LOADSIZE
)
307 snprintf(str
, 80, "Loaded Linux: %d bytes", len
);
308 lcd_puts(0, line
++, str
);
315 /* A buffer to load the Linux kernel or Rockbox into */
316 unsigned char loadbuffer
[MAX_LOADSIZE
];
324 int padding
= 0x4400;
325 image_t
*tblp
= boot_table
;
327 struct partinfo
* pinfo
;
328 unsigned short* identify_info
;
330 /* Turn on the backlight */
332 #if CONFIG_BACKLIGHT==BL_IPOD4G
333 /* brightness full */
334 outl(0x80000000 | (0xff << 16), 0x7000a010);
336 /* set port B03 on */
337 outl(((0x100 | 1) << 3), 0x6000d824);
339 #elif CONFIG_BACKLIGHT==BL_IPODMINI
340 /* set port B03 on */
341 outl(((0x100 | 1) << 3), 0x6000d824);
343 #elif CONFIG_BACKLIGHT==BL_IPODNANO
345 /* set port B03 on */
346 outl(((0x100 | 1) << 3), 0x6000d824);
348 /* set port L07 on */
349 outl(((0x100 | 1) << 7), 0x6000d12c);
350 #elif CONFIG_BACKLIGHT==BL_IPOD3G
351 outl(inl(IPOD_LCD_BASE
) | 0x2, IPOD_LCD_BASE
);
354 TMP_IPOD_HW_REVISION
= IPOD_HW_REVISION
;
355 ipod_hw_rev
= IPOD_HW_REVISION
;
363 /* ADC and button drivers are not yet implemented */
370 lcd_setfont(FONT_SYSFIXED
);
372 lcd_puts(0, line
++, "Rockbox boot loader");
373 snprintf(buf
, sizeof(buf
), "Version: 20%s", version
);
374 lcd_puts(0, line
++, buf
);
375 snprintf(buf
, sizeof(buf
), "IPOD version: 0x%08x", IPOD_HW_REVISION
);
376 lcd_puts(0, line
++, buf
);
381 identify_info
=ata_get_identify();
383 for (i
=0; i
< 20; i
++) {
384 ((unsigned short*)buf
)[i
]=htobe16(identify_info
[i
+27]);
387 for (i
=39; i
&& buf
[i
]==' '; i
--) {
390 lcd_puts(0, line
++, buf
);
393 snprintf(buf
, sizeof(buf
), "ATA: %d", i
);
394 lcd_puts(0, line
++, buf
);
399 rc
= disk_mount_all();
402 lcd_puts(0, line
++, "No partition found");
404 // while(button_get(true) != SYS_USB_CONNECTED) {};
407 pinfo
= disk_partinfo(1);
408 snprintf(buf
, sizeof(buf
), "Partition 1: 0x%02x %ld MB",
409 pinfo
->type
, pinfo
->size
/ 2048);
410 lcd_puts(0, line
++, buf
);
413 /* Check for a keypress */
416 if ((i
!=BUTTON_MENU
) && (i
!=BUTTON_PLAY
)) {
417 lcd_puts(0, line
, "Loading Rockbox...");
419 rc
=load_rockbox(loadbuffer
);
421 snprintf(buf
, sizeof(buf
), "Rockbox error: %d",rc
);
422 lcd_puts(0, line
++, buf
);
425 lcd_puts(0, line
++, "Rockbox loaded.");
427 memcpy((void*)DRAM_START
,loadbuffer
,rc
);
428 return (void*)DRAM_START
;
432 if (i
==BUTTON_PLAY
) {
433 lcd_puts(0, line
, "Loading Linux...");
435 rc
=load_linux(loadbuffer
);
437 snprintf(buf
, sizeof(buf
), "Linux error: %d",rc
);
438 lcd_puts(0, line
++, buf
);
441 memcpy((void*)DRAM_START
,loadbuffer
,rc
);
442 return (void*)DRAM_START
;
446 /* If everything else failed, try the original firmware */
447 lcd_puts(0, line
, "Loading original firmware...");
450 /* Pause for 5 seconds so we can see what's happened */
453 entry
= tblp
->addr
+ tblp
->entryOffset
;
454 if (imageno
|| ((int)tblp
->addr
& 0xffffff) != 0) {
455 memmove16(tblp
->addr
, tblp
->addr
+ tblp
->devOffset
- padding
,
459 /* Return the start address in loaded image */
463 /* These functions are present in the firmware library, but we reimplement
464 them here because the originals do a lot more than we want */
466 void reset_poweroff_timer(void)
479 void usb_acknowledge(void)
483 void usb_wait_for_disconnect(void)
487 void sys_poweroff(void)