summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/boot/coreboot_tables.h13
-rw-r--r--src/lib/coreboot_table.c74
2 files changed, 87 insertions, 0 deletions
diff --git a/src/include/boot/coreboot_tables.h b/src/include/boot/coreboot_tables.h
index 46c1df5e49..0efb8fdb41 100644
--- a/src/include/boot/coreboot_tables.h
+++ b/src/include/boot/coreboot_tables.h
@@ -263,6 +263,19 @@ struct lb_board_id {
uint32_t board_id;
};
+#define LB_TAG_MAC_ADDRS 0x0026
+struct mac_address {
+ uint8_t mac_addr[6];
+ uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */
+};
+
+struct lb_macs {
+ uint32_t tag;
+ uint32_t size;
+ uint32_t count;
+ struct mac_address mac_addrs[0];
+};
+
/* The following structures are for the cmos definitions table */
#define LB_TAG_CMOS_OPTION_TABLE 200
/* cmos header record */
diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c
index d6d84cd3f5..a8b5edf049 100644
--- a/src/lib/coreboot_table.c
+++ b/src/lib/coreboot_table.c
@@ -38,6 +38,7 @@
#endif
#include <vendorcode/google/chromeos/chromeos.h>
#include <vendorcode/google/chromeos/gnvs.h>
+#include <vendorcode/google/chromeos/cros_vpd.h>
#endif
#if CONFIG_ARCH_X86
#include <cpu/x86/mtrr.h>
@@ -157,9 +158,79 @@ void fill_lb_gpio(struct lb_gpio *gpio, int num,
}
#if CONFIG_CHROMEOS
+static void lb_macs(struct lb_header *header)
+{
+ /*
+ * In case there is one or more MAC addresses stored in the VPD, the
+ * key is "ethernet_mac{0..9}", up to 10 values.
+ */
+ static const char mac_addr_key_base[] = "ethernet_mac0";
+ char mac_addr_key[sizeof(mac_addr_key_base)];
+ char mac_addr_str[13]; /* 12 symbols and the trailing zero. */
+ int count;
+ struct lb_macs *macs = NULL;
+ const int index_of_index = sizeof(mac_addr_key) - 2;
+
+ /*
+ * MAC addresses are stored in the VPD as strings of hex numbers,
+ * which need to be converted into binary for storing in the coreboot
+ * table.
+ */
+ strcpy(mac_addr_key, mac_addr_key_base);
+ count = 0;
+ do {
+ int i;
+
+ if (!cros_vpd_gets(mac_addr_key, mac_addr_str,
+ sizeof(mac_addr_str)))
+ break; /* No more MAC addresses in VPD */
+
+ if (!macs) {
+ macs = (struct lb_macs *)lb_new_record(header);
+ macs->tag = LB_TAG_MAC_ADDRS;
+ }
+
+ /* MAC address in symbolic form is in mac_addr_str. */
+ for (i = 0; i < sizeof(macs->mac_addrs[0].mac_addr); i++) {
+ int j;
+ uint8_t n = 0;
+
+ for (j = 0; j < 2; j++) {
+ char c = mac_addr_str[i * 2 + j];
+
+ if (isxdigit(c)) {
+ if (isdigit(c))
+ c -= '0';
+ else
+ c = tolower(c) - 'a' + 10;
+ } else {
+ printk(BIOS_ERR,
+ "%s: non hexadecimal symbol "
+ "%#2.2x in the VPD field %s\n",
+ __func__, (uint8_t)c,
+ mac_addr_key);
+ c = 0;
+ }
+ n <<= 4;
+ n |= c;
+ }
+ macs->mac_addrs[count].mac_addr[i] = n;
+ }
+ count++;
+ mac_addr_key[index_of_index] = '0' + count;
+ } while (count < 10);
+
+ if (!count)
+ return; /* No MAC addresses in the VPD. */
+
+ macs->count = count;
+ macs->size = sizeof(*macs) + count * sizeof(struct mac_address);
+}
+
static void lb_gpios(struct lb_header *header)
{
struct lb_gpios *gpios;
+
gpios = (struct lb_gpios *)lb_new_record(header);
gpios->tag = LB_TAG_GPIO;
gpios->size = sizeof(*gpios);
@@ -446,6 +517,9 @@ unsigned long write_coreboot_table(
/* pass along the vboot_handoff address. */
lb_vboot_handoff(head);
+
+ /* Retrieve mac addresses from VPD, if any. */
+ lb_macs(head);
#endif
/* Add board ID if available */