summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/servo_v4/board.h2
-rw-r--r--chip/stm32/usb.c58
-rw-r--r--common/flash.c131
-rw-r--r--common/system.c21
-rw-r--r--include/config.h10
-rw-r--r--include/flash.h19
-rw-r--r--include/system.h13
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