blob: 061997453aff429610df041ee39284302e14d474 [file] [log] [blame]
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070014 */
15
16#include <boot/coreboot_tables.h>
17#include <console/console.h>
18#include <string.h>
19
20#include <vendorcode/google/chromeos/cros_vpd.h>
21
Vadim Bendebury375f3922015-03-28 22:14:13 -070022/*
23 * Decode string representation of the MAC address (a string of 12 hex
24 * symbols) into binary. 'key_name' is the name of the VPD field, it's used if
25 * it is necessary to report an input data format problem.
26 */
27static void decode_mac(struct mac_address *mac,
28 const char *mac_addr_str,
29 const char *key_name)
30{
31 int i;
32
33 for (i = 0; i < sizeof(mac->mac_addr); i++) {
34 int j;
35 uint8_t n = 0;
36
37 for (j = 0; j < 2; j++) {
38 char c = mac_addr_str[i * 2 + j];
39
40 if (isxdigit(c)) {
41 if (isdigit(c))
42 c -= '0';
43 else
44 c = tolower(c) - 'a' + 10;
45 } else {
46 printk(BIOS_ERR, "%s: non hexadecimal symbol "
47 "%#2.2x in the VPD field %s:%s\n",
48 __func__, (uint8_t)c, key_name,
49 mac_addr_str);
50 c = 0;
51 }
52 n <<= 4;
53 n |= c;
54 }
55 mac->mac_addr[i] = n;
56 }
57}
58
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070059void lb_table_add_macs_from_vpd(struct lb_header *header)
60{
61 /*
Vadim Bendebury375f3922015-03-28 22:14:13 -070062 * Mac addresses in the VPD can be stored in two groups, for ethernet
63 * and WiFi, with keys 'ethernet_macX and wifi_macX.
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070064 */
Vadim Bendebury375f3922015-03-28 22:14:13 -070065 const char *mac_addr_key_bases[] = {"ethernet_mac0", "wifi_mac0"};
66 char mac_addr_key[20]; /* large enough for either key */
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070067 char mac_addr_str[13]; /* 12 symbols and the trailing zero. */
Vadim Bendebury375f3922015-03-28 22:14:13 -070068 int i, count;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070069 struct lb_macs *macs = NULL;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070070
Vadim Bendebury375f3922015-03-28 22:14:13 -070071 /* Make sure the copy is always zero terminated. */
72 mac_addr_key[sizeof(mac_addr_key) - 1] = '\0';
73
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070074 count = 0;
Vadim Bendebury375f3922015-03-28 22:14:13 -070075 for (i = 0; i < ARRAY_SIZE(mac_addr_key_bases); i++) {
76 int index_of_index;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070077
Vadim Bendebury375f3922015-03-28 22:14:13 -070078 strncpy(mac_addr_key, mac_addr_key_bases[i],
79 sizeof(mac_addr_key) - 1);
80 index_of_index = strlen(mac_addr_key) - 1;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070081
Vadim Bendebury375f3922015-03-28 22:14:13 -070082 do {
83 /*
84 * If there are no more MAC addresses of this template
85 * in the VPD - move on.
86 */
87 if (!cros_vpd_gets(mac_addr_key, mac_addr_str,
88 sizeof(mac_addr_str)))
89 break;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070090
Vadim Bendebury375f3922015-03-28 22:14:13 -070091 if (!macs) {
92 macs = (struct lb_macs *)lb_new_record(header);
93 macs->tag = LB_TAG_MAC_ADDRS;
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070094 }
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -070095
Vadim Bendebury375f3922015-03-28 22:14:13 -070096 decode_mac(macs->mac_addrs + count,
97 mac_addr_str,
98 mac_addr_key);
99
100 count++;
101 mac_addr_key[index_of_index]++;
102 } while (count < 10);
103 }
Vadim Bendeburydd94b5f2014-10-16 13:02:37 -0700104 if (!count)
105 return; /* No MAC addresses in the VPD. */
106
107 macs->count = count;
108 macs->size = sizeof(*macs) + count * sizeof(struct mac_address);
109}