ec/google/chromeec: Optimize battery string readout with caching
[coreboot.git] / src / vendorcode / google / chromeos / vpd_mac.c
blob385b9f475de1be5e37c8a079a733ea1916ea32a8
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <boot/coreboot_tables.h>
4 #include <console/console.h>
5 #include <ctype.h>
6 #include <string.h>
8 #include <drivers/vpd/vpd.h>
11 * Decode string representation of the MAC address (a string of 12 hex
12 * symbols) into binary. 'key_name' is the name of the VPD field, it's used if
13 * it is necessary to report an input data format problem.
15 static void decode_mac(struct mac_address *mac,
16 const char *mac_addr_str,
17 const char *key_name)
19 int i;
21 for (i = 0; i < sizeof(mac->mac_addr); i++) {
22 int j;
23 uint8_t n = 0;
25 for (j = 0; j < 2; j++) {
26 char c = mac_addr_str[i * 2 + j];
28 if (isxdigit(c)) {
29 if (isdigit(c))
30 c -= '0';
31 else
32 c = tolower(c) - 'a' + 10;
33 } else {
34 printk(BIOS_ERR, "%s: non hexadecimal symbol "
35 "%#2.2x in the VPD field %s:%s\n",
36 __func__, (uint8_t)c, key_name,
37 mac_addr_str);
38 c = 0;
40 n <<= 4;
41 n |= c;
43 mac->mac_addr[i] = n;
47 void lb_table_add_macs_from_vpd(struct lb_header *header)
50 * Mac addresses in the VPD can be stored in two groups, for ethernet
51 * and WiFi, with keys 'ethernet_macX and wifi_macX.
53 const char *mac_addr_key_bases[] = {"ethernet_mac0", "wifi_mac0"};
54 char mac_addr_key[20]; /* large enough for either key */
55 char mac_addr_str[13]; /* 12 symbols and the trailing zero. */
56 int i, count;
57 struct lb_macs *macs = NULL;
59 /* Make sure the copy is always zero terminated. */
60 mac_addr_key[sizeof(mac_addr_key) - 1] = '\0';
62 count = 0;
63 for (i = 0; i < ARRAY_SIZE(mac_addr_key_bases); i++) {
64 int index_of_index;
66 strncpy(mac_addr_key, mac_addr_key_bases[i],
67 sizeof(mac_addr_key) - 1);
68 index_of_index = strlen(mac_addr_key) - 1;
70 do {
72 * If there are no more MAC addresses of this template
73 * in the VPD - move on.
75 if (!vpd_gets(mac_addr_key, mac_addr_str,
76 sizeof(mac_addr_str), VPD_RO_THEN_RW))
77 break;
79 if (!macs) {
80 macs = (struct lb_macs *)lb_new_record(header);
81 macs->tag = LB_TAG_MAC_ADDRS;
84 decode_mac(macs->mac_addrs + count,
85 mac_addr_str,
86 mac_addr_key);
88 count++;
89 mac_addr_key[index_of_index]++;
90 } while (count < 10);
92 if (!count)
93 return; /* No MAC addresses in the VPD. */
95 macs->count = count;
96 macs->size = sizeof(*macs) + count * sizeof(struct mac_address);