|
@@ -1014,7 +1014,6 @@ static void sink_bytes(void)
|
|
|
|
|
|
static struct {
|
|
|
uint32_t len;
|
|
|
- uint32_t cur;
|
|
|
} update;
|
|
|
|
|
|
static void erase_old_bootloader(void)
|
|
@@ -1026,11 +1025,7 @@ static void erase_old_bootloader(void)
|
|
|
|
|
|
static void update_prep(uint32_t len)
|
|
|
{
|
|
|
- fpec_init();
|
|
|
- erase_old_bootloader();
|
|
|
-
|
|
|
floppy_state = ST_update_bootloader;
|
|
|
- update.cur = 0;
|
|
|
update.len = len;
|
|
|
|
|
|
printk("Update Bootloader: %u bytes\n", len);
|
|
@@ -1038,28 +1033,40 @@ static void update_prep(uint32_t len)
|
|
|
|
|
|
static void update_continue(void)
|
|
|
{
|
|
|
- int len;
|
|
|
+ uint16_t crc;
|
|
|
+ int len, retry;
|
|
|
|
|
|
+ /* Read entire new bootloader into the u_buf[] ring. */
|
|
|
if ((len = ep_rx_ready(EP_RX)) >= 0) {
|
|
|
usb_read(EP_RX, &u_buf[u_prod], len);
|
|
|
u_prod += len;
|
|
|
}
|
|
|
|
|
|
- if ((len = u_prod) >= 2) {
|
|
|
- int nr = len & ~1;
|
|
|
- fpec_write(u_buf, nr, BL_START + update.cur);
|
|
|
- update.cur += nr;
|
|
|
- u_prod -= nr;
|
|
|
- memcpy(u_buf, &u_buf[nr], u_prod);
|
|
|
- }
|
|
|
+ /* Keep going until we have the entire bootloader. */
|
|
|
+ if ((u_prod < update.len) || !ep_tx_ready(EP_TX))
|
|
|
+ return;
|
|
|
|
|
|
- if ((update.cur >= update.len) && ep_tx_ready(EP_TX)) {
|
|
|
- uint16_t crc = crc16_ccitt((void *)BL_START, update.len, 0xffff);
|
|
|
- printk("Final CRC: %04x (%s)\n", crc, crc ? "FAIL" : "OK");
|
|
|
- u_buf[0] = !!crc;
|
|
|
- floppy_state = ST_command_wait;
|
|
|
- floppy_end_command(u_buf, 1);
|
|
|
+ /* Validate the new bootloader before erasing the existing one! */
|
|
|
+ crc = crc16_ccitt(u_buf, update.len, 0xffff);
|
|
|
+ if (crc != 0)
|
|
|
+ goto done;
|
|
|
+
|
|
|
+ /* We are now committed to overwriting the existing bootloader.
|
|
|
+ * Try really hard to write the new bootloader (including retries). */
|
|
|
+ fpec_init();
|
|
|
+ for (retry = 0; retry < 3; retry++) {
|
|
|
+ erase_old_bootloader();
|
|
|
+ fpec_write(u_buf, update.len, BL_START);
|
|
|
+ crc = crc16_ccitt((void *)BL_START, update.len, 0xffff);
|
|
|
+ if (crc == 0)
|
|
|
+ goto done;
|
|
|
}
|
|
|
+
|
|
|
+done:
|
|
|
+ printk("Final CRC: %04x (%s)\n", crc, crc ? "FAIL" : "OK");
|
|
|
+ u_buf[0] = !!crc;
|
|
|
+ floppy_state = ST_command_wait;
|
|
|
+ floppy_end_command(u_buf, 1);
|
|
|
}
|
|
|
|
|
|
|