diff options
-rw-r--r-- | apps/plugins/iriver_flash.c | 192 |
1 files changed, 96 insertions, 96 deletions
diff --git a/apps/plugins/iriver_flash.c b/apps/plugins/iriver_flash.c index ce31429aa8..f5d209268f 100644 --- a/apps/plugins/iriver_flash.c +++ b/apps/plugins/iriver_flash.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
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) 2006 by Miika Pekkarinen |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
@@ -71,26 +71,26 @@ bool cfi_read_id(volatile uint16_t* pBase, uint8_t* pManufacturerID, uint8_t* pD | |||
71 | { | 71 | { |
72 | uint8_t not_manu, not_id; /* read values before switching to ID mode */ | 72 | uint8_t not_manu, not_id; /* read values before switching to ID mode */ |
73 | uint8_t manu, id; /* read values when in ID mode */ | 73 | uint8_t manu, id; /* read values when in ID mode */ |
74 | 74 | ||
75 | pBase = (uint16_t*)((uint32_t)pBase & 0xFFF80000); /* down to 512k align */ | 75 | pBase = (uint16_t*)((uint32_t)pBase & 0xFFF80000); /* down to 512k align */ |
76 | 76 | ||
77 | /* read the normal content */ | 77 | /* read the normal content */ |
78 | not_manu = pBase[0]; /* should be 'A' (0x41) and 'R' (0x52) */ | 78 | not_manu = pBase[0]; /* should be 'A' (0x41) and 'R' (0x52) */ |
79 | not_id = pBase[1]; /* from the "ARCH" marker */ | 79 | not_id = pBase[1]; /* from the "ARCH" marker */ |
80 | 80 | ||
81 | pBase[0x5555] = 0xAA; /* enter command mode */ | 81 | pBase[0x5555] = 0xAA; /* enter command mode */ |
82 | pBase[0x2AAA] = 0x55; | 82 | pBase[0x2AAA] = 0x55; |
83 | pBase[0x5555] = 0x90; /* ID command */ | 83 | pBase[0x5555] = 0x90; /* ID command */ |
84 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ | 84 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ |
85 | 85 | ||
86 | manu = pBase[0]; | 86 | manu = pBase[0]; |
87 | id = pBase[1]; | 87 | id = pBase[1]; |
88 | 88 | ||
89 | pBase[0] = 0xF0; /* reset flash (back to normal read mode) */ | 89 | pBase[0] = 0xF0; /* reset flash (back to normal read mode) */ |
90 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ | 90 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ |
91 | 91 | ||
92 | /* I assume success if the obtained values are different from | 92 | /* I assume success if the obtained values are different from |
93 | the normal flash content. This is not perfectly bulletproof, they | 93 | the normal flash content. This is not perfectly bulletproof, they |
94 | could theoretically be the same by chance, causing us to fail. */ | 94 | could theoretically be the same by chance, causing us to fail. */ |
95 | if (not_manu != manu || not_id != id) /* a value has changed */ | 95 | if (not_manu != manu || not_id != id) /* a value has changed */ |
96 | { | 96 | { |
@@ -106,7 +106,7 @@ bool cfi_read_id(volatile uint16_t* pBase, uint8_t* pManufacturerID, uint8_t* pD | |||
106 | bool cfi_erase_sector(volatile uint16_t* pAddr) | 106 | bool cfi_erase_sector(volatile uint16_t* pAddr) |
107 | { | 107 | { |
108 | unsigned timeout = 430000; /* the timeout loop should be no less than 25ms */ | 108 | unsigned timeout = 430000; /* the timeout loop should be no less than 25ms */ |
109 | 109 | ||
110 | FB[0x5555] = 0xAA; /* enter command mode */ | 110 | FB[0x5555] = 0xAA; /* enter command mode */ |
111 | FB[0x2AAA] = 0x55; | 111 | FB[0x2AAA] = 0x55; |
112 | FB[0x5555] = 0x80; /* erase command */ | 112 | FB[0x5555] = 0x80; /* erase command */ |
@@ -126,20 +126,20 @@ bool cfi_erase_sector(volatile uint16_t* pAddr) | |||
126 | static inline bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) | 126 | static inline bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) |
127 | { | 127 | { |
128 | unsigned timeout = 85; /* the timeout loop should be no less than 20us */ | 128 | unsigned timeout = 85; /* the timeout loop should be no less than 20us */ |
129 | 129 | ||
130 | if (~*pAddr & data) /* just a safety feature, not really necessary */ | 130 | if (~*pAddr & data) /* just a safety feature, not really necessary */ |
131 | return false; /* can't set any bit from 0 to 1 */ | 131 | return false; /* can't set any bit from 0 to 1 */ |
132 | 132 | ||
133 | FB[0x5555] = 0xAA; /* enter command mode */ | 133 | FB[0x5555] = 0xAA; /* enter command mode */ |
134 | FB[0x2AAA] = 0x55; | 134 | FB[0x2AAA] = 0x55; |
135 | FB[0x5555] = 0xA0; /* byte program command */ | 135 | FB[0x5555] = 0xA0; /* byte program command */ |
136 | 136 | ||
137 | *pAddr = data; | 137 | *pAddr = data; |
138 | 138 | ||
139 | /* I counted 7 instructions for this loop -> min. 0.58 us per round */ | 139 | /* I counted 7 instructions for this loop -> min. 0.58 us per round */ |
140 | /* Plus memory waitstates it will be much more, gives margin */ | 140 | /* Plus memory waitstates it will be much more, gives margin */ |
141 | while (*pAddr != data && --timeout); /* poll for programmed */ | 141 | while (*pAddr != data && --timeout); /* poll for programmed */ |
142 | 142 | ||
143 | return (timeout != 0); | 143 | return (timeout != 0); |
144 | } | 144 | } |
145 | 145 | ||
@@ -148,10 +148,10 @@ static inline bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) | |||
148 | bool cfi_get_flash_info(struct flash_info* pInfo) | 148 | bool cfi_get_flash_info(struct flash_info* pInfo) |
149 | { | 149 | { |
150 | rb->memset(pInfo, 0, sizeof(struct flash_info)); | 150 | rb->memset(pInfo, 0, sizeof(struct flash_info)); |
151 | 151 | ||
152 | if (!cfi_read_id(FB, &pInfo->manufacturer, &pInfo->id)) | 152 | if (!cfi_read_id(FB, &pInfo->manufacturer, &pInfo->id)) |
153 | return false; | 153 | return false; |
154 | 154 | ||
155 | if (pInfo->manufacturer == 0xBF) /* SST */ | 155 | if (pInfo->manufacturer == 0xBF) /* SST */ |
156 | { | 156 | { |
157 | if (pInfo->id == 0xD6) | 157 | if (pInfo->id == 0xD6) |
@@ -188,12 +188,12 @@ bool cfi_get_flash_info(struct flash_info* pInfo) | |||
188 | int wait_for_button(void) | 188 | int wait_for_button(void) |
189 | { | 189 | { |
190 | int button; | 190 | int button; |
191 | 191 | ||
192 | do | 192 | do |
193 | { | 193 | { |
194 | button = rb->button_get(true); | 194 | button = rb->button_get(true); |
195 | } while (IS_SYSEVENT(button) || (button & BUTTON_REL)); | 195 | } while (IS_SYSEVENT(button) || (button & BUTTON_REL)); |
196 | 196 | ||
197 | return button; | 197 | return button; |
198 | } | 198 | } |
199 | 199 | ||
@@ -209,8 +209,8 @@ void ShowFlashInfo(struct flash_info* pInfo) | |||
209 | { | 209 | { |
210 | rb->lcd_putsf(0, 0, "Flash: M=%02x D=%02x", | 210 | rb->lcd_putsf(0, 0, "Flash: M=%02x D=%02x", |
211 | pInfo->manufacturer, pInfo->id); | 211 | pInfo->manufacturer, pInfo->id); |
212 | 212 | ||
213 | 213 | ||
214 | if (pInfo->size) | 214 | if (pInfo->size) |
215 | { | 215 | { |
216 | rb->lcd_puts(0, 1, pInfo->name); | 216 | rb->lcd_puts(0, 1, pInfo->name); |
@@ -220,16 +220,16 @@ void ShowFlashInfo(struct flash_info* pInfo) | |||
220 | { | 220 | { |
221 | rb->lcd_puts(0, 1, "Unsupported chip"); | 221 | rb->lcd_puts(0, 1, "Unsupported chip"); |
222 | } | 222 | } |
223 | 223 | ||
224 | } | 224 | } |
225 | 225 | ||
226 | rb->lcd_update(); | 226 | rb->lcd_update(); |
227 | } | 227 | } |
228 | 228 | ||
229 | bool show_info(void) | 229 | bool show_info(void) |
230 | { | 230 | { |
231 | struct flash_info fi; | 231 | struct flash_info fi; |
232 | 232 | ||
233 | rb->lcd_clear_display(); | 233 | rb->lcd_clear_display(); |
234 | cfi_get_flash_info(&fi); | 234 | cfi_get_flash_info(&fi); |
235 | ShowFlashInfo(&fi); | 235 | ShowFlashInfo(&fi); |
@@ -238,19 +238,19 @@ bool show_info(void) | |||
238 | rb->splash(HZ*3, "Sorry!"); | 238 | rb->splash(HZ*3, "Sorry!"); |
239 | return false; /* exit */ | 239 | return false; /* exit */ |
240 | } | 240 | } |
241 | 241 | ||
242 | return true; | 242 | return true; |
243 | } | 243 | } |
244 | 244 | ||
245 | bool confirm(const char *msg) | 245 | bool confirm(const char *msg) |
246 | { | 246 | { |
247 | bool ret; | 247 | bool ret; |
248 | 248 | ||
249 | rb->splashf(0, "%s ([PLAY] to CONFIRM)", msg); | 249 | rb->splashf(0, "%s ([PLAY] to CONFIRM)", msg); |
250 | 250 | ||
251 | ret = (wait_for_button() == BUTTON_ON); | 251 | ret = (wait_for_button() == BUTTON_ON); |
252 | show_info(); | 252 | show_info(); |
253 | 253 | ||
254 | return ret; | 254 | return ret; |
255 | } | 255 | } |
256 | 256 | ||
@@ -260,24 +260,24 @@ int load_firmware_file(const char *filename, uint32_t *checksum) | |||
260 | int len, rc; | 260 | int len, rc; |
261 | int i; | 261 | int i; |
262 | uint32_t sum; | 262 | uint32_t sum; |
263 | 263 | ||
264 | fd = rb->open(filename, O_RDONLY); | 264 | fd = rb->open(filename, O_RDONLY); |
265 | if (fd < 0) | 265 | if (fd < 0) |
266 | return -1; | 266 | return -1; |
267 | 267 | ||
268 | len = rb->filesize(fd); | 268 | len = rb->filesize(fd); |
269 | 269 | ||
270 | if (audiobuf_size < len) | 270 | if (audiobuf_size < len) |
271 | { | 271 | { |
272 | rb->splash(HZ*3, "Aborting: Out of memory!"); | 272 | rb->splash(HZ*3, "Aborting: Out of memory!"); |
273 | rb->close(fd); | 273 | rb->close(fd); |
274 | return -2; | 274 | return -2; |
275 | } | 275 | } |
276 | 276 | ||
277 | rb->read(fd, checksum, 4); | 277 | rb->read(fd, checksum, 4); |
278 | rb->lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); | 278 | rb->lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); |
279 | len -= FIRMWARE_OFFSET_FILE_DATA; | 279 | len -= FIRMWARE_OFFSET_FILE_DATA; |
280 | 280 | ||
281 | rc = rb->read(fd, audiobuf, len); | 281 | rc = rb->read(fd, audiobuf, len); |
282 | rb->close(fd); | 282 | rb->close(fd); |
283 | if (rc != len) | 283 | if (rc != len) |
@@ -285,22 +285,22 @@ int load_firmware_file(const char *filename, uint32_t *checksum) | |||
285 | rb->splash(HZ*3, "Aborting: Read failure"); | 285 | rb->splash(HZ*3, "Aborting: Read failure"); |
286 | return -3; | 286 | return -3; |
287 | } | 287 | } |
288 | 288 | ||
289 | /* Verify the checksum */ | 289 | /* Verify the checksum */ |
290 | sum = MODEL_NUMBER; | 290 | sum = MODEL_NUMBER; |
291 | for (i = 0; i < len; i++) | 291 | for (i = 0; i < len; i++) |
292 | sum += audiobuf[i]; | 292 | sum += audiobuf[i]; |
293 | 293 | ||
294 | if (sum != *checksum) | 294 | if (sum != *checksum) |
295 | { | 295 | { |
296 | rb->splash(HZ*3, "Aborting: Checksums mismatch!"); | 296 | rb->splash(HZ*3, "Aborting: Checksums mismatch!"); |
297 | return -4; | 297 | return -4; |
298 | } | 298 | } |
299 | 299 | ||
300 | return len; | 300 | return len; |
301 | } | 301 | } |
302 | 302 | ||
303 | unsigned long valid_bootloaders[][2] = { | 303 | unsigned long valid_bootloaders[][2] = { |
304 | /* Size-8 CRC32 */ | 304 | /* Size-8 CRC32 */ |
305 | #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */ | 305 | #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */ |
306 | { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */ | 306 | { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */ |
@@ -351,10 +351,10 @@ int flash_rockbox(const char *filename, int section) | |||
351 | unsigned long checksum, sum; | 351 | unsigned long checksum, sum; |
352 | unsigned char *p8; | 352 | unsigned char *p8; |
353 | uint16_t *p16; | 353 | uint16_t *p16; |
354 | 354 | ||
355 | if (get_section_address(section) < 0) | 355 | if (get_section_address(section) < 0) |
356 | return -1; | 356 | return -1; |
357 | 357 | ||
358 | p8 = (char *)BOOTLOADER_ENTRYPOINT; | 358 | p8 = (char *)BOOTLOADER_ENTRYPOINT; |
359 | if (!detect_valid_bootloader(p8, 0)) | 359 | if (!detect_valid_bootloader(p8, 0)) |
360 | { | 360 | { |
@@ -376,9 +376,9 @@ int flash_rockbox(const char *filename, int section) | |||
376 | len = load_firmware_file(filename, &checksum); | 376 | len = load_firmware_file(filename, &checksum); |
377 | if (len <= 0) | 377 | if (len <= 0) |
378 | return len * 10; | 378 | return len * 10; |
379 | 379 | ||
380 | pos = get_section_address(section); | 380 | pos = get_section_address(section); |
381 | 381 | ||
382 | /* Check if image relocation seems to be sane. */ | 382 | /* Check if image relocation seems to be sane. */ |
383 | if (section == SECT_ROMIMAGE) | 383 | if (section == SECT_ROMIMAGE) |
384 | { | 384 | { |
@@ -390,39 +390,39 @@ int flash_rockbox(const char *filename, int section) | |||
390 | *p32, pos+sizeof(struct flash_header)); | 390 | *p32, pos+sizeof(struct flash_header)); |
391 | return -1; | 391 | return -1; |
392 | } | 392 | } |
393 | 393 | ||
394 | } | 394 | } |
395 | 395 | ||
396 | /* Erase the program flash. */ | 396 | /* Erase the program flash. */ |
397 | for (i = 0; i + pos < BOOTLOADER_ENTRYPOINT && i < len + 32; i += SEC_SIZE) | 397 | for (i = 0; i + pos < BOOTLOADER_ENTRYPOINT && i < len + 32; i += SEC_SIZE) |
398 | { | 398 | { |
399 | /* Additional safety check. */ | 399 | /* Additional safety check. */ |
400 | if (i + pos < SEC_SIZE) | 400 | if (i + pos < SEC_SIZE) |
401 | return -1; | 401 | return -1; |
402 | 402 | ||
403 | rb->lcd_putsf(0, 3, "Erasing... %d%%", (i+SEC_SIZE)*100/len); | 403 | rb->lcd_putsf(0, 3, "Erasing... %d%%", (i+SEC_SIZE)*100/len); |
404 | rb->lcd_update(); | 404 | rb->lcd_update(); |
405 | 405 | ||
406 | /*rc = */cfi_erase_sector(FB + (i + pos)/2); | 406 | /*rc = */cfi_erase_sector(FB + (i + pos)/2); |
407 | } | 407 | } |
408 | 408 | ||
409 | /* Write the magic and size. */ | 409 | /* Write the magic and size. */ |
410 | rb->memset(&hdr, 0, sizeof(struct flash_header)); | 410 | rb->memset(&hdr, 0, sizeof(struct flash_header)); |
411 | hdr.magic = FLASH_MAGIC; | 411 | hdr.magic = FLASH_MAGIC; |
412 | hdr.length = len; | 412 | hdr.length = len; |
413 | // rb->strncpy(hdr.version, rb->rbversion , sizeof(hdr.version)-1); | 413 | // rb->strncpy(hdr.version, rb->rbversion , sizeof(hdr.version)-1); |
414 | p16 = (uint16_t *)&hdr; | 414 | p16 = (uint16_t *)&hdr; |
415 | 415 | ||
416 | rb->lcd_puts(0, 4, "Programming..."); | 416 | rb->lcd_puts(0, 4, "Programming..."); |
417 | rb->lcd_update(); | 417 | rb->lcd_update(); |
418 | 418 | ||
419 | pos = get_section_address(section)/2; | 419 | pos = get_section_address(section)/2; |
420 | for (i = 0; i < (long)sizeof(struct flash_header)/2; i++) | 420 | for (i = 0; i < (long)sizeof(struct flash_header)/2; i++) |
421 | { | 421 | { |
422 | cfi_program_word(FB + pos, p16[i]); | 422 | cfi_program_word(FB + pos, p16[i]); |
423 | pos++; | 423 | pos++; |
424 | } | 424 | } |
425 | 425 | ||
426 | p16 = (uint16_t *)audiobuf; | 426 | p16 = (uint16_t *)audiobuf; |
427 | for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) | 427 | for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) |
428 | { | 428 | { |
@@ -431,20 +431,20 @@ int flash_rockbox(const char *filename, int section) | |||
431 | rb->lcd_putsf(0, 4, "Programming... %d%%", (i+1)*100/(len/2)); | 431 | rb->lcd_putsf(0, 4, "Programming... %d%%", (i+1)*100/(len/2)); |
432 | rb->lcd_update(); | 432 | rb->lcd_update(); |
433 | } | 433 | } |
434 | 434 | ||
435 | cfi_program_word(FB + pos + i, p16[i]); | 435 | cfi_program_word(FB + pos + i, p16[i]); |
436 | } | 436 | } |
437 | 437 | ||
438 | /* Verify */ | 438 | /* Verify */ |
439 | rb->lcd_puts(0, 5, "Verifying"); | 439 | rb->lcd_puts(0, 5, "Verifying"); |
440 | rb->lcd_update(); | 440 | rb->lcd_update(); |
441 | 441 | ||
442 | p8 = (char *)get_section_address(section); | 442 | p8 = (char *)get_section_address(section); |
443 | p8 += sizeof(struct flash_header); | 443 | p8 += sizeof(struct flash_header); |
444 | sum = MODEL_NUMBER; | 444 | sum = MODEL_NUMBER; |
445 | for (i = 0; i < len; i++) | 445 | for (i = 0; i < len; i++) |
446 | sum += p8[i]; | 446 | sum += p8[i]; |
447 | 447 | ||
448 | if (sum != checksum) | 448 | if (sum != checksum) |
449 | { | 449 | { |
450 | rb->splash(HZ*3, "Verify failed!"); | 450 | rb->splash(HZ*3, "Verify failed!"); |
@@ -456,9 +456,9 @@ int flash_rockbox(const char *filename, int section) | |||
456 | cfi_erase_sector(FB + FLASH_ROMIMAGE_ENTRY/2); | 456 | cfi_erase_sector(FB + FLASH_ROMIMAGE_ENTRY/2); |
457 | return -5; | 457 | return -5; |
458 | } | 458 | } |
459 | 459 | ||
460 | rb->splash(HZ*2, "Success"); | 460 | rb->splash(HZ*2, "Success"); |
461 | 461 | ||
462 | return 0; | 462 | return 0; |
463 | } | 463 | } |
464 | 464 | ||
@@ -481,20 +481,20 @@ int flash_bootloader(const char *filename) | |||
481 | bootsector = audiobuf; | 481 | bootsector = audiobuf; |
482 | audiobuf += SEC_SIZE; | 482 | audiobuf += SEC_SIZE; |
483 | audiobuf_size -= SEC_SIZE; | 483 | audiobuf_size -= SEC_SIZE; |
484 | 484 | ||
485 | if (!confirm("Update bootloader?")) | 485 | if (!confirm("Update bootloader?")) |
486 | return -2; | 486 | return -2; |
487 | 487 | ||
488 | len = load_firmware_file(filename, &checksum); | 488 | len = load_firmware_file(filename, &checksum); |
489 | if (len <= 0) | 489 | if (len <= 0) |
490 | return len * 10; | 490 | return len * 10; |
491 | 491 | ||
492 | if (len > 0xFFFF) | 492 | if (len > 0xFFFF) |
493 | { | 493 | { |
494 | rb->splash(HZ*3, "Too big bootloader"); | 494 | rb->splash(HZ*3, "Too big bootloader"); |
495 | return -1; | 495 | return -1; |
496 | } | 496 | } |
497 | 497 | ||
498 | /* Verify the crc32 checksum also. */ | 498 | /* Verify the crc32 checksum also. */ |
499 | if (!detect_valid_bootloader(audiobuf, len)) | 499 | if (!detect_valid_bootloader(audiobuf, len)) |
500 | { | 500 | { |
@@ -508,40 +508,40 @@ int flash_bootloader(const char *filename) | |||
508 | /* Backup the bootloader sector first. */ | 508 | /* Backup the bootloader sector first. */ |
509 | p8 = (char *)FB; | 509 | p8 = (char *)FB; |
510 | rb->memcpy(bootsector, p8, SEC_SIZE); | 510 | rb->memcpy(bootsector, p8, SEC_SIZE); |
511 | 511 | ||
512 | /* Erase the boot sector and write a proper reset vector. */ | 512 | /* Erase the boot sector and write a proper reset vector. */ |
513 | cfi_erase_sector(FB); | 513 | cfi_erase_sector(FB); |
514 | p16 = (uint16_t *)audiobuf; | 514 | p16 = (uint16_t *)audiobuf; |
515 | for (i = 0; i < 8/2; i++) | 515 | for (i = 0; i < 8/2; i++) |
516 | cfi_program_word(FB + i, p16[i]); | 516 | cfi_program_word(FB + i, p16[i]); |
517 | 517 | ||
518 | /* And restore original content for original FW to function. */ | 518 | /* And restore original content for original FW to function. */ |
519 | p16 = (uint16_t *)bootsector; | 519 | p16 = (uint16_t *)bootsector; |
520 | for (i = 8/2; i < SEC_SIZE/2; i++) | 520 | for (i = 8/2; i < SEC_SIZE/2; i++) |
521 | cfi_program_word(FB + i, p16[i]); | 521 | cfi_program_word(FB + i, p16[i]); |
522 | 522 | ||
523 | /* Erase the bootloader flash section. */ | 523 | /* Erase the bootloader flash section. */ |
524 | for (i = BOOTLOADER_ERASEGUARD; i < BOOTLOADER_ERASEGUARD+16; i++) | 524 | for (i = BOOTLOADER_ERASEGUARD; i < BOOTLOADER_ERASEGUARD+16; i++) |
525 | /*rc =*/ cfi_erase_sector(FB + (SEC_SIZE/2) * i); | 525 | /*rc =*/ cfi_erase_sector(FB + (SEC_SIZE/2) * i); |
526 | 526 | ||
527 | pos = BOOTLOADER_ENTRYPOINT/2; | 527 | pos = BOOTLOADER_ENTRYPOINT/2; |
528 | p16 = (uint16_t *)audiobuf; | 528 | p16 = (uint16_t *)audiobuf; |
529 | for (i = 0; i < len/2; i++) | 529 | for (i = 0; i < len/2; i++) |
530 | cfi_program_word(FB + pos + i, p16[i]); | 530 | cfi_program_word(FB + pos + i, p16[i]); |
531 | 531 | ||
532 | /* Verify */ | 532 | /* Verify */ |
533 | p8 = (char *)BOOTLOADER_ENTRYPOINT; | 533 | p8 = (char *)BOOTLOADER_ENTRYPOINT; |
534 | sum = MODEL_NUMBER; | 534 | sum = MODEL_NUMBER; |
535 | for (i = 0; i < len; i++) | 535 | for (i = 0; i < len; i++) |
536 | sum += p8[i]; | 536 | sum += p8[i]; |
537 | 537 | ||
538 | if (sum != checksum) | 538 | if (sum != checksum) |
539 | { | 539 | { |
540 | rb->splash(HZ*3, "Verify failed!"); | 540 | rb->splash(HZ*3, "Verify failed!"); |
541 | show_fatal_error(); | 541 | show_fatal_error(); |
542 | return -5; | 542 | return -5; |
543 | } | 543 | } |
544 | 544 | ||
545 | p8 = (char *)FB; | 545 | p8 = (char *)FB; |
546 | for (i = 0; i < 8; i++) | 546 | for (i = 0; i < 8; i++) |
547 | { | 547 | { |
@@ -552,9 +552,9 @@ int flash_bootloader(const char *filename) | |||
552 | return -6; | 552 | return -6; |
553 | } | 553 | } |
554 | } | 554 | } |
555 | 555 | ||
556 | rb->splash(HZ*2, "Success"); | 556 | rb->splash(HZ*2, "Success"); |
557 | 557 | ||
558 | return 0; | 558 | return 0; |
559 | } | 559 | } |
560 | 560 | ||
@@ -564,22 +564,22 @@ int flash_original_fw(int len) | |||
564 | int pos, i, rc; | 564 | int pos, i, rc; |
565 | unsigned char *p8; | 565 | unsigned char *p8; |
566 | uint16_t *p16; | 566 | uint16_t *p16; |
567 | 567 | ||
568 | rb->lcd_puts(0, 3, "Critical section..."); | 568 | rb->lcd_puts(0, 3, "Critical section..."); |
569 | rb->lcd_update(); | 569 | rb->lcd_update(); |
570 | 570 | ||
571 | p8 = (char *)FB; | 571 | p8 = (char *)FB; |
572 | rb->memcpy(reset_vector, p8, sizeof reset_vector); | 572 | rb->memcpy(reset_vector, p8, sizeof reset_vector); |
573 | 573 | ||
574 | /* Erase the boot sector and write back the reset vector. */ | 574 | /* Erase the boot sector and write back the reset vector. */ |
575 | cfi_erase_sector(FB); | 575 | cfi_erase_sector(FB); |
576 | p16 = (uint16_t *)reset_vector; | 576 | p16 = (uint16_t *)reset_vector; |
577 | for (i = 0; i < (long)sizeof(reset_vector)/2; i++) | 577 | for (i = 0; i < (long)sizeof(reset_vector)/2; i++) |
578 | cfi_program_word(FB + i, p16[i]); | 578 | cfi_program_word(FB + i, p16[i]); |
579 | 579 | ||
580 | rb->lcd_puts(0, 4, "Flashing orig. FW"); | 580 | rb->lcd_puts(0, 4, "Flashing orig. FW"); |
581 | rb->lcd_update(); | 581 | rb->lcd_update(); |
582 | 582 | ||
583 | /* Erase the program flash. */ | 583 | /* Erase the program flash. */ |
584 | for (i = 1; i < BOOTLOADER_ERASEGUARD && (i-1)*4096 < len; i++) | 584 | for (i = 1; i < BOOTLOADER_ERASEGUARD && (i-1)*4096 < len; i++) |
585 | { | 585 | { |
@@ -587,18 +587,18 @@ int flash_original_fw(int len) | |||
587 | rb->lcd_putsf(0, 5, "Erase: 0x%03x (%d)", i, rc); | 587 | rb->lcd_putsf(0, 5, "Erase: 0x%03x (%d)", i, rc); |
588 | rb->lcd_update(); | 588 | rb->lcd_update(); |
589 | } | 589 | } |
590 | 590 | ||
591 | rb->lcd_puts(0, 6, "Programming"); | 591 | rb->lcd_puts(0, 6, "Programming"); |
592 | rb->lcd_update(); | 592 | rb->lcd_update(); |
593 | 593 | ||
594 | pos = 0x00000008/2; | 594 | pos = 0x00000008/2; |
595 | p16 = (uint16_t *)audiobuf; | 595 | p16 = (uint16_t *)audiobuf; |
596 | for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) | 596 | for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) |
597 | cfi_program_word(FB + pos + i, p16[i]); | 597 | cfi_program_word(FB + pos + i, p16[i]); |
598 | 598 | ||
599 | rb->lcd_puts(0, 7, "Verifying"); | 599 | rb->lcd_puts(0, 7, "Verifying"); |
600 | rb->lcd_update(); | 600 | rb->lcd_update(); |
601 | 601 | ||
602 | /* Verify reset vectors. */ | 602 | /* Verify reset vectors. */ |
603 | p8 = (char *)FB; | 603 | p8 = (char *)FB; |
604 | for (i = 0; i < 8; i++) | 604 | for (i = 0; i < 8; i++) |
@@ -610,7 +610,7 @@ int flash_original_fw(int len) | |||
610 | break; | 610 | break; |
611 | } | 611 | } |
612 | } | 612 | } |
613 | 613 | ||
614 | /* Verify */ | 614 | /* Verify */ |
615 | p8 = (char *)0x00000008; | 615 | p8 = (char *)0x00000008; |
616 | for (i = 0; i < len; i++) | 616 | for (i = 0; i < len; i++) |
@@ -622,9 +622,9 @@ int flash_original_fw(int len) | |||
622 | return -5; | 622 | return -5; |
623 | } | 623 | } |
624 | } | 624 | } |
625 | 625 | ||
626 | rb->splash(HZ*2, "Success"); | 626 | rb->splash(HZ*2, "Success"); |
627 | 627 | ||
628 | return 0; | 628 | return 0; |
629 | } | 629 | } |
630 | 630 | ||
@@ -633,14 +633,14 @@ int load_original_bin(const char *filename) | |||
633 | unsigned long magic[2]; | 633 | unsigned long magic[2]; |
634 | int len, rc; | 634 | int len, rc; |
635 | int fd; | 635 | int fd; |
636 | 636 | ||
637 | if (!confirm("Restore original firmware (bootloader will be kept)?")) | 637 | if (!confirm("Restore original firmware (bootloader will be kept)?")) |
638 | return -2; | 638 | return -2; |
639 | 639 | ||
640 | fd = rb->open(filename, O_RDONLY); | 640 | fd = rb->open(filename, O_RDONLY); |
641 | if (fd < 0) | 641 | if (fd < 0) |
642 | return -1; | 642 | return -1; |
643 | 643 | ||
644 | len = rb->filesize(fd) - 0x228; | 644 | len = rb->filesize(fd) - 0x228; |
645 | rb->lseek(fd, 0x220, SEEK_SET); | 645 | rb->lseek(fd, 0x220, SEEK_SET); |
646 | rb->read(fd, magic, 8); | 646 | rb->read(fd, magic, 8); |
@@ -650,19 +650,19 @@ int load_original_bin(const char *filename) | |||
650 | rb->close(fd); | 650 | rb->close(fd); |
651 | return -1; | 651 | return -1; |
652 | } | 652 | } |
653 | 653 | ||
654 | rc = rb->read(fd, audiobuf, len); | 654 | rc = rb->read(fd, audiobuf, len); |
655 | rb->close(fd); | 655 | rb->close(fd); |
656 | 656 | ||
657 | if (rc != len) | 657 | if (rc != len) |
658 | { | 658 | { |
659 | rb->splash(HZ*2, "Read error"); | 659 | rb->splash(HZ*2, "Read error"); |
660 | return -2; | 660 | return -2; |
661 | } | 661 | } |
662 | 662 | ||
663 | if (len % 2) | 663 | if (len % 2) |
664 | len++; | 664 | len++; |
665 | 665 | ||
666 | return flash_original_fw(len); | 666 | return flash_original_fw(len); |
667 | } | 667 | } |
668 | 668 | ||
@@ -670,34 +670,34 @@ int load_romdump(const char *filename) | |||
670 | { | 670 | { |
671 | int len, rc; | 671 | int len, rc; |
672 | int fd; | 672 | int fd; |
673 | 673 | ||
674 | if (!confirm("Restore firmware section (bootloader will be kept)?")) | 674 | if (!confirm("Restore firmware section (bootloader will be kept)?")) |
675 | return -2; | 675 | return -2; |
676 | 676 | ||
677 | fd = rb->open(filename, O_RDONLY); | 677 | fd = rb->open(filename, O_RDONLY); |
678 | if (fd < 0) | 678 | if (fd < 0) |
679 | return -1; | 679 | return -1; |
680 | 680 | ||
681 | len = rb->filesize(fd) - 8; | 681 | len = rb->filesize(fd) - 8; |
682 | if (len <= 0) | 682 | if (len <= 0) |
683 | return -1; | 683 | return -1; |
684 | 684 | ||
685 | rb->lseek(fd, 8, SEEK_SET); | 685 | rb->lseek(fd, 8, SEEK_SET); |
686 | rc = rb->read(fd, audiobuf, len); | 686 | rc = rb->read(fd, audiobuf, len); |
687 | rb->close(fd); | 687 | rb->close(fd); |
688 | 688 | ||
689 | if (rc != len) | 689 | if (rc != len) |
690 | { | 690 | { |
691 | rb->splash(HZ*2, "Read error"); | 691 | rb->splash(HZ*2, "Read error"); |
692 | return -2; | 692 | return -2; |
693 | } | 693 | } |
694 | 694 | ||
695 | if (len % 2) | 695 | if (len % 2) |
696 | len++; | 696 | len++; |
697 | 697 | ||
698 | if (len > BOOTLOADER_ENTRYPOINT - 8) | 698 | if (len > BOOTLOADER_ENTRYPOINT - 8) |
699 | len = BOOTLOADER_ENTRYPOINT - 8; | 699 | len = BOOTLOADER_ENTRYPOINT - 8; |
700 | 700 | ||
701 | return flash_original_fw(len); | 701 | return flash_original_fw(len); |
702 | } | 702 | } |
703 | 703 | ||
@@ -717,7 +717,7 @@ void DoUserDialog(char* filename) | |||
717 | rb->splash(HZ*3, "Battery too low!"); | 717 | rb->splash(HZ*3, "Battery too low!"); |
718 | return; /* exit */ | 718 | return; /* exit */ |
719 | } | 719 | } |
720 | 720 | ||
721 | rb->lcd_setfont(FONT_SYSFIXED); | 721 | rb->lcd_setfont(FONT_SYSFIXED); |
722 | if (!show_info()) | 722 | if (!show_info()) |
723 | return ; | 723 | return ; |
@@ -727,9 +727,9 @@ void DoUserDialog(char* filename) | |||
727 | rb->splash(HZ*3, "Please use this plugin with \"Open with...\""); | 727 | rb->splash(HZ*3, "Please use this plugin with \"Open with...\""); |
728 | return ; | 728 | return ; |
729 | } | 729 | } |
730 | 730 | ||
731 | audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuf_size); | 731 | audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuf_size); |
732 | 732 | ||
733 | if (rb->strcasestr(filename, "/rockbox.iriver")) | 733 | if (rb->strcasestr(filename, "/rockbox.iriver")) |
734 | flash_rockbox(filename, SECT_RAMIMAGE); | 734 | flash_rockbox(filename, SECT_RAMIMAGE); |
735 | else if (rb->strcasestr(filename, "/rombox.iriver")) | 735 | else if (rb->strcasestr(filename, "/rombox.iriver")) |