diff --git a/cmd_parser.c b/cmd_parser.c index 68a01f4..4538c3d 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -32,7 +32,9 @@ extern volatile __xdata uint8_t sfr_data[4]; extern __code uint8_t * __code greeting; extern __code uint8_t * __code hex; -extern __xdata uint8_t flash_buf[256]; +extern __xdata uint8_t flash_buf[512]; +extern __xdata struct flash_region_t flash_region; + __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint16_t vlan_ptr; __xdata uint8_t gpio_last_value[8] = { 0 }; @@ -489,13 +491,21 @@ void cmd_parser(void) __banked if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { print_string("\nPRINT SECURITY REGISTERS\n"); // The following will only show something else than 0xff if it was programmed for a managed switch - flash_read_security(0x0001000, 40); - flash_read_security(0x0002000, 40); - flash_read_security(0x0003000, 40); + flash_region.addr = 0x0001000; + flash_region.len = 40; + flash_read_security(); + flash_region.addr = 0x0002000; + flash_region.len = 40; + flash_read_security(); + flash_region.addr = 0x0003000; + flash_region.len = 40; + flash_read_security(); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { print_string("\nDUMPING FLASH\n"); - flash_dump(0, 255); + flash_region.addr = 0; + flash_region.len = 255; + flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { print_string("\nJEDEC ID\n"); @@ -510,17 +520,22 @@ void cmd_parser(void) __banked print_string("\nFLASH FAST MODE\n"); flash_init(1); print_string("\nNow dumping flash\n"); - flash_dump(0, 255); + flash_region.addr = 0; + flash_region.len = 255; + flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { print_string("\nFLASH erase\n"); - flash_sector_erase(0x20000); + flash_region.addr = 0x20000; + flash_sector_erase(); } 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_write_bytes(0x20000, flash_buf, 20); + flash_region.addr = 0x200000; + flash_region.len = 20; + flash_write_bytes(flash_buf); } if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { print_string("\nPORT "); @@ -620,22 +635,44 @@ void cmd_parser(void) __banked } } +#define FLASH_READ_BURST_SIZE 0x100; void execute_config(void) __banked { - __xdata uint32_t pos = CONFIG_START; - __xdata uint16_t len_left = CONFIG_LEN; - do { - flash_find_mark(pos, len_left, "\n"); - if (mpos != 0xffff) { - __xdata uint16_t len = len_left - mpos; - flash_read_bulk(&cmd_buffer[0], pos, len > SBUF_SIZE ? SBUF_SIZE : len); - cmd_buffer[len > SBUF_SIZE ? SBUF_SIZE : len] = '\0'; - len++; - pos += len; - len_left -= len; - if (len && !cmd_tokenize()) - cmd_parser(); - } - } while (mpos != 0xffff); -} + memcpyc(flash_buf, "test", 5); + print_string_x(flash_buf); + __xdata uint32_t pos = CONFIG_START; + __xdata uint16_t len_left = CONFIG_LEN; + do { + flash_region.addr = pos; + flash_region.len = FLASH_READ_BURST_SIZE; + write_char('-'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('\n'); + + flash_read_bulk(flash_buf); + + uint8_t cfg_idx = 0; + uint8_t c = 0; + do { + for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) { + c = flash_buf[cfg_idx++]; + print_byte(c); + + if (c == 0 || c == '\n') { + cmd_buffer[cmd_idx] = '\0'; + write_char('\n'); write_char('#'); print_short(cfg_idx); write_char('-'); print_short(cmd_idx); write_char('-'); print_string_x(cmd_buffer); write_char('\n'); + if (cmd_idx && !cmd_tokenize()) + cmd_parser(); + if (c == 0) + return; + break; + } + + cmd_buffer[cmd_idx] = c; + } + write_char('N'); + } while(cfg_idx); + + len_left -= FLASH_READ_BURST_SIZE; + pos += FLASH_READ_BURST_SIZE; + } while(len_left); +} diff --git a/config.txt b/config.txt new file mode 100644 index 0000000..3200af0 --- /dev/null +++ b/config.txt @@ -0,0 +1,3 @@ +ip 192.168.10.247 +gw 192.168.10.1 +netmask 255.255.255.0 \ No newline at end of file diff --git a/html/index.html b/html/index.html index 485e607..f9f94c6 100644 --- a/html/index.html +++ b/html/index.html @@ -1,24 +1,35 @@ - - - - - FreeSwitchOS Main Page - - - -
+ + + + + + + FreeSwitchOS Main Page + + + + +

Switch Configuration

- - - #{html_index} +
Setting
+ + + + +
Settings
-
- +
+ + diff --git a/html/main_info.js b/html/main_info.js new file mode 100644 index 0000000..1d9d7ee --- /dev/null +++ b/html/main_info.js @@ -0,0 +1,22 @@ +document.addEventListener("DOMContentLoaded", function () { + fetch('/information.json') + .then(response => response.json()) + .then(data => { + const tableBody = document.getElementById('infoTable').querySelector('tbody'); + + // Create table rows + for (const [key, value] of Object.entries(data)) { + const row = document.createElement('tr'); + const cellKey = document.createElement('td'); + const cellValue = document.createElement('td'); + + cellKey.textContent = key; + cellValue.textContent = value; + + row.appendChild(cellKey); + row.appendChild(cellValue); + tableBody.appendChild(row); + } + }) + .catch(error => console.error('Error fetching the data:', error)); +}); diff --git a/html/update.html b/html/update.html new file mode 100644 index 0000000..ab99b67 --- /dev/null +++ b/html/update.html @@ -0,0 +1,20 @@ + + + + + Firmware update + + + +
+
+

Firmware Update

+
+ + Choose a firmware update file to upload:
+ +
+ + diff --git a/httpd/httpd.c b/httpd/httpd.c index 57602f8..b376399 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -7,13 +7,24 @@ #include "uip.h" #include "../html_data.h" +// Upload Firmware to 1M +#define FIRMWARE_UPLOAD_START 0x100000 + +// SPI FLASH MEMORY PAGE SIZE. +#define FLASHMEM_PAGE_SIZE 0x100 + #define CMARK_S 6 #pragma codeseg BANK1 extern __code struct f_data f_data[]; -extern __code fcall_ptr f_calls[]; extern __code char * __code mime_strings[]; +extern __xdata struct flash_region_t flash_region; + +// Flash buffer to optimize flash writing speed, write_len is the current filling position +extern __xdata uint8_t flash_buf[512]; +__xdata uint32_t uptr; // Current flash write position +__xdata uint16_t write_len; __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; __xdata uint8_t entry; @@ -22,11 +33,20 @@ __xdata uint16_t o_idx; __xdata uint16_t mpos; __xdata uint16_t len_left; +// HTTP header properties +__xdata uint8_t boundary[72]; +__xdata uint8_t *content_type = 0; + +// Global variables holding POST state +__xdata uint16_t bindex; // Current index into the boundary + +__xdata uint16_t short_parsed; #define TSTATE_NONE 0 #define TSTATE_TX 1 #define TSTATE_ACKED 2 #define TSTATE_CLOSED 3 +#define TSTATE_POST 4 inline uint8_t is_separator(uint8_t c) @@ -44,9 +64,9 @@ void httpd_init(void) __banked } -uint8_t find_entry(__xdata uint8_t * __xdata e) +uint8_t find_entry(__xdata uint8_t *e) { - register uint8_t i, j; + uint8_t i, j; for (i = 0; f_data[i].len; i++) { j = 0; @@ -61,13 +81,12 @@ uint8_t find_entry(__xdata uint8_t * __xdata e) } -char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) +char strcmp(__xdata uint8_t *c, __code uint8_t * __xdata d) { - register uint8_t i = 0; + uint8_t i = 0; - while (d[i] && (d[i] == c[i])) { + while (d[i] && (d[i] == c[i])) i++; - } if (c[i] < d[i]) return -1; @@ -77,15 +96,47 @@ char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) } -uint8_t parse_short(register uint16_t *n, __xdata uint8_t * __xdata p) +char is_word(__xdata uint8_t *c, __code uint8_t * __xdata d) +{ + uint8_t i = 0; + + while (d[i] && (d[i] == c[i])) + i++; + + if (d[i]) + return 0; + if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i]) + return 0; + return 1; +} + + +char is_word_x(__xdata uint8_t *c, __xdata uint8_t *d) +{ + register uint8_t i = 0; + + while (d[i] && (d[i] == c[i])) + i++; + + if (d[i]) + return 0; + if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i]) + return 0; + return 1; +} + + +uint8_t parse_short(__xdata uint8_t *p) { uint8_t err = 1; - *n = 0; + uint8_t c = 0; - while (*p >= '0' && *p <= '9') { + short_parsed = 0; + while(1) { + c = *p++ - '0'; + if (c > 9) { break; } err = 0; - *n = (*n * 10) + *p - '0'; - p++; + short_parsed = (short_parsed * 10) + c; } return err; } @@ -93,33 +144,190 @@ uint8_t parse_short(register uint16_t *n, __xdata uint8_t * __xdata p) void send_not_found(void) { - slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n"); - print_string("slen: "); print_short(slen); write_char('\n'); - slen += strtox(outbuf + slen, "\n404 Not Found\n

Not Found

\n"); + slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n" \ + "\n404 Not Found\n

Not Found

\n"); } -void handle_post(void) + +void send_bad_request(void) { - __xdata uint8_t *p = uip_appdata; + slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" \ + "\n400 Bad Request\n

Bad Request

\n"); +} + + +__xdata uint8_t *skip_boundary(__xdata uint8_t *p) +{ + while (*p) { + if (is_word_x(p, boundary)) + return p + strlen_x(boundary); + p++; + } + return p; +} + + +__xdata uint8_t *scan_header(__xdata uint8_t *p) +{ + content_type = 0; + while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') { write_char(*p); if (!*p++) break; + if (is_word(p, "\nContent-Type:")) + content_type = p + 15; } - if (!*p) { - print_string("No body found!\n"); + if (content_type && is_word(content_type, "multipart/form-data; boundary")) { + print_string("\nFound multiplart\n"); + content_type += 30; + uint8_t i = 0; + while (content_type[i] != '\r' && content_type[i] != '\n') { + boundary[i + 2] = content_type[i]; + i++; + } + // The boundary between parts is "--" + the boundary given in the header + boundary[0] = '-'; + boundary[1] = '-'; + boundary[i + 2] = 0; + } + return p; +} + + +/* + * Reads post data from the http stream and writes it into flash memory + * Input: the current position in the TCP buffer (uip_appdata) + * Returns 1: More data to read, 0: Upload complete, all parts reads + */ +uint8_t stream_upload(uint16_t bptr) +{ + __xdata uint8_t *p = uip_appdata; + __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); + + print_string("Stream_upload called: "); + print_short(bptr); write_char('\n'); + + do { + if (bptr >= uip_len) { + s->tstate = TSTATE_POST; + return 1; + } + // Have we reached the end of the part? + if (!boundary[bindex]) { + s->tstate = TSTATE_NONE; + print_string("len 2: "); print_short(write_len); write_char(' '); + flash_region.addr = uptr; + flash_region.len = write_len; + flash_write_bytes(flash_buf); + uptr += write_len; + write_len = 0; + // TODO: This is a bit premature, what about a nice web-page saying the device will reset??? + print_string("Upload to flash done, will reset!\n"); + reset_chip(); + if (bptr >= uip_len) + return 0; + return 1; + } + if (p[bptr] == boundary[bindex]) { + bptr++; + bindex++; + } else { + if (bindex) { + memcpy(flash_buf + write_len, boundary, bindex); + write_len += bindex; + bindex = 0; + } + flash_buf[write_len++] = p[bptr++]; + if (write_len >= FLASHMEM_PAGE_SIZE) { + print_string("len: "); print_short(write_len); write_char(' '); + flash_region.addr = uptr; + flash_region.len = FLASHMEM_PAGE_SIZE; + flash_write_bytes(flash_buf); + uptr += FLASHMEM_PAGE_SIZE; + write_len -= FLASHMEM_PAGE_SIZE; + + // Copy the remaining byte for the next page to the beginning of the buffer. + if (write_len > 0) { + memcpy(flash_buf, flash_buf + FLASHMEM_PAGE_SIZE, write_len); + } + } + bindex = 0; + } + } while(1); +} + + +void handle_post(void) +{ + __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); + __xdata uint8_t *p = uip_appdata; + __xdata uint8_t *request_path = p + 6; + + print_string("Is POST\n"); + p += 5; // Skip post + // Find end of request path + while (*p && !is_separator(*p)) + p++; + *p++ = '\0'; + + // Find end of request header + boundary[0] ='\0'; + p = scan_header(p); + print_string("Boundary: >"); print_string_x(boundary); print_string("<\n"); + if (!*p || !content_type) { + print_string("Bad Request!\n"); send_not_found(); return; } - register uint8_t i = 0; - p += 4; - while (*p && *p != '\n' && *p != '\r') - cmd_buffer[i++] = *p++; - cmd_buffer[i] = '\0'; - if (i && !cmd_tokenize()) + if (is_word(request_path, "cmd")) { + register uint8_t i = 0; + p += 4; + while (*p && *p != '\n' && *p != '\r') + cmd_buffer[i++] = *p++; + cmd_buffer[i] = '\0'; + + if (i && !cmd_tokenize()) cmd_parser(); + } else if (is_word(request_path, "upload")) { + print_string("POST upload request\n"); + if (!boundary[0]) { + print_string("Bad request, no boundary!\n"); + send_bad_request(); + return; + } + // We skip the intial parts as part of the header + do { + p = skip_boundary(p); + if (!*p) + goto bad_request; + p = scan_header(p); + if (!*p) + goto bad_request; + if (!content_type) // We are waiting for the part with the octet stream + continue; + } while (!is_word(content_type, "application/octet-stream")); + print_string("Have content octets\n"); + p += 4; // Skip \r\n\r\n sequence at end of preamble of part + + uptr = FIRMWARE_UPLOAD_START; + bindex = 0; + write_len = 0; + stream_upload(p - uip_appdata); + + print_string("Done reading first fragment\n"); + return; + + } else { + send_not_found(); + return; + } slen = strtox(outbuf, "HTTP/1.1 200 OK\r\n\r\n"); + return; +bad_request: + send_bad_request(); + return; } @@ -168,20 +376,28 @@ void httpd_appcall(void) print_string("Sending B done\n"); s->tstate = TSTATE_TX; } + } else if (uip_newdata() && s->tstate == TSTATE_POST) { + stream_upload(0); } else if (uip_newdata() && s->tstate != TSTATE_TX) { write_char('<'); print_short(uip_len); write_char('\n'); __xdata uint8_t *p = uip_appdata; + // Mark end of request header with \0 p[uip_len] = 0; while (*p) write_char(*p++); write_char('\n'); p = uip_appdata; - if (p[0] == 'P' && p[1] == 'O' && p[2] == 'S' && p[3] == 'T' && p[4] == ' ') { + if (is_word(p, "POST")) { handle_post(); + // If this is an ongoing post stream, then wait for the next packet + if (s->tstate == TSTATE_POST) { + uip_len = 0; + return; + } goto do_send; } - if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ') + if (is_word(p, "GET")) print_string("GET request "); p += 4; __xdata uint8_t *q = p; @@ -198,10 +414,11 @@ void httpd_appcall(void) print_string("Not file entry\n"); if (!strcmp(q, "/status.json")) { send_status(); + } else if (!strcmp(q, "/information.json")) { + send_basic_info(); } else if (!strcmp(q, "/vlan.json")) { - __xdata uint16_t vlan; - parse_short(&vlan, q + 15); - send_vlan(vlan); + parse_short(q + 15); + send_vlan(short_parsed); } else if (!strcmp(q, "/counters.json")) { send_counters(q[19]-'0'); } else { @@ -211,40 +428,14 @@ void httpd_appcall(void) print_string("Have entry\n"); slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: "); slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]); - slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000"); - slen += strtox(outbuf + slen, "\r\n\r\n"); + slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000\r\n\r\n"); len_left = f_data[entry].len; - if (f_data[entry].mime == mime_HTML) { - print_string("MIME is html len is "); print_short(len_left); write_char('\n'); - mpos = 0; - flash_find_mark(f_data[entry].start, len_left, "#{"); - print_string("mpos: "); print_short(mpos); write_char('\n'); - while (mpos != 0xffff) { - print_string("Entry-len:"); print_short(len_left); write_char('\n'); - mpos = len_left - mpos; - print_string("l/pos: "); print_short(mpos); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, mpos + CMARK_S); // call marker is e.g. #{001} - slen += mpos; - write_char('@'); write_char(outbuf[slen + 2]); write_char(outbuf[slen + 3]); write_char(outbuf[slen + 4]); - fcall_ptr ptr = f_calls[(outbuf[slen + 2] - '0') * 100 + (outbuf[slen + 3]-'0') * 10 + outbuf[slen + 4] - '0']; - slen -= CMARK_S; // Overwrite marker with generated html - print_string("Call location is: "); print_short((uint16_t)ptr); write_char('\n'); -// f_calls[outbuf[slen + 2] * 100 + outbuf[slen + 3] * 10 + outbuf[slen + 4]](); - ptr(); - print_string("call done\n"); - mpos += CMARK_S; - len_left -= mpos; - flash_find_mark(f_data[entry].start + mpos, len_left, "#{"); - print_string("mpos now: "); print_short(mpos); write_char('\n'); - } - print_string("At end mpos: "); print_short(mpos); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, len_left); - slen += len_left; - } else { - print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start, len_left); - slen += len_left; - } + + print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); + flash_region.addr = f_data[entry].start; + flash_region.len = len_left; + flash_read_bulk(outbuf + slen); + slen += len_left; } do_send: print_string("slen: "); print_short(slen); write_char('\n'); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 89ae166..dce8843 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -27,6 +27,7 @@ extern __xdata uint8_t isRTL8373; extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; +__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"; /* Convert only the lower nibble to ascii HEX char. For convenience the upper nibble is masked out. @@ -133,40 +134,40 @@ void reg_to_html(register uint16_t reg) sfr_data_to_html(); } - -uint16_t html_index(void) +void send_basic_info(void) { - print_string("html_index called\n"); - slen += strtox(outbuf + slen, "IP Address"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); + print_string("send_basic_info called\n"); + slen += strtox(outbuf + slen, "{\"ip_address\":\""); itoa_html(uip_hostaddr[0]); char_to_html('.'); itoa_html(uip_hostaddr[0] >> 8); char_to_html('.'); itoa_html(uip_hostaddr[1]); char_to_html('.'); itoa_html(uip_hostaddr[1] >> 8); - slen += strtox(outbuf + slen, "Gateway"); + slen += strtox(outbuf + slen, "\",\"ip_gateway\":\""); itoa_html(uip_draddr[0]); char_to_html('.'); itoa_html(uip_draddr[0] >> 8); char_to_html('.'); itoa_html(uip_draddr[1]); char_to_html('.'); itoa_html(uip_draddr[1] >> 8); - slen += strtox(outbuf + slen, "Netmask"); + slen += strtox(outbuf + slen, "\",\"ip_netmask\":\""); itoa_html(uip_netmask[0]); char_to_html('.'); itoa_html(uip_netmask[0] >> 8); char_to_html('.'); itoa_html(uip_netmask[1]); char_to_html('.'); itoa_html(uip_netmask[1] >> 8); - slen += strtox(outbuf + slen, "MAC Address"); + slen += strtox(outbuf + slen, "\",\"mac_address\":\""); byte_to_html(uip_ethaddr.addr[0]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[1]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[2]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[3]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[4]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[5]); - slen += strtox(outbuf + slen, ""); - return 0; + slen += strtox(outbuf + slen, "\",\"sw_ver\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}"); + // slen += strtox(outbuf + slen, "\"}"); } -void send_vlan(__xdata uint16_t vlan) +void send_vlan(uint16_t vlan) { - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending VLAN\n"); //{"members":"0x00060011"} slen += strtox(outbuf + slen, "{\"members\":\"0x"); @@ -187,7 +188,7 @@ void send_vlan(__xdata uint16_t vlan) void send_counters(char port) { print_string("send_counters called: "); print_byte(port); write_char('\n'); - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending counters\n"); port--; @@ -209,7 +210,7 @@ void send_counters(char port) void send_status(void) { - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending status\n"); char_to_html('['); diff --git a/httpd/page_impl.h b/httpd/page_impl.h index c643140..16f776e 100644 --- a/httpd/page_impl.h +++ b/httpd/page_impl.h @@ -4,5 +4,6 @@ void send_counters(char port); void send_status(void); void send_vlan(register uint16_t vlan); +void send_basic_info(void); #endif diff --git a/installer/installer.c b/installer/installer.c index c66f06f..3eeb61d 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -256,8 +256,7 @@ void flash_write_enable(void) SFR_FLASH_TCONF = 0x18; SFR_FLASH_CMD = 6; -// The following is explicitly set for SIO, is this necessary?: - SFR_FLASH_DUMMYCYCLES = 0; + SFR_FLASH_DUMMYCICLES = 0; SFR_FLASH_MODEB = 0; SFR_FLASH_EXEC_GO = 1; diff --git a/rtl837x_common.h b/rtl837x_common.h index 35d1e49..c04fbb3 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -50,6 +50,11 @@ struct uip_eth_addr { uint8_t addr[6]; }; +struct flash_region_t { + uint32_t addr; + uint16_t len; +}; + extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 471116f..4df0604 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -10,10 +10,13 @@ __xdata uint8_t dio_enabled; __xdata uint8_t markbuf[16]; extern __xdata uint16_t mpos; +__xdata struct flash_region_t flash_region; + // For the flash commands, see e.g. Windbond W25Q32JV datasheet #define CMD_WRITE_STATUS 0x01 #define CMD_PAGE_PROGRAM 0x02 +#define CMD_READ 0x03 #define CMD_WRITE_ENABLE 0x06 #define CMD_FREAD 0x0b #define CMD_SECTOR_ERASE 0x20 @@ -36,7 +39,7 @@ void flash_configure_mmio(void) } SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = 0xb; // Default is Single IO + SFR_FLASH_CMD_R = CMD_FREAD; // Default is Single IO SFR_FLASH_DUMMYCYCLES = 8; } @@ -184,7 +187,7 @@ void flash_write_enable(void) } -void flash_dump(register uint32_t addr, register uint8_t len) +void flash_dump(uint8_t len) { short status; do { @@ -205,10 +208,10 @@ void flash_dump(register uint32_t addr, register uint8_t len) // Read 4 bytes SFR_FLASH_TCONF = 4; while (len) { - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; - addr += 4; + 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); @@ -232,7 +235,7 @@ void flash_dump(register uint32_t addr, register uint8_t len) * 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 */ -void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) +void flash_read_bulk(__xdata uint8_t *dst) { short status; do { @@ -246,119 +249,41 @@ void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, regist 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? + SFR_FLASH_CMD_R = CMD_READ; + SFR_FLASH_DUMMYCYCLES = 0; } + + // Read 4 bytes - SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = src >> 16; - SFR_FLASH_ADDR8 = src >> 8; - SFR_FLASH_ADDR0 = src; - src += 4; + while (1) { + 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_TCONF = 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); *dst++ = SFR_FLASH_DATA0; - if (len == 1) - return; + if (flash_region.len == 1) + break; *dst++ = SFR_FLASH_DATA8; - if (len == 2) - return; + if (flash_region.len == 2) + break; *dst++ = SFR_FLASH_DATA16; - if (len == 3) - return; + if (flash_region.len == 3) + break; *dst++ = SFR_FLASH_DATA24; - - len -= 4; + if (flash_region.len == 4) + break; + flash_region.len -= 4; } } -void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark) -{ - uint16_t status; - do { - status = flash_read_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? - } - - uint8_t i = 0; - uint8_t l = 0; - uint8_t k; - - // Calculate the length - while (mark[i++]) - l++; - - if (l >= 12) { - mpos = 0xffff; - return; - } - - i = 0; - SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = src >> 16; - SFR_FLASH_ADDR8 = src >> 8; - SFR_FLASH_ADDR0 = src; - src += 4; - - SFR_FLASH_EXEC_GO = 1; - while(SFR_FLASH_EXEC_BUSY); - markbuf[i++] = SFR_FLASH_DATA0; - if (len != 1) { - markbuf[i++] = SFR_FLASH_DATA8; - if (len != 2) { - markbuf[i++] = SFR_FLASH_DATA16; - if (len != 3) { - markbuf[i++] = SFR_FLASH_DATA24; - } else { - markbuf[i++] = 0; - } - } else { - markbuf[i++] = 0; - } - } else { - markbuf[i++] = 0; - } - - len -= len >= 4? 4 : len; - uint8_t j = 0; - k = (i + 13 - l) & 0xf; - i &= 0xf; - while (mark[j] && (k != ((i) & 0xf))) { - if (mark[j] != markbuf[k]) { - k = k - j + 17; - j = 0; - } else { - k++; - j++; - } - k &= 0xf; - } - if (!mark[j]) { - mpos = len + l + ((4 - ( k & 0x3)) & 0x3); - return; - } - } - mpos = 0xffff; - return; -} - - -void flash_read_security(uint32_t addr, uint8_t len) +void flash_read_security() { while (flash_read_status() & 0x1); @@ -369,66 +294,63 @@ void flash_read_security(uint32_t addr, uint8_t len) // Transfer 4 bytes (command + 3byte address) SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; - addr += 4; + do { + 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_byte(SFR_FLASH_DATA0); - if (len == 1) - return; + if (flash_region.len == 1) + break; print_byte(SFR_FLASH_DATA8); - if (len == 2) - return; + if (flash_region.len == 2) + break; print_byte(SFR_FLASH_DATA16); - if (len == 3) - return; + if (flash_region.len == 3) + break; print_byte(SFR_FLASH_DATA24); - len -= 4; - } + flash_region.len -= 4; + } while(flash_region.len); } -void flash_sector_erase(uint32_t addr) +void flash_sector_erase(void) { flash_write_enable(); SFR_FLASH_TCONF = 8; SFR_FLASH_CMD = CMD_SECTOR_ERASE; - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; SFR_FLASH_EXEC_GO = 1; while (flash_read_status() & 0x1); flash_configure_mmio(); - } -void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len) +void flash_write_bytes(__xdata uint8_t *ptr) { - uint8_t exit_loop = 0; - - while(1) { + write_char('>'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('-'); print_byte(*ptr); write_char('\n'); + while(1) { flash_write_enable(); SFR_FLASH_CMD = CMD_PAGE_PROGRAM; - SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is is 4, 8 enables write, 0x40 is unkown + SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown // Last transfer? - if (len < 5) { - SFR_FLASH_TCONF = 8 | len; - exit_loop = 1; + if (flash_region.len < 5) { + SFR_FLASH_TCONF = 8 | flash_region.len; } - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; SFR_FLASH_DATA0 = *ptr++; SFR_FLASH_DATA8 = *ptr++; SFR_FLASH_DATA16 = *ptr++; @@ -436,11 +358,13 @@ void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len // Execute transfer, we wait for completion at top of loop SFR_FLASH_EXEC_GO = 1; - if (exit_loop) + + if (flash_region.len < 5) break; - len -= 4; - addr += 4; - } + + flash_region.len -= 4; + flash_region.addr += 4; + }; while (flash_read_status() & 0x1); flash_configure_mmio(); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index f891f97..cad66b0 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -4,11 +4,10 @@ void flash_init(uint8_t enable_dio); void flash_read_uid(void); void flash_write_enable(void); -void flash_dump(register uint32_t addr, register uint8_t len); +void flash_dump(uint8_t len); void flash_read_jedecid(void); -void flash_read_security(uint32_t addr, uint8_t len); -void flash_sector_erase(uint32_t addr); -void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len); -void flash_write_bytes(__xdata uint32_t addr, register __xdata uint8_t *ptr, register uint16_t len); -void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark); +void flash_read_security(void); +void flash_sector_erase(void); +void flash_read_bulk(__xdata uint8_t *dst); +void flash_write_bytes(__xdata uint8_t *ptr); #endif diff --git a/rtlplayground.c b/rtlplayground.c index a657297..5ce107c 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -16,6 +16,9 @@ #include "uip/uip.h" #include "uip/uip_arp.h" +// Upload Firmware to 1M +#define FIRMWARE_UPLOAD_START 0x100000 + #define SYS_TICK_HZ 100 #define SERIAL_BAUD_RATE 115200 @@ -67,10 +70,12 @@ __xdata uint8_t sfr_data[4]; extern __xdata uint8_t cmd_buffer[SBUF_SIZE]; extern __xdata uint8_t gpio_last_value[8]; +extern __xdata struct flash_region_t flash_region; + __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code hex = "0123456789abcdef"; -__xdata uint8_t flash_buf[256]; +__xdata uint8_t flash_buf[512]; // NIC buffers for packet RX/TX __xdata uint8_t rx_headers[16]; // Packet header(s) on RX @@ -195,9 +200,6 @@ uint16_t strlen_x(register __xdata const char *s) uint16_t l = 0; while (s[l]) l++; - write_char(';'); - print_short(l); - write_char(';'); return l; } @@ -761,12 +763,14 @@ void tcpip_output(void) uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8; ring_ptr |= sfr_data[3]; +#ifdef RXTXDBG print_string("TX: \n"); for (uint8_t i = 0; i < 120; i++) { print_byte(uip_buf[i]); write_char(' '); } write_char('\n'); +#endif // Move data over from xmem buffer to ASIC side using DMA nic_tx_packet(ring_ptr); @@ -1695,6 +1699,45 @@ void bootloader(void) print_string(" Flash controller\n"); flash_init(0); + // Check update in progress and move blocks + flash_region.addr = FIRMWARE_UPLOAD_START; + flash_region.len = 0x100; + flash_read_bulk(flash_buf); + + if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { + print_string("Update in progress, moving firmware to start of FLASH!\n"); + + __xdata uint32_t dest = 0x0; + __xdata uint32_t source = FIRMWARE_UPLOAD_START; + // A 512kByte = 4MBit Flash has 128*8=1024 512k blocks, we copy only 120 + for (__xdata uint16_t i=0; i < 960; i++) { + print_string("Writing block: "); + print_short(dest); + flash_region.addr = source; + flash_region.len = 0x200; + flash_read_bulk(flash_buf); + write_char('\n'); + if (!(i & 0x7)) { + flash_region.addr = dest; + flash_sector_erase(); + } + flash_region.addr = dest; + flash_region.len = 0x200; + flash_write_bytes(flash_buf); + dest += 0x200; + source += 0x200; + } + print_string("Deleting uploaded flash image\n"); + dest = FIRMWARE_UPLOAD_START; + for (register uint8_t i=0; i < 120; i++) { + flash_region.addr = dest; + flash_sector_erase(); + dest += 0x1000; + } + print_string("Resetting now"); + reset_chip(); + } + // Reset NIC reg_bit_set(0x24, 2); do { diff --git a/tools/fileadder.c b/tools/fileadder.c index 84a2865..7b739d8 100644 --- a/tools/fileadder.c +++ b/tools/fileadder.c @@ -270,7 +270,7 @@ int main(int argc, char **argv) defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef enum mime_type_e {\n mime_HTML = 0,\n mime_SVG,\n mime_ICO,\n mime_PNG,\n mime_JS,\n mime_CSS,\n mime_TXT\n} mime_type_t;\n\n"); defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "struct f_data {\n __code char *file;\n uint32_t start;\n uint16_t len;\n mime_type_t mime;\n};\n\n"); - defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(void);\n\n"); + // defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(void);\n\n"); ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "// This file is automatically generated, do not edit!\n\n"); if (arguments.prefix) @@ -280,7 +280,7 @@ int main(int argc, char **argv) ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " __code char * __code mime_strings[] = {\n \"text/html\",\n \"image/svg+xml\",\n" " \"image/svg+xml\",\n \"image/png\",\n \"text/javascript\",\n \"text/css\",\n \"text/plain\"};\n\n"); ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "__code struct f_data f_data[] = {\n"); - fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n"); + // fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n"); // Now that the beginning of the buffer is filled with out image, optionally resize the image if (filesize) @@ -335,7 +335,7 @@ int main(int argc, char **argv) } ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {0, 0, 0}\n};\n"); - fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n"); + // fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n"); defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#endif\n"); if (filesize) { diff --git a/tools/httpd_sim.c b/tools/httpd_sim.c index 2a4f8d1..9c54444 100644 --- a/tools/httpd_sim.c +++ b/tools/httpd_sim.c @@ -67,6 +67,13 @@ char *getMime(const char *name) return "text/plain"; } +void send_basic_info(int socket) +{ + char *response = "HTTP/1.1 200 OK\r\n" + "Content-Type: application/json; charset=UTF-8\r\n\r\n" + "{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}"; + write(socket, response, strlen(response)); +} void send_vlan(int s, int vlan) { @@ -249,6 +256,11 @@ void launch(struct Server *server) send_status(new_socket); goto done; } + if (!strncmp(&buffer[4], "/information.json", 12)) { + printf("Status request\n"); + send_basic_info(new_socket); + goto done; + } if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) { int vlan = atoi(&buffer[19]); printf("VLAN request for %d\n", vlan);