mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-09-02 15:02:51 +08:00
Merge upstream/main into the Spanning Tree branch
Only httpd.c conflicted: main added the buffered configuration upload next to the pointers this branch had moved into xdata to free internal RAM. Both belong, so the new globals sit above declarations that keep their storage class.
This commit is contained in:
+99
-5
@@ -42,6 +42,15 @@ __xdata uint32_t cont_addr;
|
||||
|
||||
// HTTP header properties
|
||||
__xdata uint8_t boundary[72];
|
||||
|
||||
// a client may split the request anywhere, including inside a boundary or a
|
||||
// part header, so a configuration upload is parsed only once it is complete;
|
||||
// sized for a full config sector plus the multipart framing around it
|
||||
#define CONFIG_UPLOAD_BUF (CONFIG_LEN + 384)
|
||||
__xdata uint8_t config_upload;
|
||||
__xdata uint8_t config_buf[CONFIG_UPLOAD_BUF];
|
||||
__xdata uint16_t cfg_pos, cfg_hdr, cfg_body, cfg_end, cfg_last;
|
||||
__xdata uint8_t cfg_bl;
|
||||
__xdata uint8_t * __xdata content_type = 0;
|
||||
__xdata uint8_t * __xdata session = 0;
|
||||
|
||||
@@ -78,6 +87,7 @@ inline uint8_t is_separator(uint8_t c)
|
||||
|
||||
void httpd_init(void) __banked
|
||||
{
|
||||
config_upload = 0; // xdata is not zeroed by the startup code
|
||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||
// Start listening to port 80
|
||||
uip_listen(HTONS(80));
|
||||
@@ -316,6 +326,65 @@ void gen_random_bytes(__xdata uint8_t *b, uint8_t bytes)
|
||||
}
|
||||
|
||||
|
||||
/* 0: body incomplete, 1: configuration stored, 2: malformed */
|
||||
static uint8_t config_take(void)
|
||||
{
|
||||
cfg_bl = strlen_x(boundary);
|
||||
|
||||
// the body is complete once the closing boundary has arrived
|
||||
cfg_last = 0;
|
||||
while (1) {
|
||||
if (cfg_last + cfg_bl + 1 >= write_len)
|
||||
return 0;
|
||||
if (strstart_x(&config_buf[cfg_last], boundary)
|
||||
&& strstart(&config_buf[cfg_last + cfg_bl], "--"))
|
||||
break;
|
||||
cfg_last++;
|
||||
}
|
||||
|
||||
// every part lies ahead of the closing boundary, so it bounds the walk
|
||||
cfg_pos = 0;
|
||||
while (cfg_pos < cfg_last) {
|
||||
if (!strstart_x(&config_buf[cfg_pos], boundary)) {
|
||||
cfg_pos++;
|
||||
continue;
|
||||
}
|
||||
cfg_hdr = cfg_pos + cfg_bl;
|
||||
cfg_body = cfg_hdr;
|
||||
while (1) {
|
||||
if (cfg_body + 3 >= cfg_last)
|
||||
return 2;
|
||||
if (strstart(&config_buf[cfg_body], "\r\n\r\n"))
|
||||
break;
|
||||
cfg_body++;
|
||||
}
|
||||
cfg_end = cfg_body;
|
||||
cfg_body += 4;
|
||||
// reaching cfg_last is a match: the last part ends at the closing boundary
|
||||
while (cfg_end < cfg_last && !strstart_x(&config_buf[cfg_end], boundary))
|
||||
cfg_end++;
|
||||
while (cfg_hdr + 8 < cfg_body) {
|
||||
// the part carrying a filename holds the configuration
|
||||
if (strstart(&config_buf[cfg_hdr], "filename")) {
|
||||
// the payload plus its terminator must fit the sector
|
||||
if (cfg_end - cfg_body + 1 > CONFIG_LEN)
|
||||
return 2;
|
||||
config_buf[cfg_end] = 0;
|
||||
flash_region.addr = CONFIG_START;
|
||||
flash_sector_erase();
|
||||
flash_region.addr = CONFIG_START;
|
||||
flash_region.len = cfg_end - cfg_body + 1;
|
||||
flash_write_bytes(config_buf + cfg_body);
|
||||
return 1;
|
||||
}
|
||||
cfg_hdr++;
|
||||
}
|
||||
cfg_pos = cfg_end;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reads post data from the http stream and writes it into flash memory
|
||||
* Input: the current position in the TCP buffer (uip_appdata)
|
||||
@@ -438,6 +507,7 @@ void handle_post(void)
|
||||
return;
|
||||
}
|
||||
print_string("Firmware upload started.");
|
||||
config_upload = 0;
|
||||
uptr = FIRMWARE_UPLOAD_START;
|
||||
verify_crc = 1;
|
||||
max_upload = 1024576;
|
||||
@@ -446,12 +516,10 @@ void handle_post(void)
|
||||
send_unauthorized();
|
||||
return;
|
||||
}
|
||||
dbg_string("Configuration upload, erasing config mem!\n");
|
||||
uptr = CONFIG_START;
|
||||
dbg_string("Configuration upload\n");
|
||||
verify_crc = 0;
|
||||
max_upload = 2048;
|
||||
flash_region.addr = CONFIG_START;
|
||||
flash_sector_erase();
|
||||
config_upload = 1;
|
||||
write_len = 0;
|
||||
}
|
||||
// Check for other POST requests, which are not multipart, below
|
||||
} else {
|
||||
@@ -505,6 +573,32 @@ void handle_post(void)
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
if (config_upload) {
|
||||
cfg_pos = uip_len - (p - uip_appdata);
|
||||
if (write_len + cfg_pos >= CONFIG_UPLOAD_BUF) {
|
||||
print_string("Configuration too large, aborting.\n");
|
||||
config_upload = 0;
|
||||
s->tstate = TSTATE_NONE;
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
memcpy(config_buf + write_len, p, cfg_pos);
|
||||
write_len += cfg_pos;
|
||||
uint8_t taken = config_take();
|
||||
|
||||
if (!taken) {
|
||||
s->tstate = TSTATE_MULTIPART;
|
||||
return;
|
||||
}
|
||||
config_upload = 0;
|
||||
s->tstate = TSTATE_NONE;
|
||||
if (taken == 2) {
|
||||
send_bad_request();
|
||||
return;
|
||||
}
|
||||
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n");
|
||||
return;
|
||||
}
|
||||
// We skip the intial parts as part of the header
|
||||
do {
|
||||
p = skip_boundary(p);
|
||||
|
||||
+9
-29
@@ -178,10 +178,12 @@ void reg_to_html_long(register uint16_t reg)
|
||||
void send_sfp_info(uint8_t sfp)
|
||||
{
|
||||
// This loops over the Vendor-name, Vendor OUI, Vendor PN and Vendor rev ASCII fields
|
||||
for (uint8_t i = 20; i < 60; i++) {
|
||||
if (i >= 36 && i < 40) // Skip Non-ASCII codes
|
||||
for (uint8_t i = 16; i < 64; i++) {
|
||||
if (!(i & 0xf))
|
||||
sfp_read_block(sfp, i, 16);
|
||||
if (i < 20 || i >= 60 || (i >= 36 && i < 40)) // Skip Non-ASCII codes
|
||||
continue;
|
||||
uint8_t c = sfp_read_reg(sfp, i);
|
||||
uint8_t c = sfp_buf[i & 0xf];
|
||||
if (c && c != 0xa0) // a0 is the byte read from a non-existant I2C EEPROM
|
||||
char_to_html(c);
|
||||
}
|
||||
@@ -194,32 +196,10 @@ void sfp_send_data(uint8_t slot, uint8_t reg, uint8_t len)
|
||||
if (len > 16)
|
||||
return;
|
||||
|
||||
if (reg & 0x80) { // Configure SFP readings address (0x51) as I2C device address
|
||||
reg &= 0x7f;
|
||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | (len - 1) & 0xf, 0x51 >> 5, (0x51 << 3) & 0xff);
|
||||
} else {
|
||||
REG_WRITE(RTL837X_REG_I2C_CTRL, 0x00, 0x1 << (I2C_MEM_ADDR_WIDTH-16) | (len - 1) & 0xf, 0x50 >> 5, (0x50 << 3) & 0xff);
|
||||
}
|
||||
sfp_read_block(slot, reg, len);
|
||||
|
||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
||||
sfr_mask_data(1, 0xfc, i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5 | i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2);
|
||||
reg_write_m(RTL837X_REG_I2C_CTRL);
|
||||
|
||||
REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg);
|
||||
|
||||
// Execute I2C Read
|
||||
reg_bit_set(RTL837X_REG_I2C_CTRL, 0);
|
||||
|
||||
// Wait for execution to finish
|
||||
do {
|
||||
reg_read_m(RTL837X_REG_I2C_CTRL);
|
||||
} while (sfr_data[3] & 0x1);
|
||||
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
if (!(i & 0x3))
|
||||
reg_read_m(RTL837X_REG_I2C_OUT + i);
|
||||
byte_to_html(sfr_data[3 - (i & 0x3)]);
|
||||
}
|
||||
for (uint8_t i = 0; i < len; i++)
|
||||
byte_to_html(sfp_buf[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -936,7 +916,7 @@ found_end:
|
||||
if (valid_len > (TCP_OUTBUF_SIZE - slen)) {
|
||||
cont_len = valid_len - (TCP_OUTBUF_SIZE - slen);
|
||||
valid_len = TCP_OUTBUF_SIZE - slen;
|
||||
cont_addr = valid_len;
|
||||
cont_addr = CONFIG_START + valid_len;
|
||||
}
|
||||
|
||||
flash_region.addr = CONFIG_START;
|
||||
|
||||
Reference in New Issue
Block a user