blob: 11da73b39b2fe835711c6681abe8f2ee560c224d [file] [log] [blame]
Linus Nielsen Feltzingc5df4f82007-02-23 09:30:09 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Greg White
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
Marcoen Hirschberg0a068242006-08-12 08:27:48 +000019#include "config.h"
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include "cpu.h"
25#include "system.h"
26#include "lcd.h"
27#include "kernel.h"
28#include "thread.h"
29#include "ata.h"
30#include "fat.h"
31#include "disk.h"
32#include "font.h"
33#include "adc.h"
34#include "backlight.h"
35#include "panic.h"
36#include "power.h"
37#include "file.h"
Marcoen Hirschberg29536762006-12-29 02:49:12 +000038#include "button-target.h"
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000039#include "common.h"
Marcoen Hirschberg29536762006-12-29 02:49:12 +000040
Greg White8b3c8792007-01-17 01:49:19 +000041extern void map_memory(void);
Marcoen Hirschberg29536762006-12-29 02:49:12 +000042
Marcoen Hirschberg0a068242006-08-12 08:27:48 +000043char version[] = APPSVERSION;
44
Greg White8b3c8792007-01-17 01:49:19 +000045static void go_usb_mode(void)
Marcoen Hirschberg29536762006-12-29 02:49:12 +000046{
Greg White8b3c8792007-01-17 01:49:19 +000047 /* Drop into USB mode. This does not check for disconnection. */
Marcoen Hirschberg0a068242006-08-12 08:27:48 +000048 int i;
49
50 GPBDAT &= 0x7EF;
51 GPBCON |= 1<<8;
52
53 GPGDAT &= 0xE7FF;
54 GPGDAT |= 1<<11;
55
Greg White8b3c8792007-01-17 01:49:19 +000056 for(i = 0; i < 10000000; i++) {
57 continue;
58 }
Marcoen Hirschberg0a068242006-08-12 08:27:48 +000059
60 GPBCON &= 0x2FFCFF;
Marcoen Hirschberg29536762006-12-29 02:49:12 +000061 GPBDAT |= 1<<5;
Marcoen Hirschberg0a068242006-08-12 08:27:48 +000062 GPBDAT |= 1<<6;
63}
64
Marcoen Hirschberg29536762006-12-29 02:49:12 +000065
66/* Restores a factory kernel/bootloader from a known location */
67/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
68/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
69/* Returns non-zero on failure */
70int restore_fwimg01dat(void)
71{
72 int orig_file = 0, dest_file = 0;
73 int size = 0, size_read;
Greg White8b3c8792007-01-17 01:49:19 +000074 static char buf[4096];
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000075
Marcoen Hirschberg29536762006-12-29 02:49:12 +000076 orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
Greg White8b3c8792007-01-17 01:49:19 +000077 if(orig_file < 0) {
Marcoen Hirschberg29536762006-12-29 02:49:12 +000078 /* Couldn't open source file */
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000079 printf("Couldn't open FWIMG01.DAT.ORIG for reading");
Marcoen Hirschberg29536762006-12-29 02:49:12 +000080 return(1);
81 }
82
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000083 printf("FWIMG01.DAT.ORIG opened for reading");
Marcoen Hirschberg29536762006-12-29 02:49:12 +000084
85 dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
Greg White8b3c8792007-01-17 01:49:19 +000086 if(dest_file < 0) {
Marcoen Hirschberg29536762006-12-29 02:49:12 +000087 /* Couldn't open destination file */
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000088 printf("Couldn't open FWIMG01.DAT.ORIG for writing");
Marcoen Hirschberg29536762006-12-29 02:49:12 +000089 close(orig_file);
90 return(2);
91 }
92
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000093 printf("FWIMG01.DAT opened for writing");
Marcoen Hirschberg29536762006-12-29 02:49:12 +000094
95 do {
96 /* Copy in chunks */
97 size_read = read(orig_file, buf, sizeof(buf));
Greg White8b3c8792007-01-17 01:49:19 +000098 if(size_read != write(dest_file, buf, size_read)) {
Marcoen Hirschberg29536762006-12-29 02:49:12 +000099 close(orig_file);
100 close(dest_file);
101 return(3);
102 }
103 size += size_read;
104
Greg White8b3c8792007-01-17 01:49:19 +0000105 } while(size_read > 0);
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000106
107 close(orig_file);
108 close(dest_file);
109
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000110 printf("Finished copying %ld bytes from", size);
111 printf("FWIMG01.DAT.ORIG to FWIMG01.DAT");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000112
113 return(0);
114}
115
Greg White3b65fc22007-01-17 18:31:40 +0000116char buf[256];
117
118void display_instructions(void)
119{
120 lcd_setfont(FONT_SYSFIXED);
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000121 printf("Hold MENU when booting for rescue mode.");
122 printf(" \"VOL+\" button to restore original kernel");
123 printf(" \"A\" button to load original firmware");
124 printf("");
125 printf("FRAME %x TTB %x", FRAME, TTB_BASE);
Greg White3b65fc22007-01-17 18:31:40 +0000126}
Greg White8b3c8792007-01-17 01:49:19 +0000127
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000128void * main(void)
129{
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000130 int i;
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000131 struct partinfo* pinfo;
132 unsigned short* identify_info;
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000133 unsigned char* loadbuffer;
134 int buffer_size;
135 bool load_original = false;
136 int rc;
137 int(*kernel_entry)(void);
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000138
Greg White8b3c8792007-01-17 01:49:19 +0000139 bool show_bootsplash = true;
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000140
Greg White8b3c8792007-01-17 01:49:19 +0000141 if(GPGDAT & 2)
142 show_bootsplash = false;
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000143
Greg White8b3c8792007-01-17 01:49:19 +0000144 if(!show_bootsplash) {
Greg White3b65fc22007-01-17 18:31:40 +0000145 lcd_init();
146 display_instructions();
Greg White8b3c8792007-01-17 01:49:19 +0000147 sleep(2*HZ);
Greg White3b65fc22007-01-17 18:31:40 +0000148 }
Greg White8b3c8792007-01-17 01:49:19 +0000149 if(GPGDAT & 2) {
Greg White3b65fc22007-01-17 18:31:40 +0000150 lcd_init();
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000151 printf("Entering rescue mode..");
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000152 go_usb_mode();
153 while(1);
154 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000155 if(GPGDAT & 0x10) {
Greg White3b65fc22007-01-17 18:31:40 +0000156 lcd_init();
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000157 load_original = true;
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000158 printf("Loading original firmware...");
Greg White8b3c8792007-01-17 01:49:19 +0000159 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000160
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000161 i = ata_init();
162 i = disk_mount_all();
Greg White8b3c8792007-01-17 01:49:19 +0000163 if(!show_bootsplash) {
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000164 printf("disk_mount_all: %d", i);
Greg White8b3c8792007-01-17 01:49:19 +0000165 }
Greg White3b65fc22007-01-17 18:31:40 +0000166 if(show_bootsplash) {
167 int fd = open("/bootsplash.raw", O_RDONLY);
168 if(fd < 0) {
169 show_bootsplash = false;
170 lcd_init();
171 display_instructions();
172 }
173 else {
174 read(fd, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
175 close(fd);
176 lcd_update();
177 lcd_init();
178 }
179 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000180 /* hold VOL+ to enter rescue mode to copy old image */
181 /* needs to be after ata_init and disk_mount_all */
Greg White8b3c8792007-01-17 01:49:19 +0000182 if(GPGDAT & 4) {
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000183
184 /* Try to restore the original kernel/bootloader if a copy is found */
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000185 printf("Restoring FWIMG01.DAT...");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000186
Greg White8b3c8792007-01-17 01:49:19 +0000187 if(!restore_fwimg01dat()) {
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000188 printf("Restoring FWIMG01.DAT successful.");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000189 } else {
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000190 printf("Restoring FWIMG01.DAT failed.");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000191 }
192
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000193 printf("Now power cycle to boot original");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000194 while(1);
195 }
196
Greg White8b3c8792007-01-17 01:49:19 +0000197 if(!show_bootsplash) {
198 identify_info = ata_get_identify();
199
200 for(i=0; i < 20; i++)
201 ((unsigned short*)buf)[i]=htobe16(identify_info[i+27]);
202
203 buf[40]=0;
204
205 /* kill trailing space */
206 for(i=39; i && buf[i]==' '; i--)
207 buf[i] = 0;
208
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000209 printf("Model");
210 printf(buf);
Greg White8b3c8792007-01-17 01:49:19 +0000211
212 for(i=0; i < 4; i++)
213 ((unsigned short*)buf)[i]=htobe16(identify_info[i+23]);
214
215 buf[8]=0;
216
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000217 printf("Firmware");
218 printf(buf);
Greg White8b3c8792007-01-17 01:49:19 +0000219
220 pinfo = disk_partinfo(0);
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000221 printf("Partition 0: 0x%02x %ld MB", pinfo->type, pinfo->size / 2048);
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000222 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000223 /* Load original firmware */
224 if(load_original) {
225 loadbuffer = (unsigned char*)0x30008000;
226 buffer_size =(unsigned char*)0x31000000 - loadbuffer;
Nicolas Pennequinbd073cd2007-02-22 21:19:48 +0000227 rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000228 if(rc < EOK) {
229 printf("Error!");
230 printf("Failed to load original firmware:");
231 printf(strerror(rc));
232 printf("Loading rockbox");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000233 sleep(2*HZ);
234 goto load_rockbox;
235 }
236
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000237 printf("Loaded: %d", rc);
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000238 sleep(2*HZ);
239
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000240 (*((int*)0x7000000)) = 333;
241 rc = *((int*)0x7000000+0x8000000);
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000242 printf("Bank0 mem test: %d", rc);
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000243 sleep(3*HZ);
244
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000245 printf("Woops, should not return from firmware!");
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000246 goto usb;
247 }
248
249load_rockbox:
250 map_memory();
Greg White8b3c8792007-01-17 01:49:19 +0000251 if(!show_bootsplash) {
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000252 printf("Loading Rockbox...");
Greg White8b3c8792007-01-17 01:49:19 +0000253 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000254
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000255 loadbuffer = (unsigned char*) 0x100;
256 buffer_size = (unsigned char*)0x400000 - loadbuffer;
Nicolas Pennequinbd073cd2007-02-22 21:19:48 +0000257 rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000258 if(rc < EOK) {
259 printf("Error!");
260 printf("Can't load rockbox.gigabeat:");
261 printf(strerror(rc));
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000262 } else {
Greg White8b3c8792007-01-17 01:49:19 +0000263 if(!show_bootsplash) {
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000264 printf("Rockbox loaded.");
Greg White8b3c8792007-01-17 01:49:19 +0000265 }
Greg White355be502007-01-13 02:24:15 +0000266 kernel_entry = (void*) loadbuffer;
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000267 rc = kernel_entry();
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000268 printf("Woops, should not return from firmware: %d", rc);
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000269 goto usb;
270 }
Marcoen Hirschberg29536762006-12-29 02:49:12 +0000271usb:
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000272 /* now wait in USB mode so the bootloader can be updated */
273 go_usb_mode();
274 while(1);
275
Greg White8b3c8792007-01-17 01:49:19 +0000276 return((void *)0);
Marcoen Hirschberg0a068242006-08-12 08:27:48 +0000277}
278