blob: ad4174c6bfac581d9c830334910f6ffd604f4422 [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright 2014 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <boot/coreboot_tables.h>
#include <console/console.h>
#include <string.h>
#include <vendorcode/google/chromeos/cros_vpd.h>
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.
*/
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);
}