summaryrefslogtreecommitdiff
path: root/bootloader/ipod.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader/ipod.c')
-rw-r--r--bootloader/ipod.c213
1 files changed, 173 insertions, 40 deletions
diff --git a/bootloader/ipod.c b/bootloader/ipod.c
index 840b95be9e..591b7608aa 100644
--- a/bootloader/ipod.c
+++ b/bootloader/ipod.c
@@ -23,6 +23,7 @@
23 23
24#include <stdlib.h> 24#include <stdlib.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <string.h>
26#include "cpu.h" 27#include "cpu.h"
27#include "system.h" 28#include "system.h"
28#include "lcd.h" 29#include "lcd.h"
@@ -34,7 +35,6 @@
34#include "font.h" 35#include "font.h"
35#include "adc.h" 36#include "adc.h"
36#include "backlight.h" 37#include "backlight.h"
37#include "button.h"
38#include "panic.h" 38#include "panic.h"
39#include "power.h" 39#include "power.h"
40#include "file.h" 40#include "file.h"
@@ -44,6 +44,14 @@
44 44
45#define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084))) 45#define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084)))
46 46
47#define BUTTON_LEFT 1
48#define BUTTON_MENU 2
49#define BUTTON_RIGHT 3
50#define BUTTON_PLAY 4
51
52/* Size of the buffer to store the loaded Rockbox/Linux image */
53#define MAX_LOADSIZE (4*1024*1024)
54
47char version[] = APPSVERSION; 55char version[] = APPSVERSION;
48 56
49#include "rockbox-16bit.h" 57#include "rockbox-16bit.h"
@@ -115,7 +123,93 @@ int usleep(unsigned int usecs)
115 return 0; 123 return 0;
116} 124}
117 125
118int load_firmware(void) 126
127static void ser_opto_keypad_cfg(int val)
128{
129 int start_time;
130
131 outl(inl(0x6000d004) & ~0x80, 0x6000d004);
132
133 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
134 outl(val, 0x7000c120);
135 outl(inl(0x7000c100) | 0x80000000, 0x7000c100);
136
137 outl(inl(0x6000d024) & ~0x10, 0x6000d024);
138 outl(inl(0x6000d014) | 0x10, 0x6000d014);
139
140 start_time = timer_get_current();
141 do {
142 if ((inl(0x7000c104) & 0x80000000) == 0) {
143 break;
144 }
145 } while (timer_check(start_time, 1500) != 0);
146
147 outl(inl(0x7000c100) & ~0x80000000, 0x7000c100);
148
149 outl(inl(0x6000d004) | 0x80, 0x6000d004);
150 outl(inl(0x6000d024) | 0x10, 0x6000d024);
151 outl(inl(0x6000d014) & ~0x10, 0x6000d014);
152
153 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
154 outl(inl(0x7000c100) | 0x60000000, 0x7000c100);
155}
156
157int opto_keypad_read(void)
158{
159 int loop_cnt, had_io = 0;
160
161 for (loop_cnt = 5; loop_cnt != 0;)
162 {
163 int key_pressed = 0;
164 int start_time;
165 unsigned int key_pad_val;
166
167 ser_opto_keypad_cfg(0x8000023a);
168
169 start_time = timer_get_current();
170 do {
171 if (inl(0x7000c104) & 0x4000000) {
172 had_io = 1;
173 break;
174 }
175
176 if (had_io != 0) {
177 break;
178 }
179 } while (timer_check(start_time, 1500) != 0);
180
181 key_pad_val = inl(0x7000c140);
182 if ((key_pad_val & ~0x7fff0000) != 0x8000023a) {
183 loop_cnt--;
184 } else {
185 key_pad_val = (key_pad_val << 11) >> 27;
186 key_pressed = 1;
187 }
188
189 outl(inl(0x7000c100) | 0x60000000, 0x7000c100);
190 outl(inl(0x7000c104) | 0xc000000, 0x7000c104);
191
192 if (key_pressed != 0) {
193 return key_pad_val ^ 0x1f;
194 }
195 }
196
197 return 0;
198}
199
200static int key_pressed(void)
201{
202 unsigned char state;
203
204 state = opto_keypad_read();
205 if ((state & 0x4) == 0) return BUTTON_LEFT;
206 if ((state & 0x10) == 0) return BUTTON_MENU;
207 if ((state & 0x8) == 0) return BUTTON_PLAY;
208 if ((state & 0x2) == 0) return BUTTON_RIGHT;
209 return 0;
210}
211
212int load_rockbox(unsigned char* buf)
119{ 213{
120 int fd; 214 int fd;
121 int rc; 215 int rc;
@@ -124,36 +218,31 @@ int load_firmware(void)
124 char model[5]; 218 char model[5];
125 unsigned long sum; 219 unsigned long sum;
126 int i; 220 int i;
127 unsigned char *buf = (unsigned char *)DRAM_START;
128 char str[80]; 221 char str[80];
129 222
130 fd = open("/rockbox.ipod", O_RDONLY); 223 fd = open("/rockbox.ipod", O_RDONLY);
131 if(fd < 0) 224 if(fd < 0)
132 return -1; 225 return -1;
133 226
134 len = filesize(fd) - 8; 227 len = filesize(fd) - 8;
135 228
136 snprintf(str, 80, "Length: %x", len); 229 if (len > MAX_LOADSIZE)
137 lcd_puts(0, line++, str); 230 return -6;
138 lcd_update();
139 231
140 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); 232 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
141 233
142 rc = read(fd, &chksum, 4); 234 rc = read(fd, &chksum, 4);
235 chksum=betoh32(chksum); /* Rockbox checksums are big-endian */
143 if(rc < 4) 236 if(rc < 4)
144 return -2; 237 return -2;
145
146 snprintf(str, 80, "Checksum: %x", chksum);
147 lcd_puts(0, line++, str);
148 lcd_update();
149 238
150 rc = read(fd, model, 4); 239 rc = read(fd, model, 4);
151 if(rc < 4) 240 if(rc < 4)
152 return -3; 241 return -3;
153 242
154 model[4] = 0; 243 model[4] = 0;
155 244
156 snprintf(str, 80, "Model name: %s", model); 245 snprintf(str, 80, "Model: %s, Checksum: %x", model, chksum);
157 lcd_puts(0, line++, str); 246 lcd_puts(0, line++, str);
158 lcd_update(); 247 lcd_update();
159 248
@@ -161,14 +250,14 @@ int load_firmware(void)
161 250
162 rc = read(fd, buf, len); 251 rc = read(fd, buf, len);
163 if(rc < len) 252 if(rc < len)
164 return -4; 253 return -4;
165 254
166 close(fd); 255 close(fd);
167 256
168 sum = MODEL_NUMBER; 257 sum = MODEL_NUMBER;
169 258
170 for(i = 0;i < len;i++) { 259 for(i = 0;i < len;i++) {
171 sum += buf[i]; 260 sum += buf[i];
172 } 261 }
173 262
174 snprintf(str, 80, "Sum: %x", sum); 263 snprintf(str, 80, "Sum: %x", sum);
@@ -178,9 +267,40 @@ int load_firmware(void)
178 if(sum != chksum) 267 if(sum != chksum)
179 return -5; 268 return -5;
180 269
181 return 0; 270 return len;
182} 271}
183 272
273
274int load_linux(unsigned char* buf) {
275 int fd;
276 int rc;
277 int len;
278 char str[80];
279
280 fd=open("/linux.bin",O_RDONLY);
281 if (fd < 0)
282 return -1;
283
284 len=filesize(fd);
285 if (len > MAX_LOADSIZE)
286 return -6;
287
288 rc=read(fd,buf,len);
289
290 if (rc < len)
291 return -4;
292
293 snprintf(str, 80, "Loaded Linux: %d bytes", len);
294 lcd_puts(0, line++, str);
295 lcd_update();
296
297 return len;
298}
299
300
301/* A buffer to load the Linux kernel or Rockbox into */
302unsigned char loadbuffer[MAX_LOADSIZE];
303
184void* main(void) 304void* main(void)
185{ 305{
186 char buf[256]; 306 char buf[256];
@@ -196,7 +316,6 @@ void* main(void)
196 /* Turn on the backlight */ 316 /* Turn on the backlight */
197 317
198#if CONFIG_BACKLIGHT==BL_IPOD4G 318#if CONFIG_BACKLIGHT==BL_IPOD4G
199
200 /* brightness full */ 319 /* brightness full */
201 outl(0x80000000 | (0xff << 16), 0x7000a010); 320 outl(0x80000000 | (0xff << 16), 0x7000a010);
202 321
@@ -277,32 +396,50 @@ void* main(void)
277 lcd_puts(0, line++, buf); 396 lcd_puts(0, line++, buf);
278 lcd_update(); 397 lcd_update();
279 398
399 /* Check for a keypress */
400 i=key_pressed();
401
402 if (i==BUTTON_MENU) {
403 lcd_puts(0, line, "Loading Rockbox...");
404 lcd_update();
405 rc=load_rockbox(loadbuffer);
406 if (rc < 0) {
407 snprintf(buf, sizeof(buf), "Rockbox error: %d",rc);
408 lcd_puts(0, line++, buf);
409 lcd_update();
410 } else {
411 lcd_puts(0, line++, "Rockbox loaded.");
412 lcd_update();
280#if 0 413#if 0
281 /* The following code will load and run an ipodlinux kernel - we will 414 /* Rockbox is not yet runable, so we disable this */
282 enable it once the button driver is written and we can detect key 415 memcpy((void*)DRAM_START,loadbuffer,rc);
283 presses */ 416 return (void*)DRAM_START;
284 int fd=open("/linux.bin",O_RDONLY);
285 if (fd >= 0) {
286 i=filesize(fd);
287 int n=read(fd,(void*)DRAM_START,i);
288 if (n==i) {
289 /* We return the entry point for the loaded kernel */
290 return DRAM_START;
291 } else {
292 /* What do we do now? We may have overwritten the copy of the
293 original firmware with our incomplete copy of the Linux
294 kernel... */
295 }
296 }
297#endif 417#endif
418 }
419 }
298 420
299 /* Pause for 5 seconds so we can see what's happened*/ 421 if (i==BUTTON_PLAY) {
300 usleep(5000000); 422 lcd_puts(0, line, "Loading Linux...");
423 lcd_update();
424 rc=load_linux(loadbuffer);
425 if (rc < 0) {
426 snprintf(buf, sizeof(buf), "Linux error: %d",rc);
427 lcd_puts(0, line++, buf);
428 lcd_update();
429 } else {
430 memcpy((void*)DRAM_START,loadbuffer,rc);
431 return (void*)DRAM_START;
432 }
433 }
301 434
302 /* If everything else failed, try the original firmware */ 435 /* If everything else failed, try the original firmware */
436
303 lcd_puts(0, line, "Loading original firmware..."); 437 lcd_puts(0, line, "Loading original firmware...");
304 lcd_update(); 438 lcd_update();
305 439
440 /* Pause for 5 seconds so we can see what's happened */
441 usleep(5000000);
442
306 entry = tblp->addr + tblp->entryOffset; 443 entry = tblp->addr + tblp->entryOffset;
307 if (imageno || ((int)tblp->addr & 0xffffff) != 0) { 444 if (imageno || ((int)tblp->addr & 0xffffff) != 0) {
308 memmove16(tblp->addr, tblp->addr + tblp->devOffset - padding, 445 memmove16(tblp->addr, tblp->addr + tblp->devOffset - padding,
@@ -320,10 +457,6 @@ void reset_poweroff_timer(void)
320{ 457{
321} 458}
322 459
323void screen_dump(void)
324{
325}
326
327int dbg_ports(void) 460int dbg_ports(void)
328{ 461{
329 return 0; 462 return 0;