summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/iriver_flash.c1123
-rw-r--r--firmware/export/config/iriverh100.h1
-rw-r--r--firmware/export/config/iriverh120.h1
-rw-r--r--firmware/export/config/iriverh300.h1
-rw-r--r--firmware/export/system.h4
5 files changed, 617 insertions, 513 deletions
diff --git a/apps/plugins/iriver_flash.c b/apps/plugins/iriver_flash.c
index 9d1c3456a6..e5da55c7ed 100644
--- a/apps/plugins/iriver_flash.c
+++ b/apps/plugins/iriver_flash.c
@@ -9,7 +9,8 @@
9 * 9 *
10 * !!! DON'T MESS WITH THIS CODE UNLESS YOU'RE ABSOLUTELY SURE WHAT YOU DO !!! 10 * !!! DON'T MESS WITH THIS CODE UNLESS YOU'RE ABSOLUTELY SURE WHAT YOU DO !!!
11 * 11 *
12 * Copyright (C) 2006 by Miika Pekkarinen 12 * Copyright (C) 2020 by James Buren (refactor + H300 support)
13 * Copyright (C) 2006 by Miika Pekkarinen (original + H100/H120 support)
13 * 14 *
14 * This program is free software; you can redistribute it and/or 15 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License 16 * modify it under the terms of the GNU General Public License
@@ -22,93 +23,185 @@
22 ****************************************************************************/ 23 ****************************************************************************/
23#include "plugin.h" 24#include "plugin.h"
24 25
25/* cfi_program_word() relies on writing to address 0, which normally is illegal. 26/*
26 So we need this to ensure we don't helpfully optimize it away into a TRAP 27 * Flash commands may rely on null pointer dereferences to work correctly.
27 when compiled with -fdelete-null-pointer-checks, which is enabled by default 28 * Disable this feature of GCC that may interfere with proper code generation.
28 at -Os with our current gcc 4.9.x toolchain. 29 */
29*/
30#pragma GCC optimize "no-delete-null-pointer-checks" 30#pragma GCC optimize "no-delete-null-pointer-checks"
31 31
32/* All CFI flash routines are copied and ported from firmware_flash.c */ 32enum firmware
33{
34 FIRMWARE_ROCKBOX, /* all .iriver firmwares */
35 FIRMWARE_ROMDUMP, /* a debug romdump */
36 FIRMWARE_ORIGINAL, /* an unscrambled original firmware */
37};
38
39#define WORD_SIZE 2
40#define BOOT_VECTOR_SIZE 8
41#define BOOT_SECTOR_OFFSET 0
42#define SECTOR_SIZE 4096
43#define BOOTLOADER_MAX_SIZE 65536
44#define BOOTLOADER_SECTORS (BOOTLOADER_MAX_SIZE / SECTOR_SIZE)
45#define RAM_IMAGE_RAW_SIZE (FLASH_ROMIMAGE_ENTRY - FLASH_RAMIMAGE_ENTRY)
46#define RAM_IMAGE_MAX_SIZE (RAM_IMAGE_RAW_SIZE - sizeof(struct flash_header))
47#define RAM_IMAGE_SECTORS (RAM_IMAGE_RAW_SIZE / SECTOR_SIZE)
48#define ROM_IMAGE_RAW_SIZE (BOOTLOADER_ENTRYPOINT - FLASH_ROMIMAGE_ENTRY)
49#define ROM_IMAGE_MAX_SIZE (ROM_IMAGE_RAW_SIZE - sizeof(struct flash_header))
50#define ROM_IMAGE_SECTORS (ROM_IMAGE_RAW_SIZE / SECTOR_SIZE)
51#define ROM_IMAGE_RELOCATION (FLASH_ROMIMAGE_ENTRY + sizeof(struct flash_header))
52#define WHOLE_FIRMWARE_SECTORS (BOOTLOADER_ENTRYPOINT / SECTOR_SIZE)
53#define FIRMWARE_OFFSET 544
54
55#if BOOTLOADER_ENTRYPOINT + BOOTLOADER_MAX_SIZE != FLASH_SIZE
56#error "Bootloader is not located at the end of flash."
57#endif
33 58
34uint8_t* audiobuf; 59#if FLASH_ROMIMAGE_ENTRY < FLASH_RAMIMAGE_ENTRY
35ssize_t audiobuf_size; 60#error "RAM image must be located before the ROM image."
61#endif
62
63#if BOOTLOADER_ENTRYPOINT < FLASH_ROMIMAGE_ENTRY
64#error "ROM image must be located before the bootloader."
65#endif
36 66
37#if !defined(IRIVER_H100_SERIES) && !defined(IRIVER_H300_SERIES) 67#if FLASH_SIZE == 2048 * 1024
38#error this platform is not (yet) flashable 68#define ROMDUMP "/internal_rom_000000-1FFFFF.bin"
69#elif FLASH_SIZE == 4096 * 1024
70#define ROMDUMP "/internal_rom_000000-3FFFFF.bin"
39#endif 71#endif
40 72
41#if CONFIG_KEYPAD == IRIVER_H100_PAD 73#ifdef IRIVER_H100
42#define KEY1 BUTTON_OFF 74#define MODEL (const uint8_t[]) { 'h', '1', '0', '0' }
43#define KEY2 BUTTON_ON 75#define ORIGINAL "/ihp_100.bin"
44#define KEY3 BUTTON_SELECT 76#elif defined(IRIVER_H120)
45#define KEYNAME1 "[Stop]" 77#define MODEL (const uint8_t[]) { 'h', '1', '2', '0' }
46#define KEYNAME2 "[On]" 78#define ORIGINAL "/ihp_120.bin"
47#define KEYNAME3 "[Select]" 79#elif defined(IRIVER_H300)
80#define MODEL (const uint8_t[]) { 'h', '3', '0', '0' }
81#define ORIGINAL "/H300.bin"
82#else
83#error "Unsupported target."
48#endif 84#endif
49 85
50struct flash_info 86struct flash_info
51{ 87{
52 uint16_t manufacturer; 88 uint16_t vendor;
53 uint16_t id; 89 uint16_t product;
54 uint32_t size; 90 uint32_t size;
55 char name[32]; 91 char name[16];
56}; 92};
57 93
58#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) 94/* checks if the region has a valid bootloader */
59#define SEC_SIZE 4096 95static bool detect_valid_bootloader(const void* ptr, uint32_t size)
60#define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE) 96{
61enum sections { 97 static const struct
62 SECT_RAMIMAGE = 1, 98 {
63 SECT_ROMIMAGE = 2, 99 uint32_t size;
64}; 100 uint32_t crc32;
65 101 }
66static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */ 102 bootloaders[] =
103 {
104#ifdef IRIVER_H100
105 { 48760, 0x2efc3323 }, /* 7-pre4 */
106 { 56896, 0x0cd8dad4 }, /* 7-pre5 */
107#elif defined(IRIVER_H120)
108 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
109 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
110 { 56896, 0x167f5d25 }, /* 7-pre5, various ATA fixes */
111#elif defined(IRIVER_H300)
67#endif 112#endif
113 {0}
114 };
68 115
69#ifdef IRIVER_H100 /* iRiver H110/H115 */ 116 for (size_t i = 0; bootloaders[i].size != 0; i++)
70#define MODEL "h100" 117 {
71#elif defined(IRIVER_H120) /* iRiver H120/H140 */ 118 uint32_t crc32;
72#define MODEL "h120" 119
73#elif defined(IRIVER_H300) /* iRiver H320/H340 */ 120 if (size != 0 && size != bootloaders[i].size)
74#define MODEL "h300" 121 continue;
75#endif 122
123 crc32 = rb->crc_32(ptr, bootloaders[i].size, 0xFFFFFFFF);
124 if (crc32 == bootloaders[i].crc32)
125 return true;
126 }
127
128 return false;
129}
130
131/* get read-only access to flash at the given offset */
132static const void* flash(uint32_t offset)
133{
134 const uint16_t* FB = (uint16_t*) FLASH_BASE;
135 return &FB[offset / WORD_SIZE];
136}
76 137
77/* read the manufacturer and device ID */ 138/* queries the rom for information and returns it if it is known */
78static void cfi_read_id(struct flash_info* pInfo) 139static bool flash_get_info(const struct flash_info** out_info)
79{ 140{
80 FB[0x5555] = 0xAA; /* enter command mode */ 141 static const struct flash_info roms[] =
142 {
143 { 0x00BF, 0x2782, 2048 * 1024, "SST39VF160" },
144 { 0x00BF, 0x235B, 4096 * 1024, "SST39VF3201" },
145 {0}
146 };
147 static struct flash_info unknown_rom = {0};
148 volatile uint16_t* FB = (uint16_t*) FLASH_BASE;
149 uint16_t vendor;
150 uint16_t product;
151
152 /* execute the software ID entry command */
153 FB[0x5555] = 0xAA;
81 FB[0x2AAA] = 0x55; 154 FB[0x2AAA] = 0x55;
82 FB[0x5555] = 0x90; /* enter ID mode */ 155 FB[0x5555] = 0x90;
83 rb->sleep(HZ/100); /* we only need to sleep 150ns but 10ms is the minimum */ 156 rb->sleep(HZ / 100);
84 157
85 pInfo->manufacturer = FB[0]; 158 /* copy the IDs from the previous command */
86 pInfo->id = FB[1]; 159 vendor = FB[0];
160 product = FB[1];
87 161
88 FB[0x5555] = 0xAA; /* enter command mode */ 162 /* execute the software ID exit command */
163 FB[0x5555] = 0xAA;
89 FB[0x2AAA] = 0x55; 164 FB[0x2AAA] = 0x55;
90 FB[0x5555] = 0xF0; /* exit ID mode */ 165 FB[0x5555] = 0xF0;
91 rb->sleep(HZ/100); /* we only need to sleep 150ns but 10ms is the minimum */ 166 rb->sleep(HZ / 100);
167
168 /* search for a known match */
169 for (size_t i = 0; roms[i].size != 0; i++)
170 {
171 if (roms[i].vendor == vendor && roms[i].product == product)
172 {
173 *out_info = &roms[i];
174 return true;
175 }
176 }
177
178 /* return only the vendor / product ids if unknown */
179 unknown_rom.vendor = vendor;
180 unknown_rom.product = product;
181 *out_info = &unknown_rom;
182 return false;
92} 183}
93 184
94/* wait until the rom signals completion of an operation */ 185/* wait until the rom signals completion of an operation */
95static bool cfi_wait_for_rom(volatile uint16_t* pAddr) 186static bool flash_wait_for_rom(uint32_t offset)
96{ 187{
97 const unsigned MAX_TIMEOUT = 0xffffff; /* should be sufficient for most targets */ 188 const size_t MAX_TIMEOUT = 0xFFFFFF; /* should be sufficient for most targets */
98 const unsigned RECOVERY_TIME = 64; /* based on 140MHz MCF 5249 */ 189 const size_t RECOVERY_TIME = 64; /* based on 140MHz MCF 5249 */
99 uint16_t old_data = *pAddr & 0x0040; /* we only want DQ6 */ 190 volatile uint16_t* FB = (uint16_t*) FLASH_BASE;
100 volatile unsigned i; /* disables certain optimizations */ 191 uint16_t old_data = FB[offset / WORD_SIZE] & 0x0040; /* we only want DQ6 */
192 volatile size_t i; /* disables certain optimizations */
193 bool result;
101 194
102 /* repeat up to MAX_TIMEOUT times or until DQ6 stops flipping */ 195 /* repeat up to MAX_TIMEOUT times or until DQ6 stops flipping */
103 for (i = 0; i < MAX_TIMEOUT; i++) 196 for (i = 0; i < MAX_TIMEOUT; i++)
104 { 197 {
105 uint16_t new_data = *pAddr & 0x0040; /* we only want DQ6 */ 198 uint16_t new_data = FB[offset / WORD_SIZE] & 0x0040; /* we only want DQ6 */
106 if(old_data == new_data) 199 if (old_data == new_data)
107 break; 200 break;
108 old_data = new_data; 201 old_data = new_data;
109 } 202 }
110 203
111 bool result = i != MAX_TIMEOUT; 204 result = i != MAX_TIMEOUT;
112 205
113 /* delay at least 1us to give the bus time to recover */ 206 /* delay at least 1us to give the bus time to recover */
114 for (i = 0; i < RECOVERY_TIME; i++); 207 for (i = 0; i < RECOVERY_TIME; i++);
@@ -116,646 +209,654 @@ static bool cfi_wait_for_rom(volatile uint16_t* pAddr)
116 return result; 209 return result;
117} 210}
118 211
119/* erase the sector which contains the given address */ 212/* erase the sector at the given offset */
120static bool cfi_erase_sector(volatile uint16_t* pAddr) 213static bool flash_erase_sector(uint32_t offset)
121{ 214{
122 FB[0x5555] = 0xAA; /* enter command mode */ 215 volatile uint16_t* FB = (uint16_t*) FLASH_BASE;
216
217 /* execute the sector erase command */
218 FB[0x5555] = 0xAA;
123 FB[0x2AAA] = 0x55; 219 FB[0x2AAA] = 0x55;
124 FB[0x5555] = 0x80; /* erase command */ 220 FB[0x5555] = 0x80;
125 FB[0x5555] = 0xAA; /* enter command mode */ 221 FB[0x5555] = 0xAA;
126 FB[0x2AAA] = 0x55; 222 FB[0x2AAA] = 0x55;
127 *pAddr = 0x30; /* erase the sector */ 223 FB[offset / WORD_SIZE] = 0x30;
128 224
129 return cfi_wait_for_rom(pAddr); 225 return flash_wait_for_rom(offset);
130} 226}
131 227
132/* address must be in an erased location */ 228/* program a word at the given offset */
133static bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) 229static bool flash_program_word(uint32_t offset, uint16_t word)
134{ 230{
135 FB[0x5555] = 0xAA; /* enter command mode */ 231 volatile uint16_t* FB = (uint16_t*) FLASH_BASE;
232
233 /* execute the word program command */
234 FB[0x5555] = 0xAA;
136 FB[0x2AAA] = 0x55; 235 FB[0x2AAA] = 0x55;
137 FB[0x5555] = 0xA0; /* byte program command */ 236 FB[0x5555] = 0xA0;
138 *pAddr = data; /* write the word data */ 237 FB[offset / WORD_SIZE] = word;
139 238
140 return cfi_wait_for_rom(pAddr); 239 return flash_wait_for_rom(offset);
141} 240}
142 241
143/* fills in the struct with data about the flash rom */ 242/* bulk erase of adjacent sectors */
144static void cfi_get_flash_info(struct flash_info* pInfo) 243static void flash_erase_sectors(uint32_t offset, uint32_t sectors,
244 bool progress)
145{ 245{
146 uint32_t size = 0; 246 for (uint32_t i = 0; i < sectors; i++)
147 const char* name = ""; 247 {
148 248 flash_erase_sector(offset + i * SECTOR_SIZE);
149 cfi_read_id(pInfo);
150
151 switch (pInfo->manufacturer)
152 {
153 /* SST */
154 case 0x00BF:
155 switch (pInfo->id)
156 {
157 case 0x2782:
158 size = 2048 * 1024; /* 2 MiB */
159 name = "SST39VF160";
160 break;
161 case 0x235B:
162 size = 4096 * 1024; /* 4 MiB */
163 name = "SST39VF3201";
164 break;
165 }
166 break;
167 }
168 249
169 pInfo->size = size; 250 /* display a progress report if requested */
170 rb->strcpy(pInfo->name, name); 251 if (progress)
252 {
253 rb->lcd_putsf(0, 3, "Erasing... %u%%", (i + 1) * 100 / sectors);
254 rb->lcd_update();
255 }
256 }
171} 257}
172 258
173/***************** User Interface Functions *****************/ 259/* bulk program of bytes */
174static int wait_for_button(void) 260static void flash_program_bytes(uint32_t offset, const void* ptr,
261 uint32_t len, bool progress)
175{ 262{
176 int button; 263 const uint8_t* data = ptr;
177 264
178 do 265 for (uint32_t i = 0; i < len; i += WORD_SIZE)
179 { 266 {
180 button = rb->button_get(true); 267 uint32_t j = i + 1;
181 } while (IS_SYSEVENT(button) || (button & BUTTON_REL)); 268 uint32_t k = ((j < len) ? j : i) + 1;
269 uint16_t word = (data[i] << 8) | (j < len ? data[j] : 0xFF);
270
271 flash_program_word(offset + i, word);
182 272
183 return button; 273 /* display a progress report if requested */
274 if (progress && ((i % SECTOR_SIZE) == 0 || k == len))
275 {
276 rb->lcd_putsf(0, 4, "Programming... %u%%", k * 100 / len);
277 rb->lcd_update();
278 }
279 }
184} 280}
185 281
186/* helper for DoUserDialog() */ 282/* bulk verify of programmed bytes */
187static void ShowFlashInfo(const struct flash_info* pInfo) 283static bool flash_verify_bytes(uint32_t offset, const void* ptr,
284 uint32_t len, bool progress)
188{ 285{
189 if (!pInfo->manufacturer) 286 const uint8_t* FB = flash(offset);
190 { 287 const uint8_t* data = ptr;
191 rb->lcd_puts(0, 0, "Flash: M=???? D=????"); 288
192 rb->lcd_puts(0, 1, "Impossible to program"); 289 /* don't use memcmp so we can provide progress updates */
193 } 290 for (uint32_t i = 0; i < len; i++)
194 else
195 { 291 {
196 rb->lcd_putsf(0, 0, "Flash: M=%04x D=%04x", 292 uint32_t j = i + 1;
197 pInfo->manufacturer, pInfo->id);
198 293
199 if (pInfo->size) 294 if (FB[i] != data[i])
200 { 295 return false;
201 rb->lcd_puts(0, 1, pInfo->name); 296
202 rb->lcd_putsf(0, 2, "Size: %u KB", pInfo->size / 1024); 297 /* display a progress report if requested */
203 } 298 if (progress && ((i % SECTOR_SIZE) == 0 || j == len))
204 else
205 { 299 {
206 rb->lcd_puts(0, 1, "Unsupported chip"); 300 rb->lcd_putsf(0, 5, "Verifying... %u%%", j * 100 / len);
301 rb->lcd_update();
207 } 302 }
208 } 303 }
209 304
210 rb->lcd_update(); 305 return true;
211} 306}
212 307
308/* print information about the flash chip */
213static bool show_info(void) 309static bool show_info(void)
214{ 310{
215 struct flash_info fi; 311 static const struct flash_info* fi = NULL;
216 312
217 rb->lcd_clear_display(); 313 rb->lcd_clear_display();
218 cfi_get_flash_info(&fi); 314
219 ShowFlashInfo(&fi); 315 if (fi == NULL)
220 if (fi.size == 0) /* no valid chip */ 316 flash_get_info(&fi);
317
318 rb->lcd_putsf(0, 0, "Flash: V=%04x P=%04x", fi->vendor, fi->product);
319
320 if (fi->size != 0)
321 {
322 rb->lcd_puts(0, 1, fi->name);
323 rb->lcd_putsf(0, 2, "Size: %u KB", fi->size / 1024);
324 }
325 else
221 { 326 {
222 rb->splash(HZ*3, "Sorry!"); 327 rb->lcd_puts(0, 1, "Unknown chip");
223 return false; /* exit */ 328 }
329
330 rb->lcd_update();
331
332 if (fi->size == 0)
333 {
334 rb->splash(HZ * 3, "Sorry!");
335 return false;
224 } 336 }
225 337
226 return true; 338 return true;
227} 339}
228 340
229static bool confirm(const char* msg) 341/* confirm a user's choice */
342static bool confirm_choice(const char* msg)
230{ 343{
344 long button;
231 rb->splashf(0, "%s ([PLAY] to CONFIRM)", msg); 345 rb->splashf(0, "%s ([PLAY] to CONFIRM)", msg);
232 bool ret = (wait_for_button() == BUTTON_ON); 346 do
347 button = rb->button_get(true);
348 while (IS_SYSEVENT(button) || (button & BUTTON_REL));
233 show_info(); 349 show_info();
234 return ret; 350 return (button == BUTTON_ON);
235} 351}
236 352
237static off_t load_firmware_file(const char* filename, uint32_t* out_checksum) 353/* all-in-one firmware loader */
354static bool load_firmware(const char* filename, enum firmware firmware,
355 const void** data, size_t* data_len)
238{ 356{
239 int fd; 357 bool result = false;
240 off_t len; 358 const char* msg = NULL;
241 uint32_t checksum; 359 int fd = -1;
242 char model[4]; 360 off_t fd_len;
243 uint32_t sum; 361 uint8_t* buffer;
362 size_t buffer_len;
244 363
245 fd = rb->open(filename, O_RDONLY); 364 fd = rb->open(filename, O_RDONLY);
246 if (fd < 0) 365 if (fd < 0)
247 return -1;
248
249 len = rb->filesize(fd);
250 if (audiobuf_size < len)
251 {
252 rb->splash(HZ*3, "Aborting: Out of memory!");
253 rb->close(fd);
254 return -2;
255 }
256
257 if (rb->read(fd, &checksum, sizeof(checksum)) != sizeof(checksum))
258 { 366 {
259 rb->splash(HZ*3, "Aborting: Read failure"); 367 msg = "Aborting: open failure";
260 rb->close(fd); 368 goto bail;
261 return -3;
262 } 369 }
263 370
264 if (rb->read(fd, model, sizeof(model)) != sizeof(model)) 371 /* get file and buffer lengths and acquire the buffer */
265 { 372 fd_len = rb->filesize(fd);
266 rb->splash(HZ*3, "Aborting: Read failure"); 373 buffer = rb->plugin_get_audio_buffer(&buffer_len);
267 rb->close(fd);
268 return -4;
269 }
270 374
271 len -= FIRMWARE_OFFSET_FILE_DATA; 375 /* ensure there's enough space in the buffer */
272 376 if ((size_t) fd_len > buffer_len)
273 if (rb->read(fd, audiobuf, len) != len)
274 { 377 {
275 rb->splash(HZ*3, "Aborting: Read failure"); 378 msg = "Aborting: out of memory";
276 rb->close(fd); 379 goto bail;
277 return -5;
278 } 380 }
279 381
280 rb->close(fd); 382 /* all known firmwares are less than or equal to FLASH_SIZE */
281 383 if (fd_len > FLASH_SIZE)
282 /* Verify the checksum */
283 sum = MODEL_NUMBER;
284 for (off_t i = 0; i < len; i++)
285 sum += audiobuf[i];
286
287 if (sum != checksum)
288 {
289 rb->splash(HZ*3, "Aborting: Checksums mismatch!");
290 return -6;
291 }
292
293 /* Verify the model */
294 if (rb->memcmp(model, MODEL, sizeof(model)) != 0)
295 { 384 {
296 rb->splash(HZ*3, "Aborting: Models mismatch!"); 385 msg = "Aborting: firmware too big";
297 return -7; 386 goto bail;
298 } 387 }
299 388
300 if (out_checksum != NULL) 389 /* rockbox firmware specific code */
301 *out_checksum = checksum; 390 if (firmware == FIRMWARE_ROCKBOX)
302
303 return len;
304}
305
306static const uint32_t valid_bootloaders[][2] = {
307 /* Size-8, CRC32 */
308#ifdef IRIVER_H100 /* iRiver H110/H115 */
309 { 48760, 0x2efc3323 }, /* 7-pre4 */
310 { 56896, 0x0cd8dad4 }, /* 7-pre5 */
311#elif defined(IRIVER_H120) /* iRiver H120/H140 */
312 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
313 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
314 { 56896, 0x167f5d25 }, /* 7-pre5, various ATA fixes */
315#elif defined(IRIVER_H300) /* iRiver H320/H340 */
316#endif
317 {}
318};
319
320/* check if the bootloader is a known good one */
321static bool detect_valid_bootloader(const uint8_t* pAddr, uint32_t len)
322{
323 for (size_t i = 0; valid_bootloaders[i][0]; i++)
324 { 391 {
325 if (len != valid_bootloaders[i][0]) 392 uint32_t checksum;
326 continue; 393 uint8_t model[4];
394 uint32_t sum;
327 395
328 uint32_t crc32 = rb->crc_32(pAddr, valid_bootloaders[i][0], 0xffffffff); 396 /* subtract the header length */
329 if (crc32 == valid_bootloaders[i][1]) 397 fd_len -= sizeof(checksum) + sizeof(model);
330 return true;
331 }
332 398
333 return false; 399 /* sanity check the length */
334} 400 if (fd_len < WORD_SIZE)
401 {
402 msg = "Aborting: firmware too small";
403 goto bail;
404 }
335 405
336static int get_section_address(int section) 406 /* read the various parts */
337{ 407 if (
338 if (section == SECT_RAMIMAGE) 408 rb->read(fd, &checksum, sizeof(checksum)) != sizeof(checksum) ||
339 return FLASH_RAMIMAGE_ENTRY; 409 rb->read(fd, model, sizeof(model)) != sizeof(model) ||
340 else if (section == SECT_ROMIMAGE) 410 rb->read(fd, buffer, fd_len) != fd_len
341 return FLASH_ROMIMAGE_ENTRY; 411 )
342 else 412 {
343 return -1; 413 msg = "Aborting: read failure";
344} 414 goto bail;
415 }
345 416
346int flash_rockbox(const char *filename, int section) 417 /* calculate the checksum */
347{ 418 sum = MODEL_NUMBER;
348 struct flash_header hdr; 419 for (off_t i = 0; i < fd_len; i++)
349 int pos, i, len/*, rc */; 420 sum += buffer[i];
350 unsigned long checksum, sum;
351 unsigned char *p8;
352 uint16_t *p16;
353 421
354 if (get_section_address(section) < 0) 422 /* verify the checksum */
355 return -1; 423 if (sum != checksum)
424 {
425 msg = "Aborting: checksum mismatch";
426 goto bail;
427 }
356 428
357 p8 = (char *)BOOTLOADER_ENTRYPOINT; 429 /* verify the model */
358 if (!detect_valid_bootloader(p8, 0)) 430 if (rb->memcmp(model, MODEL, sizeof(model)) != 0)
359 { 431 {
360 rb->splash(HZ*3, "Incompatible bootloader"); 432 msg = "Aborting: model mismatch";
361 return -1; 433 goto bail;
434 }
362 } 435 }
363 436
364 if (!rb->detect_original_firmware()) 437 /* romdump specific code */
365 { 438 if (firmware == FIRMWARE_ROMDUMP)
366 if (!confirm("Update Rockbox flash image?"))
367 return -2;
368 }
369 else
370 { 439 {
371 if (!confirm("Erase original firmware?")) 440 /* the romdump should be exactly the same size as the flash */
372 return -3; 441 if (fd_len != FLASH_SIZE)
373 } 442 {
374 443 msg = "Aborting: firmware size incorrect";
375 len = load_firmware_file(filename, &checksum); 444 goto bail;
376 if (len <= 0) 445 }
377 return len * 10;
378
379 pos = get_section_address(section);
380 446
381 /* Check if image relocation seems to be sane. */ 447 /* exclude boot vector and boot loader regions */
382 if (section == SECT_ROMIMAGE) 448 fd_len = BOOTLOADER_ENTRYPOINT - BOOT_VECTOR_SIZE;
383 {
384 uint32_t *p32 = (uint32_t *)audiobuf;
385 449
386 if (pos+sizeof(struct flash_header) != *p32) 450 /* skip the boot vector */
451 if (rb->lseek(fd, BOOT_VECTOR_SIZE, SEEK_SET) != BOOT_VECTOR_SIZE)
387 { 452 {
388 rb->splashf(HZ*10, "Incorrect relocation: 0x%08lx/0x%08lx", 453 msg = "Aborting: lseek failure";
389 *p32, pos+sizeof(struct flash_header)); 454 goto bail;
390 return -1;
391 } 455 }
392 456
457 /* read everything up to the boot loader */
458 if (rb->read(fd, buffer, fd_len) != fd_len)
459 {
460 msg = "Aborting: read failure";
461 goto bail;
462 }
393 } 463 }
394 464
395 /* Erase the program flash. */ 465 /* original firmware specific code */
396 for (i = 0; i + pos < BOOTLOADER_ENTRYPOINT && i < len + 32; i += SEC_SIZE) 466 if (firmware == FIRMWARE_ORIGINAL)
397 { 467 {
398 /* Additional safety check. */ 468 uint32_t boot_vector[2];
399 if (i + pos < SEC_SIZE)
400 return -1;
401
402 rb->lcd_putsf(0, 3, "Erasing... %d%%", (i+SEC_SIZE)*100/len);
403 rb->lcd_update();
404 469
405 /*rc = */cfi_erase_sector(FB + (i + pos)/2); 470 /* subtract the offset and the size of the boot vector */
406 } 471 fd_len -= FIRMWARE_OFFSET + sizeof(boot_vector);
407
408 /* Write the magic and size. */
409 rb->memset(&hdr, 0, sizeof(struct flash_header));
410 hdr.magic = FLASH_MAGIC;
411 hdr.length = len;
412 // rb->strncpy(hdr.version, rb->rbversion , sizeof(hdr.version)-1);
413 p16 = (uint16_t *)&hdr;
414 472
415 rb->lcd_puts(0, 4, "Programming..."); 473 /* sanity check the length */
416 rb->lcd_update(); 474 if (fd_len < WORD_SIZE)
475 {
476 msg = "Aborting: firmware too small";
477 goto bail;
478 }
417 479
418 pos = get_section_address(section)/2; 480 /* skip the leading bytes, whatever they are */
419 for (i = 0; i < (long)sizeof(struct flash_header)/2; i++) 481 if (rb->lseek(fd, FIRMWARE_OFFSET, SEEK_SET) != FIRMWARE_OFFSET)
420 { 482 {
421 cfi_program_word(FB + pos, p16[i]); 483 msg = "Aborting: lseek failure";
422 pos++; 484 goto bail;
423 } 485 }
424 486
425 p16 = (uint16_t *)audiobuf; 487 /* read the various parts */
426 for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) 488 if (
427 { 489 rb->read(fd, boot_vector, sizeof(boot_vector)) != sizeof(boot_vector) ||
428 if (i % SEC_SIZE == 0) 490 rb->read(fd, buffer, fd_len) != fd_len
491 )
429 { 492 {
430 rb->lcd_putsf(0, 4, "Programming... %d%%", (i+1)*100/(len/2)); 493 msg = "Aborting: read failure";
431 rb->lcd_update(); 494 goto bail;
432 } 495 }
433 496
434 cfi_program_word(FB + pos + i, p16[i]); 497 /* verify the boot vector */
498 if (boot_vector[0] != 0x10017ff0 || boot_vector[1] != 0x00000008)
499 {
500 msg = "Aborting: not an original firmware";
501 goto bail;
502 }
435 } 503 }
436 504
437 /* Verify */ 505 /* write the resulting buffer and length in the output parameters */
438 rb->lcd_puts(0, 5, "Verifying"); 506 *data = buffer;
439 rb->lcd_update(); 507 *data_len = fd_len;
440
441 p8 = (char *)get_section_address(section);
442 p8 += sizeof(struct flash_header);
443 sum = MODEL_NUMBER;
444 for (i = 0; i < len; i++)
445 sum += p8[i];
446
447 if (sum != checksum)
448 {
449 rb->splash(HZ*3, "Verify failed!");
450 /* Erase the magic sector so bootloader does not try to load
451 * rockbox from flash and crash. */
452 if (section == SECT_RAMIMAGE)
453 cfi_erase_sector(FB + FLASH_RAMIMAGE_ENTRY/2);
454 else
455 cfi_erase_sector(FB + FLASH_ROMIMAGE_ENTRY/2);
456 return -5;
457 }
458 508
459 rb->splash(HZ*2, "Success"); 509 /* mark success */
510 result = true;
460 511
461 return 0; 512bail: /* common exit code */
513 if (fd >= 0)
514 rb->close(fd);
515 if (msg != NULL)
516 rb->splash(HZ * 3, msg);
517 return result;
462} 518}
463 519
520/* prints fatal error if a critical failure occurs */
464static void show_fatal_error(void) 521static void show_fatal_error(void)
465{ 522{
466 rb->splash(HZ*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!"); 523 rb->splash(HZ * 30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!");
467 rb->splash(HZ*30, "Contact Rockbox developers as soon as possible!"); 524 rb->splash(HZ * 30, "Contact Rockbox developers as soon as possible!");
468 rb->splash(HZ*30, "Your device won't be bricked unless you turn off the power"); 525 rb->splash(HZ * 30, "Your device won't be bricked unless you turn off the power!");
469 rb->splash(HZ*30, "Don't use the device before further instructions from Rockbox developers"); 526 rb->splash(HZ * 30, "Don't use the device before further instructions from Rockbox developers!");
470} 527}
471 528
472int flash_bootloader(const char *filename) 529/* flash a bootloader */
530static bool flash_bootloader(const char* filename)
473{ 531{
474 char *bootsector; 532 bool result = false;
475 int pos, i, len/*, rc*/; 533 const char* msg = NULL;
476 unsigned long checksum, sum; 534 bool show_fatal = false;
477 unsigned char *p8; 535 const void* data;
478 uint16_t *p16; 536 size_t data_len;
537 static uint8_t boot_sector[SECTOR_SIZE];
479 538
480 bootsector = audiobuf; 539 /* load the firmware */
481 audiobuf += SEC_SIZE; 540 if (!load_firmware(filename, FIRMWARE_ROCKBOX, &data, &data_len))
482 audiobuf_size -= SEC_SIZE; 541 goto bail;
483 542
484 if (!confirm("Update bootloader?")) 543 /* the bootloader can only be so big */
485 return -2; 544 if (data_len > BOOTLOADER_MAX_SIZE)
486
487 len = load_firmware_file(filename, &checksum);
488 if (len <= 0)
489 return len * 10;
490
491 if (len > 0xFFFF)
492 { 545 {
493 rb->splash(HZ*3, "Too big bootloader"); 546 msg = "Aborting: bootloader too large";
494 return -1; 547 goto bail;
495 } 548 }
496 549
497 /* Verify the crc32 checksum also. */ 550 /* only support known bootloaders */
498 if (!detect_valid_bootloader(audiobuf, len)) 551 if (!detect_valid_bootloader(data, data_len))
499 { 552 {
500 rb->splash(HZ*3, "Incompatible/Untested bootloader"); 553 msg = "Aborting: bootloader is invalid";
501 return -1; 554 goto bail;
502 } 555 }
503 556
504 rb->lcd_puts(0, 3, "Flashing..."); 557 /* ask before doing anything dangerous */
505 rb->lcd_update(); 558 if (!confirm_choice("Update bootloader?"))
559 goto bail;
506 560
507 /* Backup the bootloader sector first. */ 561 /* copy the original boot sector */
508 p8 = (char *)FB; 562 rb->memcpy(boot_sector, flash(BOOT_SECTOR_OFFSET), SECTOR_SIZE);
509 rb->memcpy(bootsector, p8, SEC_SIZE);
510 563
511 /* Erase the boot sector and write a proper reset vector. */ 564 /* update the boot vector */
512 cfi_erase_sector(FB); 565 rb->memcpy(boot_sector, data, BOOT_VECTOR_SIZE);
513 p16 = (uint16_t *)audiobuf;
514 for (i = 0; i < 8/2; i++)
515 cfi_program_word(FB + i, p16[i]);
516 566
517 /* And restore original content for original FW to function. */ 567 /* erase the boot sector */
518 p16 = (uint16_t *)bootsector; 568 flash_erase_sector(BOOT_SECTOR_OFFSET);
519 for (i = 8/2; i < SEC_SIZE/2; i++)
520 cfi_program_word(FB + i, p16[i]);
521 569
522 /* Erase the bootloader flash section. */ 570 /* erase the bootloader sectors */
523 for (i = BOOTLOADER_ERASEGUARD; i < BOOTLOADER_ERASEGUARD+16; i++) 571 flash_erase_sectors(BOOTLOADER_ENTRYPOINT, BOOTLOADER_SECTORS, false);
524 /*rc =*/ cfi_erase_sector(FB + (SEC_SIZE/2) * i);
525 572
526 pos = BOOTLOADER_ENTRYPOINT/2; 573 /* program the new boot sector */
527 p16 = (uint16_t *)audiobuf; 574 flash_program_bytes(BOOT_SECTOR_OFFSET, boot_sector, SECTOR_SIZE, false);
528 for (i = 0; i < len/2; i++)
529 cfi_program_word(FB + pos + i, p16[i]);
530 575
531 /* Verify */ 576 /* program the new bootloader */
532 p8 = (char *)BOOTLOADER_ENTRYPOINT; 577 flash_program_bytes(BOOTLOADER_ENTRYPOINT, data, data_len, false);
533 sum = MODEL_NUMBER;
534 for (i = 0; i < len; i++)
535 sum += p8[i];
536 578
537 if (sum != checksum) 579 /* verify the new boot sector */
580 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET, boot_sector, SECTOR_SIZE, false))
538 { 581 {
539 rb->splash(HZ*3, "Verify failed!"); 582 msg = "Boot sector corrupt!";
540 show_fatal_error(); 583 show_fatal = true;
541 return -5; 584 goto bail;
542 } 585 }
543 586
544 p8 = (char *)FB; 587 /* verify the new bootloader */
545 for (i = 0; i < 8; i++) 588 if (!flash_verify_bytes(BOOTLOADER_ENTRYPOINT, data, data_len, false))
546 { 589 {
547 if (p8[i] != audiobuf[i]) 590 msg = "Verify failed!";
548 { 591 show_fatal = true;
549 rb->splash(HZ*3, "Bootvector corrupt!"); 592 goto bail;
550 show_fatal_error();
551 return -6;
552 }
553 } 593 }
554 594
555 rb->splash(HZ*2, "Success"); 595 /* report success */
596 rb->splash(HZ * 3, "Success!");
556 597
557 return 0; 598 /* mark success */
599 result = true;
600
601bail: /* common exit code */
602 if (msg != NULL)
603 rb->splash(HZ * 3, msg);
604 if (show_fatal)
605 show_fatal_error();
606 return result;
558} 607}
559 608
560int flash_original_fw(int len) 609/* flash a rockbox ram / rom image */
610static bool flash_rockbox(const char* filename, uint32_t offset)
561{ 611{
562 unsigned char reset_vector[8]; 612 bool result = false;
563 int pos, i, rc; 613 const char* msg = NULL;
564 unsigned char *p8; 614 const void* data;
565 uint16_t *p16; 615 size_t data_len;
616 struct flash_header header;
566 617
567 rb->lcd_puts(0, 3, "Critical section..."); 618 /* load the firmware */
568 rb->lcd_update(); 619 if (!load_firmware(filename, FIRMWARE_ROCKBOX, &data, &data_len))
569 620 goto bail;
570 p8 = (char *)FB;
571 rb->memcpy(reset_vector, p8, sizeof reset_vector);
572 621
573 /* Erase the boot sector and write back the reset vector. */ 622 /* sanity check that the offset was set correctly */
574 cfi_erase_sector(FB); 623 if (offset != FLASH_RAMIMAGE_ENTRY && offset != FLASH_ROMIMAGE_ENTRY)
575 p16 = (uint16_t *)reset_vector;
576 for (i = 0; i < (long)sizeof(reset_vector)/2; i++)
577 cfi_program_word(FB + i, p16[i]);
578
579 rb->lcd_puts(0, 4, "Flashing orig. FW");
580 rb->lcd_update();
581
582 /* Erase the program flash. */
583 for (i = 1; i < BOOTLOADER_ERASEGUARD && (i-1)*4096 < len; i++)
584 { 624 {
585 rc = cfi_erase_sector(FB + (SEC_SIZE/2) * i); 625 msg = "Aborting: invalid image offset";
586 rb->lcd_putsf(0, 5, "Erase: 0x%03x (%d)", i, rc); 626 goto bail;
587 rb->lcd_update();
588 } 627 }
589 628
590 rb->lcd_puts(0, 6, "Programming"); 629 /* ensure there's enough room for the ram / rom image */
591 rb->lcd_update(); 630 if (
592 631 (offset == FLASH_RAMIMAGE_ENTRY && data_len > RAM_IMAGE_MAX_SIZE) ||
593 pos = 0x00000008/2; 632 (offset == FLASH_ROMIMAGE_ENTRY && data_len > ROM_IMAGE_MAX_SIZE)
594 p16 = (uint16_t *)audiobuf; 633 )
595 for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) 634 {
596 cfi_program_word(FB + pos + i, p16[i]); 635 msg = "Aborting: ram / rom image too large";
636 goto bail;
637 }
597 638
598 rb->lcd_puts(0, 7, "Verifying"); 639 /* check for bootloader that can load rockbox from ram / rom */
599 rb->lcd_update(); 640 if (!detect_valid_bootloader(flash(BOOTLOADER_ENTRYPOINT), 0))
641 {
642 msg = "Aborting: incompatible bootloader";
643 goto bail;
644 }
600 645
601 /* Verify reset vectors. */ 646 /* rom image specific checks */
602 p8 = (char *)FB; 647 if (offset == FLASH_ROMIMAGE_ENTRY)
603 for (i = 0; i < 8; i++)
604 { 648 {
605 if (p8[i] != reset_vector[i]) 649 uint32_t relocation = *((const uint32_t*) data);
650
651 /* sanity check of the image relocation */
652 if (relocation != ROM_IMAGE_RELOCATION)
606 { 653 {
607 rb->splash(HZ*3, "Bootvector corrupt!"); 654 msg = "Aborting: invalid image relocation";
608 show_fatal_error(); 655 goto bail;
609 break;
610 } 656 }
611 } 657 }
612 658
613 /* Verify */ 659 /* ask before doing anything dangerous */
614 p8 = (char *)0x00000008; 660 if (!rb->detect_original_firmware())
615 for (i = 0; i < len; i++)
616 { 661 {
617 if (p8[i] != audiobuf[i]) 662 if (!confirm_choice("Update Rockbox flash image?"))
618 { 663 goto bail;
619 rb->splash(HZ*3, "Verify failed!"); 664 }
620 rb->splashf(HZ*10, "at: 0x%08x", i); 665 else
621 return -5; 666 {
622 } 667 if (!confirm_choice("Erase original firmware?"))
668 goto bail;
623 } 669 }
624 670
625 rb->splash(HZ*2, "Success"); 671 /* erase all ram / rom image sectors */
672 if (offset == FLASH_RAMIMAGE_ENTRY)
673 flash_erase_sectors(offset, RAM_IMAGE_SECTORS, true);
674 else if (offset == FLASH_ROMIMAGE_ENTRY)
675 flash_erase_sectors(offset, ROM_IMAGE_SECTORS, true);
676
677 /* prepare the header */
678 header.magic = FLASH_MAGIC;
679 header.length = data_len;
680 rb->memset(&header.version, 0x00, sizeof(header.version));
681
682 /* program the header */
683 flash_program_bytes(offset, &header, sizeof(header), false);
684
685 /* program the ram / rom image */
686 flash_program_bytes(offset + sizeof(header), data, data_len, true);
687
688 /* verify the header and ram / rom image */
689 if (
690 !flash_verify_bytes(offset, &header, sizeof(header), false) ||
691 !flash_verify_bytes(offset + sizeof(header), data, data_len, true)
692 )
693 {
694 msg = "Verify failed!";
695 /*
696 * erase the ram / rom image header to prevent the bootloader
697 * from trying to boot from it
698 */
699 flash_erase_sector(offset);
700 goto bail;
701 }
626 702
627 return 0; 703 /* report success */
704 rb->splash(HZ * 3, "Success!");
705
706 /* mark success */
707 result = true;
708
709bail: /* common exit code */
710 if (msg != NULL)
711 rb->splash(HZ * 3, msg);
712 return result;
628} 713}
629 714
630int load_original_bin(const char *filename) 715/* flash whole firmware; common code for romdump / original */
716static bool flash_whole_firmware(const void* data, size_t data_len)
631{ 717{
632 unsigned long magic[2]; 718 bool result = false;
633 int len, rc; 719 const char* msg = NULL;
634 int fd; 720 bool show_fatal = false;
721 uint8_t boot_vector[BOOT_VECTOR_SIZE];
635 722
636 if (!confirm("Restore original firmware (bootloader will be kept)?")) 723 /* copy the original boot vector */
637 return -2; 724 rb->memcpy(boot_vector, flash(BOOT_SECTOR_OFFSET), BOOT_VECTOR_SIZE);
638 725
639 fd = rb->open(filename, O_RDONLY); 726 /* erase everything except the bootloader */
640 if (fd < 0) 727 flash_erase_sectors(BOOT_SECTOR_OFFSET, WHOLE_FIRMWARE_SECTORS, true);
641 return -1; 728
729 /* program the original boot vector */
730 flash_program_bytes(BOOT_SECTOR_OFFSET, boot_vector, BOOT_VECTOR_SIZE, false);
731
732 /* program the whole firmware */
733 flash_program_bytes(BOOT_SECTOR_OFFSET + BOOT_VECTOR_SIZE, data, data_len, true);
642 734
643 len = rb->filesize(fd) - 0x228; 735 /* verify the new boot vector */
644 rb->lseek(fd, 0x220, SEEK_SET); 736 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET, boot_vector, BOOT_VECTOR_SIZE, false))
645 rb->read(fd, magic, 8);
646 if (magic[1] != 0x00000008 || len <= 0 || len > audiobuf_size)
647 { 737 {
648 rb->splash(HZ*2, "Not an original firmware file"); 738 msg = "Boot vector corrupt!";
649 rb->close(fd); 739 show_fatal = true;
650 return -1; 740 goto bail;
651 } 741 }
652 742
653 rc = rb->read(fd, audiobuf, len); 743 /* verify the new firmware */
654 rb->close(fd); 744 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET + BOOT_VECTOR_SIZE, data, data_len, true))
655
656 if (rc != len)
657 { 745 {
658 rb->splash(HZ*2, "Read error"); 746 msg = "Verify failed!";
659 return -2; 747 goto bail;
660 } 748 }
661 749
662 if (len % 2) 750 /* report success */
663 len++; 751 rb->splash(HZ * 3, "Success!");
752
753 /* mark success */
754 result = true;
664 755
665 return flash_original_fw(len); 756bail: /* common exit code */
757 if (msg != NULL)
758 rb->splash(HZ * 3, msg);
759 if (show_fatal)
760 show_fatal_error();
761 return result;
666} 762}
667 763
668int load_romdump(const char *filename) 764/* flash rom dumps */
765static bool flash_romdump(const char* filename)
669{ 766{
670 int len, rc; 767 const void* data;
671 int fd; 768 size_t data_len;
672 769
673 if (!confirm("Restore firmware section (bootloader will be kept)?")) 770 /* load the firmware */
674 return -2; 771 if (!load_firmware(filename, FIRMWARE_ROMDUMP, &data, &data_len))
772 return false;
675 773
676 fd = rb->open(filename, O_RDONLY); 774 /* ask before doing anything dangerous */
677 if (fd < 0) 775 if (!confirm_choice("Restore firmware section (bootloader will be kept)?"))
678 return -1; 776 return false;
679
680 len = rb->filesize(fd) - 8;
681 if (len <= 0)
682 return -1;
683 777
684 rb->lseek(fd, 8, SEEK_SET); 778 return flash_whole_firmware(data, data_len);
685 rc = rb->read(fd, audiobuf, len); 779}
686 rb->close(fd);
687 780
688 if (rc != len) 781/* flash original firmware */
689 { 782static bool flash_original(const char* filename)
690 rb->splash(HZ*2, "Read error"); 783{
691 return -2; 784 const void* data;
692 } 785 size_t data_len;
693 786
694 if (len % 2) 787 /* load the firmware */
695 len++; 788 if (!load_firmware(filename, FIRMWARE_ORIGINAL, &data, &data_len))
789 return false;
696 790
697 if (len > BOOTLOADER_ENTRYPOINT - 8) 791 /* ask before doing anything dangerous */
698 len = BOOTLOADER_ENTRYPOINT - 8; 792 if (!confirm_choice("Restore original firmware (bootloader will be kept)?"))
793 return false;
699 794
700 return flash_original_fw(len); 795 return flash_whole_firmware(data, data_len);
701} 796}
702 797
703/* Kind of our main function, defines the application flow. */ 798/* main function of plugin */
704static void DoUserDialog(const char* filename) 799static void iriver_flash(const char* filename)
705{ 800{
706 /* check whether we're running from ROM */ 801 /* refuse to run from ROM */
707 uint16_t* RB = (uint16_t*) rb; 802 const uint8_t* RB = (uint8_t*) rb;
708 if (RB >= FB && RB < FB + (FLASH_SIZE / sizeof(*FB))) 803 const uint8_t* FB = (uint8_t*) flash(0);
804 if (RB >= FB && RB < FB + FLASH_SIZE)
709 { 805 {
710 rb->splash(HZ*3, "Not from ROM"); 806 rb->splash(HZ * 3, "Refusing to run from ROM");
711 return; /* exit */ 807 return;
712 } 808 }
713 809
714 /* refuse to work if the power may fail meanwhile */ 810 /* refuse to run with low battery */
715 if (!rb->battery_level_safe()) 811 if (!rb->battery_level_safe())
716 { 812 {
717 rb->splash(HZ*3, "Battery too low!"); 813 rb->splash(HZ * 3, "Refusing to run with low battery");
718 return; /* exit */ 814 return;
719 } 815 }
720 816
817 /* print information about flash; exit if not supported */
721 if (!show_info()) 818 if (!show_info())
722 return; /* exit */ 819 return;
723 820
821 /* exit if no filename was provided */
724 if (filename == NULL) 822 if (filename == NULL)
725 { 823 {
726 rb->splash(HZ*3, "Please use this plugin with \"Open with...\""); 824 rb->splash(HZ * 3, "Please use this plugin with \"Open with...\"");
727 return; /* exit */ 825 return;
728 } 826 }
729 827
730 audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuf_size); 828 /* choose what to do with the file */
731 829 if (rb->strcasestr(filename, "/bootloader.iriver") != NULL)
732 if (rb->strcasestr(filename, "/rockbox.iriver"))
733 flash_rockbox(filename, SECT_RAMIMAGE);
734 else if (rb->strcasestr(filename, "/rombox.iriver"))
735 flash_rockbox(filename, SECT_ROMIMAGE);
736 else if (rb->strcasestr(filename, "/bootloader.iriver"))
737 flash_bootloader(filename); 830 flash_bootloader(filename);
738 else if (rb->strcasestr(filename, "/ihp_120.bin")) 831 else if (rb->strcasestr(filename, "/rockbox.iriver") != NULL)
739 load_original_bin(filename); 832 flash_rockbox(filename, FLASH_RAMIMAGE_ENTRY);
740 else if (rb->strcasestr(filename, "/internal_rom_000000-1FFFFF.bin")) 833 else if (rb->strcasestr(filename, "/rombox.iriver") != NULL)
741 load_romdump(filename); 834 flash_rockbox(filename, FLASH_ROMIMAGE_ENTRY);
835 else if (rb->strcasestr(filename, ROMDUMP) != NULL)
836 flash_romdump(filename);
837 else if (rb->strcasestr(filename, ORIGINAL) != NULL)
838 flash_original(filename);
742 else 839 else
743 rb->splash(HZ*3, "Unknown file type"); 840 rb->splash(HZ * 3, "Unknown file type");
744} 841}
745 842
746 843/* plugin entry point */
747/***************** Plugin Entry Point *****************/
748
749enum plugin_status plugin_start(const void* parameter) 844enum plugin_status plugin_start(const void* parameter)
750{ 845{
751 int oldmode; 846 /* need to disable memguard to write to flash */
847 int mode = rb->system_memory_guard(MEMGUARD_NONE);
752 848
753 /* now go ahead and have fun! */ 849 /* setup LCD font */
754 oldmode = rb->system_memory_guard(MEMGUARD_NONE); /*disable memory guard */
755 rb->lcd_setfont(FONT_SYSFIXED); 850 rb->lcd_setfont(FONT_SYSFIXED);
756 DoUserDialog(parameter); 851
852 /* run the main entry function */
853 iriver_flash(parameter);
854
855 /* restore LCD font */
757 rb->lcd_setfont(FONT_UI); 856 rb->lcd_setfont(FONT_UI);
758 rb->system_memory_guard(oldmode); /* re-enable memory guard */ 857
858 /* restore original memory guard setting */
859 rb->system_memory_guard(mode);
759 860
760 return PLUGIN_OK; 861 return PLUGIN_OK;
761} 862}
diff --git a/firmware/export/config/iriverh100.h b/firmware/export/config/iriverh100.h
index bbfab01ba5..b7f1ca4b30 100644
--- a/firmware/export/config/iriverh100.h
+++ b/firmware/export/config/iriverh100.h
@@ -172,6 +172,7 @@
172#define BOOTFILE "rockbox." BOOTFILE_EXT 172#define BOOTFILE "rockbox." BOOTFILE_EXT
173#define BOOTDIR "/.rockbox" 173#define BOOTDIR "/.rockbox"
174 174
175#define FLASH_BASE 0x00000000
175#define BOOTLOADER_ENTRYPOINT 0x001F0000 176#define BOOTLOADER_ENTRYPOINT 0x001F0000
176#define FLASH_RAMIMAGE_ENTRY 0x00001000 177#define FLASH_RAMIMAGE_ENTRY 0x00001000
177#define FLASH_ROMIMAGE_ENTRY 0x00100000 178#define FLASH_ROMIMAGE_ENTRY 0x00100000
diff --git a/firmware/export/config/iriverh120.h b/firmware/export/config/iriverh120.h
index 77ee1382be..4b658bcf49 100644
--- a/firmware/export/config/iriverh120.h
+++ b/firmware/export/config/iriverh120.h
@@ -178,6 +178,7 @@
178#define BOOTFILE "rockbox." BOOTFILE_EXT 178#define BOOTFILE "rockbox." BOOTFILE_EXT
179#define BOOTDIR "/.rockbox" 179#define BOOTDIR "/.rockbox"
180 180
181#define FLASH_BASE 0x00000000
181#define BOOTLOADER_ENTRYPOINT 0x001F0000 182#define BOOTLOADER_ENTRYPOINT 0x001F0000
182#define FLASH_RAMIMAGE_ENTRY 0x00001000 183#define FLASH_RAMIMAGE_ENTRY 0x00001000
183#define FLASH_ROMIMAGE_ENTRY 0x00100000 184#define FLASH_ROMIMAGE_ENTRY 0x00100000
diff --git a/firmware/export/config/iriverh300.h b/firmware/export/config/iriverh300.h
index f901f160c6..e5805dd8f4 100644
--- a/firmware/export/config/iriverh300.h
+++ b/firmware/export/config/iriverh300.h
@@ -187,6 +187,7 @@
187#define BOOTFILE "rockbox." BOOTFILE_EXT 187#define BOOTFILE "rockbox." BOOTFILE_EXT
188#define BOOTDIR "/.rockbox" 188#define BOOTDIR "/.rockbox"
189 189
190#define FLASH_BASE 0x00000000
190#define BOOTLOADER_ENTRYPOINT 0x003F0000 191#define BOOTLOADER_ENTRYPOINT 0x003F0000
191#define FLASH_RAMIMAGE_ENTRY 0x00001000 192#define FLASH_RAMIMAGE_ENTRY 0x00001000
192#define FLASH_ROMIMAGE_ENTRY 0x00200000 193#define FLASH_ROMIMAGE_ENTRY 0x00200000
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 1885acfffd..68d7958870 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -36,8 +36,8 @@ extern void system_init(void);
36extern long cpu_frequency; 36extern long cpu_frequency;
37 37
38struct flash_header { 38struct flash_header {
39 unsigned long magic; 39 uint32_t magic;
40 unsigned long length; 40 uint32_t length;
41 char version[32]; 41 char version[32];
42}; 42};
43 43