diff options
Diffstat (limited to 'bootloader')
-rw-r--r-- | bootloader/common.c | 2 | ||||
-rw-r--r-- | bootloader/gigabeat.c | 278 |
2 files changed, 65 insertions, 215 deletions
diff --git a/bootloader/common.c b/bootloader/common.c index 51b751cbf9..1ac8e8f7e3 100644 --- a/bootloader/common.c +++ b/bootloader/common.c | |||
@@ -31,7 +31,7 @@ | |||
31 | /* TODO: Other bootloaders need to be adjusted to set this variable to true | 31 | /* TODO: Other bootloaders need to be adjusted to set this variable to true |
32 | on a button press - currently only the ipod, H10 and Sansa versions do. */ | 32 | on a button press - currently only the ipod, H10 and Sansa versions do. */ |
33 | #if defined(IPOD_ARCH) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || \ | 33 | #if defined(IPOD_ARCH) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || \ |
34 | defined(SANSA_E200) | 34 | defined(SANSA_E200) || defined(GIGABEAT_F) |
35 | bool verbose = false; | 35 | bool verbose = false; |
36 | #else | 36 | #else |
37 | bool verbose = true; | 37 | bool verbose = true; |
diff --git a/bootloader/gigabeat.c b/bootloader/gigabeat.c index e4cf6f08fd..e482c70d16 100644 --- a/bootloader/gigabeat.c +++ b/bootloader/gigabeat.c | |||
@@ -20,7 +20,8 @@ | |||
20 | 20 | ||
21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <string.h> | 23 | #include "inttypes.h" |
24 | #include "string.h" | ||
24 | #include "cpu.h" | 25 | #include "cpu.h" |
25 | #include "system.h" | 26 | #include "system.h" |
26 | #include "lcd.h" | 27 | #include "lcd.h" |
@@ -32,250 +33,99 @@ | |||
32 | #include "font.h" | 33 | #include "font.h" |
33 | #include "adc.h" | 34 | #include "adc.h" |
34 | #include "backlight.h" | 35 | #include "backlight.h" |
36 | #include "backlight-target.h" | ||
37 | #include "button.h" | ||
35 | #include "panic.h" | 38 | #include "panic.h" |
36 | #include "power.h" | 39 | #include "power.h" |
37 | #include "file.h" | 40 | #include "file.h" |
38 | #include "button-target.h" | ||
39 | #include "common.h" | 41 | #include "common.h" |
42 | #include "rbunicode.h" | ||
43 | #include "usb.h" | ||
44 | #include "mmu-meg-fx.h" | ||
40 | 45 | ||
41 | extern void map_memory(void); | 46 | #include <stdarg.h> |
42 | 47 | ||
43 | char version[] = APPSVERSION; | 48 | char version[] = APPSVERSION; |
44 | 49 | ||
45 | static void go_usb_mode(void) | 50 | void main(void) |
46 | { | 51 | { |
47 | /* Drop into USB mode. This does not check for disconnection. */ | ||
48 | int i; | ||
49 | |||
50 | GPBDAT &= 0x7EF; | ||
51 | GPBCON |= 1<<8; | ||
52 | |||
53 | GPGDAT &= 0xE7FF; | ||
54 | GPGDAT |= 1<<11; | ||
55 | |||
56 | for(i = 0; i < 10000000; i++) { | ||
57 | continue; | ||
58 | } | ||
59 | |||
60 | GPBCON &= 0x2FFCFF; | ||
61 | GPBDAT |= 1<<5; | ||
62 | GPBDAT |= 1<<6; | ||
63 | } | ||
64 | |||
65 | |||
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 */ | ||
70 | int restore_fwimg01dat(void) | ||
71 | { | ||
72 | int orig_file = 0, dest_file = 0; | ||
73 | int size = 0, size_read; | ||
74 | static char buf[4096]; | ||
75 | |||
76 | orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY); | ||
77 | if(orig_file < 0) { | ||
78 | /* Couldn't open source file */ | ||
79 | printf("Couldn't open FWIMG01.DAT.ORIG for reading"); | ||
80 | return(1); | ||
81 | } | ||
82 | |||
83 | printf("FWIMG01.DAT.ORIG opened for reading"); | ||
84 | |||
85 | dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR); | ||
86 | if(dest_file < 0) { | ||
87 | /* Couldn't open destination file */ | ||
88 | printf("Couldn't open FWIMG01.DAT.ORIG for writing"); | ||
89 | close(orig_file); | ||
90 | return(2); | ||
91 | } | ||
92 | |||
93 | printf("FWIMG01.DAT opened for writing"); | ||
94 | |||
95 | do { | ||
96 | /* Copy in chunks */ | ||
97 | size_read = read(orig_file, buf, sizeof(buf)); | ||
98 | if(size_read != write(dest_file, buf, size_read)) { | ||
99 | close(orig_file); | ||
100 | close(dest_file); | ||
101 | return(3); | ||
102 | } | ||
103 | size += size_read; | ||
104 | |||
105 | } while(size_read > 0); | ||
106 | |||
107 | close(orig_file); | ||
108 | close(dest_file); | ||
109 | |||
110 | printf("Finished copying %ld bytes from", size); | ||
111 | printf("FWIMG01.DAT.ORIG to FWIMG01.DAT"); | ||
112 | |||
113 | return(0); | ||
114 | } | ||
115 | |||
116 | char buf[256]; | ||
117 | |||
118 | void display_instructions(void) | ||
119 | { | ||
120 | lcd_setfont(FONT_SYSFIXED); | ||
121 | 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); | ||
126 | } | ||
127 | |||
128 | void * main(void) | ||
129 | { | ||
130 | int i; | ||
131 | struct partinfo* pinfo; | ||
132 | unsigned short* identify_info; | ||
133 | unsigned char* loadbuffer; | 52 | unsigned char* loadbuffer; |
134 | int buffer_size; | 53 | int buffer_size; |
135 | bool load_original = false; | ||
136 | int rc; | 54 | int rc; |
137 | int(*kernel_entry)(void); | 55 | int(*kernel_entry)(void); |
138 | 56 | ||
139 | bool show_bootsplash = true; | 57 | memory_init(); |
140 | 58 | power_init(); | |
141 | if(GPGDAT & 2) | 59 | system_init(); |
142 | show_bootsplash = false; | 60 | lcd_init(); |
61 | backlight_init(); | ||
62 | font_init(); | ||
143 | 63 | ||
144 | if(!show_bootsplash) { | 64 | lcd_setfont(FONT_SYSFIXED); |
145 | lcd_init(); | ||
146 | display_instructions(); | ||
147 | sleep(2*HZ); | ||
148 | } | ||
149 | if(GPGDAT & 2) { | ||
150 | lcd_init(); | ||
151 | printf("Entering rescue mode.."); | ||
152 | go_usb_mode(); | ||
153 | while(1); | ||
154 | } | ||
155 | if(GPGDAT & 0x10) { | ||
156 | lcd_init(); | ||
157 | load_original = true; | ||
158 | printf("Loading original firmware..."); | ||
159 | } | ||
160 | |||
161 | i = ata_init(); | ||
162 | i = disk_mount_all(); | ||
163 | if(!show_bootsplash) { | ||
164 | printf("disk_mount_all: %d", i); | ||
165 | } | ||
166 | 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 | } | ||
180 | /* hold VOL+ to enter rescue mode to copy old image */ | ||
181 | /* needs to be after ata_init and disk_mount_all */ | ||
182 | if(GPGDAT & 4) { | ||
183 | |||
184 | /* Try to restore the original kernel/bootloader if a copy is found */ | ||
185 | printf("Restoring FWIMG01.DAT..."); | ||
186 | |||
187 | if(!restore_fwimg01dat()) { | ||
188 | printf("Restoring FWIMG01.DAT successful."); | ||
189 | } else { | ||
190 | printf("Restoring FWIMG01.DAT failed."); | ||
191 | } | ||
192 | |||
193 | printf("Now power cycle to boot original"); | ||
194 | while(1); | ||
195 | } | ||
196 | |||
197 | 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 | 65 | ||
205 | /* kill trailing space */ | 66 | usb_init(); |
206 | for(i=39; i && buf[i]==' '; i--) | ||
207 | buf[i] = 0; | ||
208 | 67 | ||
209 | printf("Model"); | 68 | /* Enter USB mode without USB thread */ |
210 | printf(buf); | 69 | if(usb_detect()) |
70 | { | ||
71 | const char msg[] = "Bootloader USB mode"; | ||
72 | reset_screen(); | ||
73 | lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, | ||
74 | (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); | ||
75 | lcd_update(); | ||
211 | 76 | ||
212 | for(i=0; i < 4; i++) | 77 | ata_enable(false); |
213 | ((unsigned short*)buf)[i]=htobe16(identify_info[i+23]); | 78 | sleep(HZ/20); |
79 | usb_enable(true); | ||
214 | 80 | ||
215 | buf[8]=0; | 81 | while (usb_detect()) |
82 | sleep(HZ); | ||
216 | 83 | ||
217 | printf("Firmware"); | 84 | usb_enable(false); |
218 | printf(buf); | ||
219 | 85 | ||
220 | pinfo = disk_partinfo(0); | 86 | reset_screen(); |
221 | printf("Partition 0: 0x%02x %ld MB", pinfo->type, pinfo->size / 2048); | 87 | lcd_update(); |
88 | } | ||
89 | |||
90 | kernel_init(); | ||
91 | adc_init(); | ||
92 | button_init(); | ||
93 | |||
94 | /* Show debug messages if button is pressed */ | ||
95 | if(button_read_device()) | ||
96 | verbose = true; | ||
97 | |||
98 | printf("Rockbox boot loader"); | ||
99 | printf("Version %s", version); | ||
100 | |||
101 | rc = ata_init(); | ||
102 | if(rc) | ||
103 | { | ||
104 | reset_screen(); | ||
105 | error(EATA, rc); | ||
222 | } | 106 | } |
223 | /* Load original firmware */ | ||
224 | if(load_original) { | ||
225 | loadbuffer = (unsigned char*)0x30008000; | ||
226 | buffer_size =(unsigned char*)0x31000000 - loadbuffer; | ||
227 | rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size); | ||
228 | if(rc < EOK) { | ||
229 | printf("Error!"); | ||
230 | printf("Failed to load original firmware:"); | ||
231 | printf(strerror(rc)); | ||
232 | printf("Loading rockbox"); | ||
233 | sleep(2*HZ); | ||
234 | goto load_rockbox; | ||
235 | } | ||
236 | |||
237 | printf("Loaded: %d", rc); | ||
238 | sleep(2*HZ); | ||
239 | 107 | ||
240 | (*((int*)0x7000000)) = 333; | 108 | disk_init(); |
241 | rc = *((int*)0x7000000+0x8000000); | ||
242 | printf("Bank0 mem test: %d", rc); | ||
243 | sleep(3*HZ); | ||
244 | 109 | ||
245 | printf("Woops, should not return from firmware!"); | 110 | rc = disk_mount_all(); |
246 | goto usb; | 111 | if (rc<=0) |
112 | { | ||
113 | error(EDISK,rc); | ||
247 | } | 114 | } |
248 | 115 | ||
249 | load_rockbox: | 116 | printf("Loading firmware"); |
250 | map_memory(); | ||
251 | if(!show_bootsplash) { | ||
252 | printf("Loading Rockbox..."); | ||
253 | } | ||
254 | 117 | ||
255 | loadbuffer = (unsigned char*) 0x100; | 118 | loadbuffer = (unsigned char*) 0x100; |
256 | buffer_size = (unsigned char*)0x400000 - loadbuffer; | 119 | buffer_size = (unsigned char*)0x400000 - loadbuffer; |
257 | rc = load_raw_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size); | 120 | |
258 | if(rc < EOK) { | 121 | rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); |
259 | rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size); | 122 | if(rc < 0) |
260 | } | 123 | error(EBOOTFILE, rc); |
261 | if(rc < EOK) { | 124 | |
262 | printf("Error!"); | 125 | if (rc == EOK) |
263 | printf("Can't load rockbox.gigabeat:"); | 126 | { |
264 | printf(strerror(rc)); | ||
265 | } else { | ||
266 | if(!show_bootsplash) { | ||
267 | printf("Rockbox loaded."); | ||
268 | } | ||
269 | kernel_entry = (void*) loadbuffer; | 127 | kernel_entry = (void*) loadbuffer; |
270 | rc = kernel_entry(); | 128 | rc = kernel_entry(); |
271 | printf("Woops, should not return from firmware: %d", rc); | ||
272 | goto usb; | ||
273 | } | 129 | } |
274 | usb: | ||
275 | /* now wait in USB mode so the bootloader can be updated */ | ||
276 | go_usb_mode(); | ||
277 | while(1); | ||
278 | |||
279 | return((void *)0); | ||
280 | } | 130 | } |
281 | 131 | ||