From 3853a2701d169b3596630045c9ad1e498e3b6766 Mon Sep 17 00:00:00 2001 From: bloqaudio Date: Fri, 3 Jul 2026 20:57:45 -0500 Subject: [PATCH] machine: read a factory MAC from flash via mac_flash_offset Adds an optional per-board mac_flash_offset. When non-zero, RTLPlayground reads a 6-byte MAC from that flash address and uses it if it is a valid globally-administered unicast address; otherwise it falls back to the generated locally-administered MAC. Offset 0 (default for every board) preserves current behaviour. Enable it for the SWTGW218AS, whose stock firmware keeps the factory MAC in nvcfg at 0x1FC000. RTLPlayground images and web upgrades only touch flash below that region, so the factory MAC survives flashing. --- machine.c | 1 + machine.h | 1 + rtlplayground.c | 36 ++++++++++++++++++++++-------------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/machine.c b/machine.c index 091097a..c27b92a 100644 --- a/machine.c +++ b/machine.c @@ -415,6 +415,7 @@ void machine_custom_init(void) { } __code const struct machine machine = { .machine_name = "SWTGW218AS 8+1 Managed Switch", .isRTL8373 = 1, + .mac_flash_offset = 0x1FC000, .min_port = 0, .max_port = 8, .n_sfp = 1, diff --git a/machine.h b/machine.h index c3368f6..523beea 100644 --- a/machine.h +++ b/machine.h @@ -85,6 +85,7 @@ typedef struct machine { uint32_t led_sets[4][4]; uint8_t led_mux_custom; uint8_t led_mux[28]; + uint32_t mac_flash_offset; }; typedef struct machine_runtime diff --git a/rtlplayground.c b/rtlplayground.c index ce73963..bdb8ab3 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -2112,20 +2112,28 @@ void main(void) uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]); uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]); uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); - reg_read_m(RTL837X_REG_CHIP_UUID); -#ifdef DEBUG - print_string("SoC UUID: "); print_sfr_data(); -#endif - uip_ethaddr.addr[0] = 0x06; // LAA prefix - uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3]; - uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3]; - uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3]; - reg_read_m(RTL837X_REG_CHIP_LOT_NO); -#ifdef DEBUG - print_string(", LOT: "); print_sfr_data(); write_char(' '); -#endif - uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2]; - uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3]; + uip_ethaddr.addr[0] = 0xff; + if (machine.mac_flash_offset) { + flash_region.addr = machine.mac_flash_offset; + flash_region.len = FLASH_BUF_SIZE; + flash_read_bulk(flash_buf); + // accept only a real unicast, globally-administered address (reject blank/LAA/multicast/all-zero OUI) + if (flash_buf[0] != 0xff && !(flash_buf[0] & 0x03) && (flash_buf[0] | flash_buf[1] | flash_buf[2])) { + uip_ethaddr.addr[0] = flash_buf[0]; uip_ethaddr.addr[1] = flash_buf[1]; + uip_ethaddr.addr[2] = flash_buf[2]; uip_ethaddr.addr[3] = flash_buf[3]; + uip_ethaddr.addr[4] = flash_buf[4]; uip_ethaddr.addr[5] = flash_buf[5]; + } + } + if (uip_ethaddr.addr[0] == 0xff) { // no valid flash MAC -> generate locally-administered + reg_read_m(RTL837X_REG_CHIP_UUID); + uip_ethaddr.addr[0] = 0x06; // LAA prefix + uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3]; + uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3]; + uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3]; + reg_read_m(RTL837X_REG_CHIP_LOT_NO); + uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2]; + uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3]; + } print_string("Setting MAC to: "); print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':'); print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':');