drivers/net/r8168: Split fetch_mac_string_vpd() logic up

Orginally fetch_mac_string_vpd() has been special cased around
a device_index of 0/1 that causes a number of edge cases and
complexity when attempting to refactor to deal with the revised
VPD format. The following change prepares the ground work by
splitting up the functional into logical workers where we can
deal with each edge case in a more bounded way.

The background here is that the format for VPD has changed s.t. the
first NIC should always have a zero concat to the end. The details
of that can be found here:
 https://chromeos.google.com/partner/dlm/docs/factory/vpd.html#field-ethernet_macn

BUG=b:152157720
BRANCH=none
TEST=none

Change-Id: Idc886d9b0b3037c91f40b742437e4e50711b5f00
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/39811
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Edward O'Callaghan 2020-03-25 12:52:50 +11:00 committed by Edward O'Callaghan
parent 335384d2b7
commit 2a82f744d4
1 changed files with 59 additions and 43 deletions

View File

@ -92,12 +92,49 @@ static u8 get_hex_digit(const u8 c)
#define MACLEN 17 #define MACLEN 17
static enum cb_err fetch_mac_string_vpd(u8 *macstrbuf, const u8 device_index) /* Returns MAC address based on the key that is passed in. */
static enum cb_err fetch_mac_vpd_key(u8 *macstrbuf, const char *vpd_key)
{ {
struct region_device rdev; struct region_device rdev;
void *search_address; void *search_address;
size_t search_length; size_t search_length;
size_t offset; size_t offset;
if (fmap_locate_area_as_rdev("RO_VPD", &rdev)) {
printk(BIOS_ERR, "Error: Couldn't find RO_VPD region.");
return CB_ERR;
}
search_address = rdev_mmap_full(&rdev);
if (search_address == NULL) {
printk(BIOS_ERR, "LAN: VPD not found.\n");
return CB_ERR;
}
search_length = region_device_sz(&rdev);
offset = search(vpd_key, search_address, strlen(vpd_key),
search_length);
if (offset == search_length) {
printk(BIOS_ERR,
"Error: Could not locate '%s' in VPD\n", vpd_key);
return CB_ERR;
}
printk(BIOS_DEBUG, "Located '%s' in VPD\n", vpd_key);
offset += strlen(vpd_key) + 1; /* move to next character */
if (offset + MACLEN > search_length) {
printk(BIOS_ERR, "Search result too small!\n");
return CB_ERR;
}
memcpy(macstrbuf, search_address + offset, MACLEN);
return CB_SUCCESS;
}
/* Prepares vpd_key by concatenating ethernet_mac with device_index */
static enum cb_err fetch_mac_vpd_dev_idx(u8 *macstrbuf, u8 device_index)
{
char key[] = "ethernet_mac "; /* Leave a space at tail to stuff an index */ char key[] = "ethernet_mac "; /* Leave a space at tail to stuff an index */
/* /*
@ -112,35 +149,29 @@ static enum cb_err fetch_mac_string_vpd(u8 *macstrbuf, const u8 device_index)
/* Translate index number from integer to ascii */ /* Translate index number from integer to ascii */
key[DEVICE_INDEX_BYTE] = (device_index - 1) + '0'; key[DEVICE_INDEX_BYTE] = (device_index - 1) + '0';
if (fmap_locate_area_as_rdev("RO_VPD", &rdev)) { return fetch_mac_vpd_key(macstrbuf, key);
printk(BIOS_ERR, "Error: Couldn't find RO_VPD region."); }
return CB_ERR;
} static void fetch_mac_string_vpd(struct drivers_net_config *config, u8 *macstrbuf)
search_address = rdev_mmap_full(&rdev); {
if (search_address == NULL) { if (!config)
printk(BIOS_ERR, "LAN: VPD not found.\n"); return;
return CB_ERR;
/* Current implementation is up to 10 NIC cards */
if (config->device_index > MAX_DEVICE_SUPPORT) {
printk(BIOS_ERR, "r8168: the maximum device_index should be less then %d\n."
" Using default 00:e0:4c:00:c0:b0\n", MAX_DEVICE_SUPPORT);
return;
} }
search_length = region_device_sz(&rdev); /* check "ethernet_mac" first when the device index is 1 */
offset = search(key, search_address, strlen(key), if (config->device_index == 1 &&
search_length); fetch_mac_vpd_dev_idx(macstrbuf, 0) == CB_SUCCESS)
return;
if (offset == search_length) { if (fetch_mac_vpd_dev_idx(macstrbuf, config->device_index) != CB_SUCCESS)
printk(BIOS_ERR, printk(BIOS_ERR, "r8168: mac address not found in VPD,"
"Error: Could not locate '%s' in VPD\n", key); " using default 00:e0:4c:00:c0:b0\n");
return CB_ERR;
}
printk(BIOS_DEBUG, "Located '%s' in VPD\n", key);
offset += strlen(key) + 1; /* move to next character */
if (offset + MACLEN > search_length) {
printk(BIOS_ERR, "Search result too small!\n");
return CB_ERR;
}
memcpy(macstrbuf, search_address + offset, MACLEN);
return CB_SUCCESS;
} }
static enum cb_err fetch_mac_string_cbfs(u8 *macstrbuf) static enum cb_err fetch_mac_string_cbfs(u8 *macstrbuf)
@ -186,25 +217,10 @@ static void program_mac_address(struct device *dev, u16 io_base)
/* Default MAC Address of 00:E0:4C:00:C0:B0 */ /* Default MAC Address of 00:E0:4C:00:C0:B0 */
u8 mac[6] = { 0x00, 0xe0, 0x4c, 0x00, 0xc0, 0xb0 }; u8 mac[6] = { 0x00, 0xe0, 0x4c, 0x00, 0xc0, 0xb0 };
struct drivers_net_config *config = dev->chip_info; struct drivers_net_config *config = dev->chip_info;
bool mac_found = false;
/* check the VPD for the mac address */ /* check the VPD for the mac address */
if (CONFIG(RT8168_GET_MAC_FROM_VPD)) { if (CONFIG(RT8168_GET_MAC_FROM_VPD)) {
/* Current implementation is up to 10 NIC cards */ fetch_mac_string_vpd(config, macstrbuf);
if (config && config->device_index <= MAX_DEVICE_SUPPORT) {
/* check "ethernet_mac" first when the device index is 1 */
if (config->device_index == 1 &&
fetch_mac_string_vpd(macstrbuf, 0) == CB_SUCCESS)
mac_found = true;
if (!mac_found && fetch_mac_string_vpd(macstrbuf,
config->device_index) != CB_SUCCESS)
printk(BIOS_ERR, "r8168: mac address not found in VPD,"
" using default 00:e0:4c:00:c0:b0\n");
} else {
printk(BIOS_ERR, "r8168: the maximum device_index should be"
" less then %d\n. Using default 00:e0:4c:00:c0:b0\n",
MAX_DEVICE_SUPPORT);
}
} else { } else {
if (fetch_mac_string_cbfs(macstrbuf) != CB_SUCCESS) if (fetch_mac_string_cbfs(macstrbuf) != CB_SUCCESS)
printk(BIOS_ERR, "r8168: Error reading MAC from CBFS," printk(BIOS_ERR, "r8168: Error reading MAC from CBFS,"