summaryrefslogtreecommitdiff
path: root/bootloader/gigabeat.c
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2006-12-29 02:49:12 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2006-12-29 02:49:12 +0000
commit295367686ec9855c4d90f68a6003e819fef8e7ab (patch)
treeb4077ffb8d2283bf199ad12a90322be77040c2fd /bootloader/gigabeat.c
parent995a804defda23233ccbdd859023f4ba3ecba0bf (diff)
downloadrockbox-295367686ec9855c4d90f68a6003e819fef8e7ab.tar.gz
rockbox-295367686ec9855c4d90f68a6003e819fef8e7ab.zip
merge a big part of the unofficial gigabeat cvs back. Includes working bootloader and rockbox with audio.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11850 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'bootloader/gigabeat.c')
-rw-r--r--bootloader/gigabeat.c367
1 files changed, 359 insertions, 8 deletions
diff --git a/bootloader/gigabeat.c b/bootloader/gigabeat.c
index c04042cead..62c31310ae 100644
--- a/bootloader/gigabeat.c
+++ b/bootloader/gigabeat.c
@@ -17,12 +17,133 @@
17#include "panic.h" 17#include "panic.h"
18#include "power.h" 18#include "power.h"
19#include "file.h" 19#include "file.h"
20#include "button-target.h"
21
22void map_memory(void);
23
24int line = 0;
20 25
21char version[] = APPSVERSION; 26char version[] = APPSVERSION;
22 27
23void go_usb_mode(void) { 28/* This section allows you to toggle bits of any memory location */
29/* Touchpad to move around the bits. Select to toggle the red bit */
30typedef struct {
31 unsigned int address;
32 char *desc;
33} memlocation_struct;
34
35/* Just add any address and descriptions here */
36/* Must finish with 0xFFFFFFFF */
37const memlocation_struct memlocations[] = {
38/* Address Description */
39{ 0x56000000, "GPACON" },
40{ 0x56000004, "GPADAT" },
41{ 0x56000010, "GPBCON" },
42{ 0x56000014, "GPBDAT" },
43{ 0x56000020, "GPCCON" },
44{ 0x56000024, "GPCDAT" },
45{ 0x56000030, "GPDCON" },
46{ 0x56000034, "GPDDAT" },
47{ 0x56000040, "GPECON" },
48{ 0x56000044, "GPEDAT" },
49{ 0x56000050, "GPFCON" },
50{ 0x56000054, "GPFDAT" },
51{ 0x56000060, "GPGCON" },
52{ 0x56000064, "GPGDAT" },
53{ 0x56000070, "GPHCON" },
54{ 0x56000074, "GPHDAT" },
55{ 0xFFFFFFFF, 0 }
56};
57
58void memdump(void)
59{
60 int i, j;
61 int current=0, bit=0;
62 char * bitval;
63 int data;
64 char tmp[40];
65
66 while(1) {
67 i = 0;
68
69 while(memlocations[i].address != 0xFFFFFFFF) {
70
71 data = *(volatile int *)memlocations[i].address;
72
73 snprintf(tmp, sizeof(tmp), "%s %s 0x%08X",
74 (i==current) ? "*" : " ",
75 memlocations[i].desc,
76 data);
77 lcd_puts(0, i*2+5, tmp);
78
79 /* print out in binary, current bit in red */
80 for (j=31; j>=0; j--) {
81 if ((bit == j) && (current == i))
82 lcd_set_foreground(LCD_RGBPACK(255,0,0));
83 lcd_puts((31-j) + ((31-j) / 8), i*2+6, (data & (1 << j)) ? "1" : "0" );
84 lcd_set_foreground(LCD_RGBPACK(0,0,0));
85 }
86
87 i++;
88 }
89
90 data = *(volatile int *)memlocations[current].address;
91 bitval = (data & (1 << bit)) ? "1" : "0";
92 snprintf(tmp, sizeof(tmp), "%s bit %ld = %s", memlocations[current].desc, bit, bitval);
93 lcd_puts(0, (i*2)+7, tmp);
94
95 lcd_update();
96
97 /* touchpad controls */
98
99 /* Up */
100 if (GPJDAT & 0x01) {
101 if (current > 0)
102 current--;
103 while(GPJDAT & 0x01);
104 }
105
106 /* Down */
107 if (GPJDAT & 0x40) {
108 if (current < (i-1))
109 current++;
110 while(GPJDAT & 0x40);
111 }
112
113 /* Left */
114 if (GPJDAT & 0x80) {
115 if (bit < 31)
116 bit++;
117 while(GPJDAT & 0x80);
118 }
119
120 /* Right */
121 if (GPJDAT & 0x1000) {
122 if (bit > 0)
123 bit--;
124 while(GPJDAT & 0x1000);
125 }
126
127 /* Centre - Toggle Bit */
128 if (GPJDAT & 0x08) {
129 data = *(volatile int *)memlocations[current].address;
130 data = data ^ (1 << bit);
131 *(volatile int *)memlocations[current].address = data;
132 while(GPJDAT & 0x08);
133 }
134
135 /* Bail out if the power button is pressed */
136 if (GPGDAT & 1) {
137 break;
138 }
139 }
140}
141
142
143static void go_usb_mode(void) {
24 /* Drop into USB mode. This does not check for disconnection. */ 144 /* Drop into USB mode. This does not check for disconnection. */
25 145
146
26 int i; 147 int i;
27 148
28 GPBDAT &= 0x7EF; 149 GPBDAT &= 0x7EF;
@@ -34,17 +155,160 @@ void go_usb_mode(void) {
34 for (i = 0; i < 10000000; i++) {continue;} 155 for (i = 0; i < 10000000; i++) {continue;}
35 156
36 GPBCON &= 0x2FFCFF; 157 GPBCON &= 0x2FFCFF;
37 GPBDAT |= 1<<5; 158 GPBDAT |= 1<<5;
38 GPBDAT |= 1<<6; 159 GPBDAT |= 1<<6;
39} 160}
40 161
162
163/* Restores a factory kernel/bootloader from a known location */
164/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
165/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
166/* Returns non-zero on failure */
167int restore_fwimg01dat(void)
168{
169 int orig_file = 0, dest_file = 0;
170 int size = 0, size_read;
171 char buf[256];
172 char lcd_buf[64];
173
174 orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
175 if (orig_file < 0) {
176 /* Couldn't open source file */
177 lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for reading");
178 lcd_update();
179 return(1);
180 }
181
182 lcd_puts(0, line++, "FWIMG01.DAT.ORIG opened for reading");
183 lcd_update();
184
185 dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
186 if (dest_file < 0) {
187 /* Couldn't open destination file */
188 lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for writing");
189 lcd_update();
190 close(orig_file);
191 return(2);
192 }
193
194 lcd_puts(0, line++, "FWIMG01.DAT opened for writing");
195 lcd_update();
196
197 do {
198 /* Copy in chunks */
199 size_read = read(orig_file, buf, sizeof(buf));
200 if (size_read != write(dest_file, buf, size_read)) {
201 close(orig_file);
202 close(dest_file);
203 return(3);
204 }
205 size += size_read;
206
207 } while (size_read > 0);
208
209 close(orig_file);
210 close(dest_file);
211
212 snprintf(lcd_buf, sizeof(lcd_buf), "Finished copying %ld bytes from", size);
213 lcd_puts(0, line++, lcd_buf);
214 lcd_puts(0, line++, "FWIMG01.DAT.ORIG to FWIMG01.DAT");
215
216 return(0);
217}
218
219
220int load_rockbox(const char* file_name, unsigned char* buf, int buffer_size)
221{
222 int fd;
223 int rc;
224 int len;
225 char str[256];
226 //unsigned long chksum;
227 //char model[5];
228 //unsigned long sum;
229 //int i;
230 //char str[80];
231
232 fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
233 if(fd < 0)
234 {
235 fd = open("/" BOOTFILE, O_RDONLY);
236 if(fd < 0)
237 return -1;
238 }
239 fd = open(file_name, O_RDONLY);
240 if(fd < 0)
241 return -2;
242
243 len = filesize(fd);
244
245 if (len > buffer_size) {
246 snprintf(str, sizeof(str), "len: %d buf: %d", len, buffer_size);
247 lcd_puts(0, line++, str);
248 lcd_update();
249 return -6;
250 }
251
252 /*lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
253
254 rc = read(fd, &chksum, 4);
255 chksum=betoh32(chksum);*/ /* Rockbox checksums are big-endian */
256 /*if(rc < 4)
257 return -2;
258
259 rc = read(fd, model, 4);
260 if(rc < 4)
261 return -3;
262
263 model[4] = 0;
264
265 snprintf(str, 80, "Model: %s", model);
266 lcd_puts(0, line++, str);
267 snprintf(str, 80, "Checksum: %x", chksum);
268 lcd_puts(0, line++, str);
269 lcd_update();
270
271 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
272*/
273
274 rc = read(fd, buf, len);
275 if(rc < len) {
276 snprintf(str, sizeof(str), "len: %d rc: %d", len, rc);
277 lcd_puts(0, line++, str);
278 lcd_update();
279 return -4;
280 }
281
282 close(fd);
283
284 /*sum = MODEL_NUMBER;
285
286 for(i = 0;i < len;i++) {
287 sum += buf[i];
288 }
289
290 snprintf(str, 80, "Sum: %x", sum);
291 lcd_puts(0, line++, str);
292 lcd_update();
293
294 if(sum != chksum)
295 return -5;*/
296
297 return len;
298}
299
41void * main(void) 300void * main(void)
42{ 301{
43 int line = 0, i; 302 int i;
44 char buf[256]; 303 char buf[256];
45 struct partinfo* pinfo; 304 struct partinfo* pinfo;
46 unsigned short* identify_info; 305 unsigned short* identify_info;
47 int testfile; 306 //int testfile;
307 unsigned char* loadbuffer;
308 int buffer_size;
309 bool load_original = false;
310 int rc;
311 int(*kernel_entry)(void);
48 312
49 lcd_init(); 313 lcd_init();
50 lcd_setfont(FONT_SYSFIXED); 314 lcd_setfont(FONT_SYSFIXED);
@@ -57,7 +321,10 @@ void * main(void)
57*/ 321*/
58 322
59 lcd_puts(0, line++, "Hold MENU when booting for rescue mode."); 323 lcd_puts(0, line++, "Hold MENU when booting for rescue mode.");
324 lcd_puts(0, line++, " \"VOL+\" button to restore original kernel");
325 lcd_puts(0, line++, " \"A\" button to load original firmware");
60 lcd_update(); 326 lcd_update();
327 sleep(1*HZ);
61 328
62 /* hold MENU to enter rescue mode */ 329 /* hold MENU to enter rescue mode */
63 if (GPGDAT & 2) { 330 if (GPGDAT & 2) {
@@ -67,12 +334,44 @@ void * main(void)
67 while(1); 334 while(1);
68 } 335 }
69 336
337 sleep(5*HZ);
338
339 if(GPGDAT & 0x10) {
340 load_original = true;
341 lcd_puts(0, line++, "Loading original firmware...");
342 lcd_update();
343 }
344
70 i = ata_init(); 345 i = ata_init();
71 i = disk_mount_all(); 346 i = disk_mount_all();
72 347
73 snprintf(buf, sizeof(buf), "disk_mount_all: %d", i); 348 snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
74 lcd_puts(0, line++, buf); 349 lcd_puts(0, line++, buf);
75 350
351 /* hold VOL+ to enter rescue mode to copy old image */
352 /* needs to be after ata_init and disk_mount_all */
353 if (GPGDAT & 4) {
354
355 /* Try to restore the original kernel/bootloader if a copy is found */
356 lcd_puts(0, line++, "Restoring FWIMG01.DAT...");
357 lcd_update();
358
359 if (!restore_fwimg01dat()) {
360 lcd_puts(0, line++, "Restoring FWIMG01.DAT successful.");
361 } else {
362 lcd_puts(0, line++, "Restoring FWIMG01.DAT failed.");
363 }
364
365 lcd_puts(0, line++, "Now power cycle to boot original");
366 lcd_update();
367 while(1);
368 }
369
370 /* Memory dump mode if Vol- pressed */
371 if (GPGDAT & 8) {
372 memdump();
373 }
374
76 identify_info = ata_get_identify(); 375 identify_info = ata_get_identify();
77 376
78 for (i=0; i < 20; i++) 377 for (i=0; i < 20; i++)
@@ -96,16 +395,68 @@ void * main(void)
96 lcd_puts(0, line++, buf); 395 lcd_puts(0, line++, buf);
97 396
98 pinfo = disk_partinfo(0); 397 pinfo = disk_partinfo(0);
99 snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB", 398 snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB",
100 pinfo->type, pinfo->size / 2048); 399 pinfo->type, pinfo->size / 2048);
101 lcd_puts(0, line++, buf); 400 lcd_puts(0, line++, buf);
401 lcd_update();
402
403 /* Load original firmware */
404 if(load_original) {
405 loadbuffer = (unsigned char*)0x30008000;
406 buffer_size =(unsigned char*)0x31000000 - loadbuffer;
407 rc = load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
408 if (rc < 0) {
409 lcd_puts(0, line++, "failed to load original firmware. Loading rockbox");
410 lcd_update();
411 sleep(2*HZ);
412 goto load_rockbox;
413 }
102 414
103 testfile = open("/boottest.txt", O_WRONLY|O_CREAT|O_TRUNC); 415 snprintf(buf, sizeof(buf), "Loaded: %d", rc);
104 write(testfile, "It works!", 9); 416 lcd_puts(0, line++, buf);
105 close(testfile); 417 lcd_update();
418 sleep(2*HZ);
419
420
421 (*((int*)0x7000000)) = 333;
422 rc = *((int*)0x7000000+0x8000000);
423 snprintf(buf, sizeof(buf), "Bank0 mem test: %d", rc);
424 lcd_puts(0, line++, buf);
425 lcd_update();
426 sleep(3*HZ);
427
428 lcd_puts(0, line++, "Woops, should not return from firmware!");
429 lcd_update();
430 goto usb;
431 }
106 432
433load_rockbox:
434 map_memory();
435 lcd_puts(0, line, "Loading Rockbox...");
107 lcd_update(); 436 lcd_update();
437 sleep(HZ*4);
438
439 // TODO: read those values from somwhere
440 loadbuffer = (unsigned char*) 0x100;
441 buffer_size = (unsigned char*)0x400000 - loadbuffer;
442 rc=load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
443 if (rc < 0) {
444 snprintf(buf, sizeof(buf), "Rockbox error: %d",rc);
445 lcd_puts(0, line++, buf);
446 lcd_update();
447 } else {
448 lcd_puts(0, line++, "Rockbox loaded.");
449 lcd_update();
450 kernel_entry = (void*)0x100;
451 rc = kernel_entry();
452 snprintf(buf, sizeof(buf), "Woops, should not return from firmware: %d", rc);
453 lcd_puts(0, line++, buf);
454 lcd_update();
455 goto usb;
456 }
457
108 458
459usb:
109 /* now wait in USB mode so the bootloader can be updated */ 460 /* now wait in USB mode so the bootloader can be updated */
110 go_usb_mode(); 461 go_usb_mode();
111 while(1); 462 while(1);