summaryrefslogtreecommitdiff
path: root/bootloader/main-pp.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader/main-pp.c')
-rw-r--r--bootloader/main-pp.c280
1 files changed, 269 insertions, 11 deletions
diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c
index 960e570889..64f9e79a93 100644
--- a/bootloader/main-pp.c
+++ b/bootloader/main-pp.c
@@ -29,6 +29,80 @@
29#include "ata.h" 29#include "ata.h"
30#include "button.h" 30#include "button.h"
31#include "disk.h" 31#include "disk.h"
32#include <string.h>
33
34/*
35 * CRC32 implementation taken from:
36 *
37 * efone - Distributed internet phone system.
38 *
39 * (c) 1999,2000 Krzysztof Dabrowski
40 * (c) 1999,2000 ElysiuM deeZine
41 *
42 * This program is free software; you can redistribute it and/or
43 * modify it under the terms of the GNU General Public License
44 * as published by the Free Software Foundation; either version
45 * 2 of the License, or (at your option) any later version.
46 *
47 */
48
49/* based on implementation by Finn Yannick Jacobs */
50
51#include <stdio.h>
52#include <stdlib.h>
53
54/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
55 * so make sure, you call it before using the other
56 * functions!
57 */
58static unsigned int crc_tab[256];
59
60/* chksum_crc() -- to a given block, this one calculates the
61 * crc32-checksum until the length is
62 * reached. the crc32-checksum will be
63 * the result.
64 */
65unsigned int chksum_crc32 (unsigned char *block, unsigned int length)
66{
67 register unsigned long crc;
68 unsigned long i;
69
70 crc = 0;
71 for (i = 0; i < length; i++)
72 {
73 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
74 }
75 return (crc);
76}
77
78/* chksum_crc32gentab() -- to a global crc_tab[256], this one will
79 * calculate the crcTable for crc32-checksums.
80 * it is generated to the polynom [..]
81 */
82
83static void chksum_crc32gentab (void)
84{
85 unsigned long crc, poly;
86 int i, j;
87
88 poly = 0xEDB88320L;
89 for (i = 0; i < 256; i++)
90 {
91 crc = i;
92 for (j = 8; j > 0; j--)
93 {
94 if (crc & 1)
95 {
96 crc = (crc >> 1) ^ poly;
97 }
98 else
99 {
100 crc >>= 1;
101 }
102 }
103 crc_tab[i] = crc;
104 }
105}
32 106
33/* Button definitions */ 107/* Button definitions */
34#if CONFIG_KEYPAD == IRIVER_H10_PAD 108#if CONFIG_KEYPAD == IRIVER_H10_PAD
@@ -50,21 +124,167 @@ unsigned char *loadbuffer = (unsigned char *)DRAM_START;
50/* Bootloader version */ 124/* Bootloader version */
51char version[] = APPSVERSION; 125char version[] = APPSVERSION;
52 126
127/* Locations and sizes in hidden partition on Sansa */
128#define PPMI_OFFSET 1024
129#define PPMI_SIZE 1
130#define MI4_HEADER_SIZE 1
131
132/* mi4 header structure */
133struct mi4header_t {
134 unsigned char magic[4];
135 uint32_t version;
136 uint32_t length;
137 uint32_t crc32;
138 uint32_t enctype;
139 uint32_t mi4size;
140 uint32_t plaintext;
141 uint32_t dsa_key[10];
142 uint32_t pad[109];
143 unsigned char type[4];
144 unsigned char model[4];
145};
146
147/* PPMI header structure */
148struct ppmi_header_t {
149 unsigned char magic[4];
150 uint32_t length;
151 uint32_t pad[126];
152};
153
154/* Load mi4 format firmware image */
155int load_mi4(unsigned char* buf, char* firmware, unsigned int buffer_size)
156{
157 int fd;
158 struct mi4header_t mi4header;
159 int rc;
160 unsigned long sum;
161 char filename[MAX_PATH];
162
163 snprintf(filename,sizeof(filename),"/.rockbox/%s",firmware);
164 fd = open(filename, O_RDONLY);
165 if(fd < 0)
166 {
167 snprintf(filename,sizeof(filename),"/%s",firmware);
168 fd = open(filename, O_RDONLY);
169 if(fd < 0)
170 return EFILE_NOT_FOUND;
171 }
172
173 read(fd, &mi4header, 0x200);
174
175 /* We don't support encrypted mi4 files yet */
176 if( (mi4header.plaintext + 0x200) != mi4header.mi4size)
177 return EINVALID_FORMAT;
178
179 /* MI4 file size */
180 printf("mi4 size: %x", mi4header.length);
181
182 if (mi4header.length > buffer_size)
183 return EFILE_TOO_BIG;
184
185 /* CRC32 */
186 printf("CRC32: %x", mi4header.crc32);
187
188 /* Rockbox model id */
189 printf("Model id: %4s", mi4header.model);
190
191 /* Read binary type (RBOS, RBBL) */
192 printf("Binary type: %4s", mi4header.type);
193
194 /* Load firmware */
195 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
196 rc = read(fd, buf, mi4header.mi4size-0x200);
197 if(rc < (int)mi4header.mi4size-0x200)
198 return EREAD_IMAGE_FAILED;
199
200 /* Check CRC32 to see if we have a valid file */
201 sum = chksum_crc32 (buf,mi4header.mi4size-0x200);
202
203 printf("Calculated CRC32: %x", sum);
204
205 if(sum != mi4header.crc32)
206 return EBAD_CHKSUM;
207
208 return EOK;
209}
210
211/* Load mi4 firmware from a hidden disk partition */
212int load_mi4_part(unsigned char* buf, struct partinfo* pinfo, unsigned int buffer_size)
213{
214 struct mi4header_t mi4header;
215 struct ppmi_header_t ppmi_header;
216 unsigned long sum;
217
218 /* Read header to find out how long the mi4 file is. */
219 ata_read_sectors(pinfo->start + PPMI_OFFSET, PPMI_SIZE, &ppmi_header);
220
221 /* The first four characters at 0x80000 (sector 1024) should be PPMI*/
222 if( memcmp(ppmi_header.magic, "PPMI", 4) )
223 return EFILE_NOT_FOUND;
224
225 printf("BL mi4 size: %x", ppmi_header.length);
226
227 /* Read mi4 header of the OF */
228 ata_read_sectors(pinfo->start + PPMI_OFFSET + PPMI_SIZE
229 + (ppmi_header.length/512), MI4_HEADER_SIZE, &mi4header);
230
231 /* We don't support encrypted mi4 files yet */
232 if( (mi4header.plaintext + 0x200) != mi4header.mi4size)
233 return EINVALID_FORMAT;
234
235 /* MI4 file size */
236 printf("OF mi4 size: %x", mi4header.length);
237
238 if (mi4header.length > buffer_size)
239 return EFILE_TOO_BIG;
240
241 /* CRC32 */
242 printf("CRC32: %x", mi4header.crc32);
243
244 /* Rockbox model id */
245 printf("Model id: %4s", mi4header.model);
246
247 /* Read binary type (RBOS, RBBL) */
248 printf("Binary type: %4s", mi4header.type);
249
250 /* Load firmware */
251 ata_read_sectors(pinfo->start + PPMI_OFFSET + PPMI_SIZE
252 + (ppmi_header.length/512) + MI4_HEADER_SIZE,
253 (mi4header.length-0x200)/512, buf);
254
255 /* Check CRC32 to see if we have a valid file */
256 sum = chksum_crc32 (buf,mi4header.mi4size-0x200);
257
258 printf("Calculated CRC32: %x", sum);
259
260 if(sum != mi4header.crc32)
261 return EBAD_CHKSUM;
262
263 return EOK;
264}
265
53void* main(void) 266void* main(void)
54{ 267{
55 char buf[256]; 268 char buf[256];
56 int i; 269 int i;
57 int btn; 270 int btn;
58 int rc; 271 int rc;
272 int num_partitions;
59 unsigned short* identify_info; 273 unsigned short* identify_info;
60 struct partinfo* pinfo; 274 struct partinfo* pinfo;
61 275
276 chksum_crc32gentab ();
277
62 system_init(); 278 system_init();
63 kernel_init(); 279 kernel_init();
64 lcd_init(); 280 lcd_init();
65 font_init(); 281 font_init();
66 button_init(); 282 button_init();
67 283
284 lcd_set_foreground(LCD_WHITE);
285 lcd_set_background(LCD_BLACK);
286 lcd_clear_display();
287
68 btn = button_read_device(); 288 btn = button_read_device();
69 289
70 /* Enable bootloader messages */ 290 /* Enable bootloader messages */
@@ -94,31 +314,69 @@ void* main(void)
94 } 314 }
95 315
96 disk_init(); 316 disk_init();
97 rc = disk_mount_all(); 317 num_partitions = disk_mount_all();
98 if (rc<=0) 318 if (num_partitions<=0)
99 { 319 {
100 error(EDISK,rc); 320 error(EDISK,num_partitions);
101 } 321 }
102 322
103 pinfo = disk_partinfo(0); 323 /* Just list the first 2 partitions since we don't have any devices yet
104 printf("Partition 0: 0x%02x %ld MB", pinfo->type, pinfo->size / 2048); 324 that have more than that */
325 for(i=0; i<2; i++)
326 {
327 pinfo = disk_partinfo(i);
328 printf("Partition %d: 0x%02x %ld MB",
329 i, pinfo->type, pinfo->size / 2048);
330 }
105 331
106 if(btn & BOOTLOADER_BOOT_OF) 332 if(btn & BOOTLOADER_BOOT_OF)
107 { 333 {
108 /* Load original mi4 firmware. This expects a file called 334 /* Load original mi4 firmware in to a memory buffer called loadbuffer.
109 "/System/OF.bin" on the player. It should be a mi4 firmware decrypted 335 The rest of the loading is done in crt0.S.
110 and header stripped using mi4code. It reads the file in to a memory 336 1) First try reading from the hidden partition (on Sansa only).
111 buffer called loadbuffer. The rest of the loading is done in crt0.S 337 2) Next try a decrypted mi4 file in /System/OF.mi4
338 3) Finally, try a raw firmware binary in /System/OF.mi4. It should be
339 a mi4 firmware decrypted and header stripped using mi4code.
112 */ 340 */
113 printf("Loading original firmware..."); 341 printf("Loading original firmware...");
342
343 /* First try a hidden partition */
344 printf("Trying hidden partition");
345 pinfo = disk_partinfo(1);
346 if(pinfo->type == PARTITION_TYPE_HIDDEN)
347 {
348 rc = load_mi4_part(loadbuffer, pinfo, MAX_LOADSIZE);
349 if (rc < EOK) {
350 printf("Can't load from partition");
351 printf(strerror(rc));
352 } else {
353 return (void*)loadbuffer;
354 }
355 } else {
356 printf("No hidden partition found.");
357 }
358
359 printf("Trying /System/OF.mi4");
360 rc=load_mi4(loadbuffer, "/System/OF.mi4", MAX_LOADSIZE);
361 if (rc < EOK) {
362 printf("Can't load /System/OF.mi4");
363 printf(strerror(rc));
364 } else {
365 return (void*)loadbuffer;
366 }
367
368 printf("Trying /System/OF.bin");
114 rc=load_raw_firmware(loadbuffer, "/System/OF.bin", MAX_LOADSIZE); 369 rc=load_raw_firmware(loadbuffer, "/System/OF.bin", MAX_LOADSIZE);
115 if (rc < EOK) { 370 if (rc < EOK) {
116 printf("Can't load /System/OF.bin"); 371 printf("Can't load /System/OF.bin");
117 error(EBOOTFILE, rc); 372 printf(strerror(rc));
373 } else {
374 return (void*)loadbuffer;
118 } 375 }
376
119 } else { 377 } else {
120 printf("Loading Rockbox..."); 378 printf("Loading Rockbox...");
121 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE); 379 rc=load_mi4(loadbuffer, BOOTFILE, MAX_LOADSIZE);
122 if (rc < EOK) { 380 if (rc < EOK) {
123 printf("Can't load %s:", BOOTFILE); 381 printf("Can't load %s:", BOOTFILE);
124 error(EBOOTFILE, rc); 382 error(EBOOTFILE, rc);