summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Buren <braewoods+rb@braewoods.net>2020-11-11 10:54:05 +0000
committerJames Buren <braewoods+rb@braewoods.net>2020-11-11 13:30:09 +0000
commit4aa749b59db9fb46a47a0bcff4f19a6f0552b2aa (patch)
tree39784c771741613847e83dce95b122f27cf485e6
parentc4254d10fc61779656dd5692c2f6333692ba73f8 (diff)
downloadrockbox-4aa749b59db9fb46a47a0bcff4f19a6f0552b2aa.tar.gz
rockbox-4aa749b59db9fb46a47a0bcff4f19a6f0552b2aa.zip
iriver_flash: refactor code to be easier to understand
This overhauls most of the code to be easier to understand in terms of the interactions with the flash. I found the original to be rather confusing with how it kept switching between byte and word offsets. My solution was to make all external access to the flash in terms of sectors and bytes. Whatever the flash uses internally is now handled by the subroutines for performing the erase, program, and verify operations. This helps make it far more consistent for the code that actually uses these operations as they do not need to concern themselves with word sizes and offsets anymore. As a side effect of this change the flash operations are now done entirely by subroutines; even the batch operations that used to use custom loops. Additionally some functions were merged with other functions in order to reduce the amount of functions as well as consolidating common code fragments. Change-Id: I4698e920a226a3bbe8070004a14e5848abdd70ec
-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