diff options
-rw-r--r-- | src/vendorcode/google/chromeos/vpd_mac.c | 118 |
1 files changed, 69 insertions, 49 deletions
diff --git a/src/vendorcode/google/chromeos/vpd_mac.c b/src/vendorcode/google/chromeos/vpd_mac.c index ad4174c6bfac..ff6ba8ebb291 100644 --- a/src/vendorcode/google/chromeos/vpd_mac.c +++ b/src/vendorcode/google/chromeos/vpd_mac.c @@ -23,68 +23,88 @@ #include <vendorcode/google/chromeos/cros_vpd.h> +/* + * Decode string representation of the MAC address (a string of 12 hex + * symbols) into binary. 'key_name' is the name of the VPD field, it's used if + * it is necessary to report an input data format problem. + */ +static void decode_mac(struct mac_address *mac, + const char *mac_addr_str, + const char *key_name) +{ + int i; + + for (i = 0; i < sizeof(mac->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:%s\n", + __func__, (uint8_t)c, key_name, + mac_addr_str); + c = 0; + } + n <<= 4; + n |= c; + } + mac->mac_addr[i] = n; + } +} + void lb_table_add_macs_from_vpd(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. + * Mac addresses in the VPD can be stored in two groups, for ethernet + * and WiFi, with keys 'ethernet_macX and wifi_macX. */ - static const char mac_addr_key_base[] = "ethernet_mac0"; - char mac_addr_key[sizeof(mac_addr_key_base)]; + const char *mac_addr_key_bases[] = {"ethernet_mac0", "wifi_mac0"}; + char mac_addr_key[20]; /* large enough for either key */ char mac_addr_str[13]; /* 12 symbols and the trailing zero. */ - int count; + int i, 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 */ + /* Make sure the copy is always zero terminated. */ + mac_addr_key[sizeof(mac_addr_key) - 1] = '\0'; - if (!macs) { - macs = (struct lb_macs *)lb_new_record(header); - macs->tag = LB_TAG_MAC_ADDRS; - } + count = 0; + for (i = 0; i < ARRAY_SIZE(mac_addr_key_bases); i++) { + int index_of_index; - /* 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; + strncpy(mac_addr_key, mac_addr_key_bases[i], + sizeof(mac_addr_key) - 1); + index_of_index = strlen(mac_addr_key) - 1; - for (j = 0; j < 2; j++) { - char c = mac_addr_str[i * 2 + j]; + do { + /* + * If there are no more MAC addresses of this template + * in the VPD - move on. + */ + if (!cros_vpd_gets(mac_addr_key, mac_addr_str, + sizeof(mac_addr_str))) + break; - 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; + if (!macs) { + macs = (struct lb_macs *)lb_new_record(header); + macs->tag = LB_TAG_MAC_ADDRS; } - macs->mac_addrs[count].mac_addr[i] = n; - } - count++; - mac_addr_key[index_of_index] = '0' + count; - } while (count < 10); + decode_mac(macs->mac_addrs + count, + mac_addr_str, + mac_addr_key); + + count++; + mac_addr_key[index_of_index]++; + } while (count < 10); + } if (!count) return; /* No MAC addresses in the VPD. */ |