diff options
-rw-r--r-- | board/servo_v4/board.h | 2 | ||||
-rw-r--r-- | chip/stm32/usb.c | 58 | ||||
-rw-r--r-- | common/flash.c | 131 | ||||
-rw-r--r-- | common/system.c | 21 | ||||
-rw-r--r-- | include/config.h | 10 | ||||
-rw-r--r-- | include/flash.h | 19 | ||||
-rw-r--r-- | include/system.h | 13 |
7 files changed, 230 insertions, 24 deletions
diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h index ff46ae13e4..c2b08fa885 100644 --- a/board/servo_v4/board.h +++ b/board/servo_v4/board.h @@ -47,6 +47,8 @@ #define CONFIG_USB_SERIALNO #define DEFAULT_SERIALNO "Uninitialized" +#define CONFIG_MAC_ADDR +#define DEFAULT_MAC_ADDR "Uninitialized" /* USB interface indexes (use define rather than enum to expand them) */ #define USB_IFACE_CONSOLE 0 diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c index 54cd90dd46..7eb2363787 100644 --- a/chip/stm32/usb.c +++ b/chip/stm32/usb.c @@ -897,4 +897,62 @@ static int command_serialno(int argc, char **argv) DECLARE_CONSOLE_COMMAND(serialno, command_serialno, "load/set [value]", "Read and write USB serial number"); + #endif /* CONFIG_USB_SERIALNO */ + +#ifdef CONFIG_MAC_ADDR + +/* Save MAC address into pstate region. */ +static int usb_save_mac_addr(const char *mac_addr) +{ + int rv; + + if (!mac_addr) { + return EC_ERROR_INVAL; + } + + /* Save this new MAC address to flash. */ + rv = board_write_mac_addr(mac_addr); + if (rv) { + return rv; + } + + /* Load this new MAC address to memory. */ + if (board_read_mac_addr() != NULL) { + return EC_SUCCESS; + } else { + return EC_ERROR_UNKNOWN; + } +} + +static int command_macaddr(int argc, char **argv) +{ + const char* buf; + int rv = EC_SUCCESS; + + if (argc != 1) { + if ((strcasecmp(argv[1], "set") == 0) && + (argc == 3)) { + ccprintf("Saving MAC address\n"); + rv = usb_save_mac_addr(argv[2]); + } else if ((strcasecmp(argv[1], "load") == 0) && + (argc == 2)) { + ccprintf("Loading MAC address\n"); + } else { + return EC_ERROR_INVAL; + } + } + + buf = board_read_mac_addr(); + if (buf == NULL) { + buf = DEFAULT_MAC_ADDR; + } + ccprintf("MAC address: %s\n", buf); + return rv; +} + +DECLARE_CONSOLE_COMMAND(macaddr, command_macaddr, + "load/set [value]", + "Read and write MAC address"); + +#endif /* CONFIG_MAC_ADDR */ diff --git a/common/flash.c b/common/flash.c index 4b3a5fae69..f2b871ee0f 100644 --- a/common/flash.c +++ b/common/flash.c @@ -45,8 +45,9 @@ /* Flags for persist_state.flags */ /* Protect persist state and RO firmware at boot */ #define PERSIST_FLAG_PROTECT_RO 0x02 -#define PSTATE_VALID_FLAGS BIT(0) -#define PSTATE_VALID_SERIALNO BIT(1) +#define PSTATE_VALID_FLAGS BIT(0) +#define PSTATE_VALID_SERIALNO BIT(1) +#define PSTATE_VALID_MAC_ADDR BIT(2) struct persist_state { uint8_t version; /* Version of this struct */ @@ -55,10 +56,15 @@ struct persist_state { uint8_t reserved; /* Reserved; set 0 */ #ifdef CONFIG_SERIALNO_LEN uint8_t serialno[CONFIG_SERIALNO_LEN]; /* Serial number. */ -#else +#endif /* CONFIG_SERIALNO_LEN */ +#ifdef CONFIG_MAC_ADDR_LEN + uint8_t mac_addr[CONFIG_MAC_ADDR_LEN]; +#endif /* CONFIG_MAC_ADDR_LEN */ +#if !defined(CONFIG_SERIALNO_LEN) && !defined(CONFIG_MAC_ADDR_LEN) uint8_t padding[4 % CONFIG_FLASH_WRITE_SIZE]; #endif }; + /* written with flash_physical_write, need to respect alignment constraints */ #ifndef CHIP_FAMILY_STM32L /* STM32L1xx is somewhat lying to us */ BUILD_ASSERT(sizeof(struct persist_state) % CONFIG_FLASH_WRITE_SIZE == 0); @@ -275,25 +281,6 @@ static uint32_t flash_read_pstate(void) } } -#ifdef CONFIG_SERIALNO_LEN -/** - * Read and return persistent serial number. - */ -const char *flash_read_pstate_serial(void) -{ - const struct persist_state *pstate = - (const struct persist_state *) - flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); - - if ((pstate->version == PERSIST_STATE_VERSION) && - (pstate->valid_fields & PSTATE_VALID_SERIALNO)) { - return (const char *)(pstate->serialno); - } - - return NULL; -} -#endif - /** * Write persistent state after erasing. * @@ -375,9 +362,26 @@ static int flash_write_pstate(uint32_t flags) #ifdef CONFIG_SERIALNO_LEN /** + * Read and return persistent serial number. + */ +const char *flash_read_pstate_serial(void) +{ + const struct persist_state *pstate = + (const struct persist_state *) + flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + + if ((pstate->version == PERSIST_STATE_VERSION) && + (pstate->valid_fields & PSTATE_VALID_SERIALNO)) { + return (const char *)(pstate->serialno); + } + + return NULL; +} + +/** * Write persistent serial number to pstate, erasing if necessary. * - * @param serialno New iascii serial number to set in pstate. + * @param serialno New ascii serial number to set in pstate. * @return EC_SUCCESS, or nonzero if error. */ int flash_write_pstate_serial(const char *serialno) @@ -408,10 +412,89 @@ int flash_write_pstate_serial(const char *serialno) return flash_write_pstate_data(&newpstate); } -#endif +#endif /* CONFIG_SERIALNO_LEN */ + +#ifdef CONFIG_MAC_ADDR_LEN + +/** + * Read and return persistent MAC address. + */ +const char *flash_read_pstate_mac_addr(void) +{ + const struct persist_state *pstate = + (const struct persist_state *) + flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + + if ((pstate->version == PERSIST_STATE_VERSION) && + (pstate->valid_fields & PSTATE_VALID_MAC_ADDR)) { + return (const char *)(pstate->mac_addr); + } + + return NULL; +} + +/** + * Write persistent MAC Addr to pstate, erasing if necessary. + * + * @param mac_addr New ascii MAC address to set in pstate. + * @return EC_SUCCESS, or nonzero if error. + */ +int flash_write_pstate_mac_addr(const char *mac_addr) +{ + int length; + struct persist_state newpstate; + const struct persist_state *pstate = + (const struct persist_state *) + flash_physical_dataptr(CONFIG_FW_PSTATE_OFF); + + /* Check that this is OK, data is valid and fits in the region. */ + if (!mac_addr) { + return EC_ERROR_INVAL; + } + + /* + * This will perform validation of the mac address before storing it. + * The MAC address format is '12:34:56:78:90:AB', a 17 character long + * string containing pairs of hex digits, each pair delimited by a ':'. + */ + length = strnlen(mac_addr, sizeof(newpstate.mac_addr)); + if (length != 17) { + return EC_ERROR_INVAL; + } + for (int i = 0; i < 17; i++) { + if (i % 3 != 2) { + /* Verify the remaining characters are hex digits. */ + if ((mac_addr[i] < '0' || '9' < mac_addr[i]) && + (mac_addr[i] < 'A' || 'F' < mac_addr[i]) && + (mac_addr[i] < 'a' || 'f' < mac_addr[i])) { + return EC_ERROR_INVAL; + } + } else { + /* Every 3rd character is a ':' */ + if (mac_addr[i] != ':') { + return EC_ERROR_INVAL; + } + } + } + /* Cache the old copy for read/modify/write. */ + memcpy(&newpstate, pstate, sizeof(newpstate)); + validate_pstate_struct(&newpstate); + + /* + * Erase any prior data and copy the string. The length was verified to + * be shorter than the buffer so a null terminator always remains. + */ + memset(newpstate.mac_addr, '\0', sizeof(newpstate.mac_addr)); + memcpy(newpstate.mac_addr, mac_addr, length); + + newpstate.valid_fields |= PSTATE_VALID_MAC_ADDR; + + return flash_write_pstate_data(&newpstate); +} +#endif /* CONFIG_MAC_ADDR_LEN */ #else /* !CONFIG_FLASH_PSTATE_BANK */ diff --git a/common/system.c b/common/system.c index 5d07bfcf90..7b50f57a1f 100644 --- a/common/system.c +++ b/common/system.c @@ -1560,6 +1560,27 @@ __overridable int board_write_serial(const char *serialno) } #endif /* CONFIG_SERIALNO_LEN */ +#ifdef CONFIG_MAC_ADDR_LEN +/* By default, read MAC address from flash, can be overridden. */ +__overridable const char *board_read_mac_addr(void) +{ + if (IS_ENABLED(CONFIG_FLASH_PSTATE) && + IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) + return flash_read_pstate_mac_addr(); + else + return ""; +} + +/* By default, write MAC address from flash, can be overridden. */ +__overridable int board_write_mac_addr(const char *mac_addr) +{ + if (IS_ENABLED(CONFIG_FLASH_PSTATE) && + IS_ENABLED(CONFIG_FLASH_PSTATE_BANK)) + return flash_write_pstate_mac_addr(mac_addr); + else + return EC_ERROR_UNIMPLEMENTED; +} +#endif /* CONFIG_MAC_ADDR_LEN */ __attribute__((weak)) void clock_enable_module(enum module_id module, int enable) diff --git a/include/config.h b/include/config.h index 87b05ed617..3dae6a4668 100644 --- a/include/config.h +++ b/include/config.h @@ -3185,6 +3185,12 @@ /* Size of the serial number if needed */ #undef CONFIG_SERIALNO_LEN +/* Support programmable Mac address field. */ +#undef CONFIG_MAC_ADDR + +/* Size of the MAC address field if needed. */ +#undef CONFIG_MAC_ADDR_LEN + /****************************************************************************/ /* Shared objects library. */ @@ -5126,6 +5132,10 @@ #define CONFIG_SERIALNO_LEN 28 #endif +#ifdef CONFIG_MAC_ADDR +#define CONFIG_MAC_ADDR_LEN 20 +#endif + #ifndef CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ #define CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ \ CONFIG_EC_MAX_SENSOR_FREQ_DEFAULT_MILLIHZ diff --git a/include/flash.h b/include/flash.h index cceac81df1..700a663a9a 100644 --- a/include/flash.h +++ b/include/flash.h @@ -344,6 +344,25 @@ const char *flash_read_pstate_serial(void); int flash_write_pstate_serial(const char *serialno); /** + * Get the MAC address from flash. + * + * @return char * ascii MAC address string. + * Format: "01:23:45:67:89:AB" + * NULL if error. + */ +const char *flash_read_pstate_mac_addr(void); + +/** + * Set the MAC address in flash. + * + * @param mac_addr ascii MAC address string. + * Format: "01:23:45:67:89:AB" + * + * @return success status. + */ +int flash_write_pstate_mac_addr(const char *mac_addr); + +/** * Lock or unlock HW necessary for mapped storage read. * * @param lock 1 to lock, 0 to unlock. diff --git a/include/system.h b/include/system.h index 0d785c6899..249ab58bf4 100644 --- a/include/system.h +++ b/include/system.h @@ -328,6 +328,19 @@ __override_proto const char *board_read_serial(void); */ __override_proto int board_write_serial(const char *serial); + +/** + * Optional board-level callback functions to read a unique MAC address per + * chip. Default implementation reads from flash. + */ +__override_proto const char *board_read_mac_addr(void); + +/** + * Optional board-level callback functions to write a unique MAC address per + * chip. Default implementation reads from flash. + */ +__override_proto int board_write_mac_addr(const char *mac_addr); + /* * Common bbram entries. Chips don't necessarily need to implement * all of these, error will be returned from system_get/set_bbram if |