diff --git a/cmd_parser.c b/cmd_parser.c index 0b8f97a..35fd791 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -803,47 +803,27 @@ void cmd_parser(void) __banked } } else if (cmd_compare(0, "stat")) { port_stats_print(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { - print_string("\nPRINT SECURITY REGISTERS\n"); + } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') { + print_string("\nSECURITY REGISTERS\n"); // The following will only show something else than 0xff if it was programmed for a managed switch + print_string("Region 1: "); flash_region.addr = 0x0001000; flash_region.len = 40; flash_read_security(); + print_string("\nRegion 2: "); flash_region.addr = 0x0002000; flash_region.len = 40; flash_read_security(); + print_string("\nRegion 3: "); flash_region.addr = 0x0003000; flash_region.len = 40; flash_read_security(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { - print_string("\nDUMPING FLASH\n"); - flash_region.addr = 0; - flash_region.len = 255; - flash_dump(255); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { print_string("\nJEDEC ID\n"); flash_read_jedecid(); } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') { - print_string("\nUNIQUE ID\n"); + print_string("\nUNIQUE ID (note: only 4 bytes are likely correct here!)\n"); flash_read_uid(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') { - print_string("\nFLASH FAST MODE\n"); // Switch to flash 62.5 MHz mode - flash_init(1); - print_string("\nNow dumping flash\n"); - flash_region.addr = 0; - flash_region.len = 255; - flash_dump(255); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { - print_string("\nFLASH erase\n"); - flash_region.addr = 0x20000; - flash_sector_erase(); - } else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') { - print_string("\nFLASH write\n"); - for (uint8_t i = 0; i < 20; i++) - flash_buf[i] = greeting[i]; - flash_region.addr = 0x200000; - flash_region.len = 20; - flash_write_bytes(flash_buf); } else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { parse_port(); } else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) { diff --git a/httpd/httpd.c b/httpd/httpd.c index 7b9cd47..2812524 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -27,6 +27,7 @@ extern __code uint8_t * __code hex; extern __code struct f_data f_data[]; extern __code char * __code mime_strings[]; extern __xdata struct flash_region_t flash_region; +extern __xdata uint32_t flash_size; // Flash buffer to optimize flash writing speed, write_len is the current filling position extern __xdata uint8_t flash_buf[FLASH_BUF_SIZE]; @@ -426,6 +427,12 @@ void handle_post(void) p += 4; // Skip \r\n\r\n sequence at end of preamble of part if (is_word(request_path, "upload")) { + if (flash_size < FIRMWARE_UPLOAD_START*2) + { + print_string("Flash too small for firmware upload!\n"); + send_bad_request(); + return; + } print_string("Firmware upload started."); uptr = FIRMWARE_UPLOAD_START; verify_crc = 1; diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 00f7cb5..76c6eb3 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -9,7 +9,7 @@ __xdata uint8_t dio_enabled; __xdata struct flash_region_t flash_region; - +__xdata uint32_t flash_size; // For the flash commands, see e.g. Windbond W25Q32JV datasheet #define CMD_WRITE_STATUS 0x01 @@ -17,8 +17,9 @@ __xdata struct flash_region_t flash_region; // Don't use command `READ 0x03`, because on many device this command can't run at maximum SPI-clock speed. // Use `Fast READ 0x0b` instead! //#define CMD_READ 0x03 +#define CMD_READ_STATUS 0x05 #define CMD_WRITE_ENABLE 0x06 -#define CMD_FREAD 0x0b +#define CMD_FREAD 0x0b #define CMD_SECTOR_ERASE 0x20 #define CMD_READ_SECURITY_REGS 0x48 #define CMD_READ_UNIQUE_ID 0x4b @@ -87,7 +88,7 @@ uint8_t flash_read_status(void) // setup status read command SFR_FLASH_TCONF = 0x11; - SFR_FLASH_CMD_R = 5; + SFR_FLASH_CMD_R = CMD_READ_STATUS; // execute and wait for controller done SFR_FLASH_EXEC_GO = 1; @@ -119,9 +120,10 @@ void flash_read_uid(void) print_byte(SFR_FLASH_DATA8); print_byte(SFR_FLASH_DATA16); print_byte(SFR_FLASH_DATA24); + write_char(' '); + SFR_FLASH_DUMMYCYCLES = 24; // Doesn't seem to work; we get the same data as for the first transfer SFR_FLASH_EXEC_GO = 1; - SFR_FLASH_DUMMYCYCLES = 24; while(SFR_FLASH_EXEC_BUSY); print_byte(SFR_FLASH_DATA0); @@ -148,15 +150,17 @@ void flash_read_jedecid(void) SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); + print_string("Maufacturer ID: 0x"); print_byte(SFR_FLASH_DATA0); + print_string("\nMemory Type: 0x"); print_byte(SFR_FLASH_DATA8); - print_byte(SFR_FLASH_DATA16); - print_byte(SFR_FLASH_DATA24); - - // Reset slow read mode - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = CMD_FREAD; - SFR_FLASH_DUMMYCYCLES = 8; + print_string("\nCapacity: 0x"); + uint8_t cap = SFR_FLASH_DATA16; + flash_size = 1UL << cap; + print_byte(cap); + print_string(" = "); + print_long(flash_size); + print_string(" Bytes\n"); flash_configure_mmio(); } @@ -188,51 +192,6 @@ void flash_write_enable(void) } while (!(status & 0x2)); } - -void flash_dump(uint8_t len) -{ - short status; - do { - status = flash_read_status(); - print_short(status); - } while (status & 0x1); - - // Set fast read mode - if (dio_enabled) { - SFR_FLASH_MODEB = 0x18; - SFR_FLASH_CMD_R = CMD_FREAD_DIO; - SFR_FLASH_DUMMYCYCLES = 4; - } else { - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = CMD_FREAD; // Fast read - SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? - } - // Read 4 bytes - SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = flash_region.addr >> 16; - SFR_FLASH_ADDR8 = flash_region.addr >> 8; - SFR_FLASH_ADDR0 = flash_region.addr; - flash_region.addr += 4; - - SFR_FLASH_EXEC_GO = 1; - while(SFR_FLASH_EXEC_BUSY); - - print_short(SFR_FLASH_DATA0); - if (len == 1) - return; - print_short(SFR_FLASH_DATA8); - if (len == 2) - return; - print_short(SFR_FLASH_DATA16); - if (len == 3) - return; - print_short(SFR_FLASH_DATA24); - - len -= 4; - } -} - /* * Reads bulk data of length len from the flash memory starging at address src * and writes the data into a buffer pointed to by dst in XMEM @@ -315,7 +274,7 @@ void flash_read_security(void) if (flash_region.len == 3) break; print_byte(SFR_FLASH_DATA24); - + write_char(' '); flash_region.len -= 4; } while(flash_region.len); diff --git a/rtlplayground.c b/rtlplayground.c index fc0eeed..9d9e755 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -24,9 +24,9 @@ #include "phy.h" extern __code const struct machine machine; +extern __xdata uint32_t flash_size; extern __xdata uint16_t crc_value; -__xdata uint8_t crc_testbytes[10]; __xdata struct machine_runtime machine_detected; void crc16(__xdata uint8_t *v) __naked; @@ -548,16 +548,6 @@ uint8_t read_flash(uint8_t bank, __code uint8_t *addr) return v; } - -void print_long_x(__xdata uint8_t v[]) -{ - write_char('0'); write_char('x'); - for (uint8_t i=0; i < 4; i++) { - write_char(hex[v[i] >> 4]); - write_char(hex[v[i] & 0xf]); - } -} - /* * Read a SerDes register in the SoC * Input must be: sds_id = 0/1, page < 128, reg <= 0xff @@ -1869,6 +1859,19 @@ void setup_i2c(void) void check_and_flash_update_image(void) { + flash_read_jedecid(); // This initializes also __xdata flash_size variable + + print_long(flash_size); print_string(" flash size detected.\n"); + print_long(FIRMWARE_UPLOAD_START*2); print_string(" bytes needed for update.\n"); + if (flash_size < FIRMWARE_UPLOAD_START*2) { + print_string("Flash too small for updating; skipping update check\n"); + return; + } + else { + print_string("Flash size ok.\n"); + } + + // Check if an update image is in flash flash_region.addr = FIRMWARE_UPLOAD_START; flash_region.len = 0x100; @@ -1881,7 +1884,7 @@ void check_and_flash_update_image(void) __xdata uint16_t i = 0; __xdata uint16_t j = 0; __xdata uint8_t * __xdata bptr; - print_string("Identified update image. Checking integrity..."); + print_string("Identified update image. Checking integrity"); flash_init(0); // Re-initialize flash for non-DIO operation, otherwise flashing will fail set_sys_led_state(SYS_LED_FAST); crc_value = 0x0000; @@ -1894,25 +1897,20 @@ void check_and_flash_update_image(void) crc16(bptr++); } source += FLASH_BUF_SIZE; - if (i%16 == 0) - write_char('.'); + if (i%16 == 0) write_char('.'); } if (crc_value == 0xb001) { - print_string("\nChecksum OK\n"); - print_string("Update in progress, moving firmware to start of FLASH."); + print_string("Checksum OK.\nUpdate in progress, moving firmware to start of flash"); source = FIRMWARE_UPLOAD_START; - // A 512kByte = 4MBit Flash has 128*8=1024 512byte blocks, we copy only 896 - // (don't overwrite config @ 0x70000) - for (i = 0; i < 896; i++) { - // print_string("Writing block: "); - // print_short(dest); + // Don't copy the config area at the end of flash + for (i = 0; i < CONFIG_START/FLASH_BUF_SIZE; i++) { flash_region.addr = source; flash_region.len = FLASH_BUF_SIZE; flash_read_bulk(flash_buf); - if (!(i & 0x7)) { + if (i%8 == 0) { flash_region.addr = dest; flash_sector_erase(); - write_char('.'); + if (i%16 == 0) write_char('.'); } flash_region.addr = dest; flash_region.len = FLASH_BUF_SIZE; @@ -1920,15 +1918,16 @@ void check_and_flash_update_image(void) dest += FLASH_BUF_SIZE; source += FLASH_BUF_SIZE; } - print_string("\nDeleting uploaded flash image\n"); + print_string("Done.\nDeleting uploaded flash image"); dest = FIRMWARE_UPLOAD_START; for (register uint8_t i=0; i < 128; i++) // TODO: Erasing the entire 512kByte upload area is probably not necessary { flash_region.addr = dest; flash_sector_erase(); dest += 0x1000; + if (i%4 == 0) write_char('.'); } - print_string("Resetting now"); + print_string("Done.\nResetting now"); delay(200); reset_chip(); }