drivers/net/r8168: Get mac address from VPD

If RT8168_GET_MAC_FROM_VPD selected, use r8168
driver with some slight mods to check the VPD
for a mac address.  Otherwise, check for mac
address in cbfs.  Use default mac address if
cannot find one.

BUG=b:62090148, b:35775024
BRANCH=None
TEST=Boot to kernel.  Insert mac address into VPD
       vpd -s ethernet_mac=<address>
     reboot the system.
     Ensure we have ip address and corresponding mac
     address with ifconfig.
     Ensure ethernet controller shows up with lspci.

Change-Id: I7ff29de2c4c3635dc786686cc071c68d51b0f975
Signed-off-by: Shelley Chen <shchen@chromium.org>
Reviewed-on: https://review.coreboot.org/20008
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Shelley Chen 2017-06-12 18:29:24 -07:00 committed by Martin Roth
parent 5aa64b97db
commit 0528b6132e
2 changed files with 108 additions and 20 deletions

View File

@ -6,10 +6,15 @@ config REALTEK_8168_RESET
config REALTEK_8168_MACADDRESS
string "Realtek rt8168 mac address"
depends on REALTEK_8168_RESET
depends on REALTEK_8168_RESET && !RT8168_GET_MAC_FROM_VPD
default "00:e0:4c:00:c0:b0"
help
This is a string to set the mac address on a Realtek rt8168 card.
It must be in the form of "xx:xx:xx:xx:xx:xx", where x is a
hexadecimal number for it to be valid. Failing to do so will
result in the default macaddress being used.
config RT8168_GET_MAC_FROM_VPD
bool
default n
select REALTEK_8168_RESET

View File

@ -24,12 +24,13 @@
#include <cbfs.h>
#include <string.h>
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_def.h>
#include <delay.h>
#include <console/console.h>
#include <fmap.h>
#define NIC_TIMEOUT 1000
@ -40,6 +41,32 @@
#define CFG_9346_LOCK 0x00
#define CFG_9346_UNLOCK 0xc0
/**
* search: Find first instance of string in a given region
* @param p string to find
* @param a start address of region to search
* @param lengthp length of string to search for
* @param lengtha length of region to search in
* @return offset offset from start address a where string was found.
* If string not found, return lengtha.
*/
static size_t search(const char *p, const u8 *a, size_t lengthp,
size_t lengtha)
{
size_t i, j;
if (lengtha < lengthp)
return lengtha;
/* Searching */
for (j = 0; j <= lengtha - lengthp; j++) {
for (i = 0; i < lengthp && p[i] == a[i + j]; i++)
;
if (i >= lengthp)
return j;
}
return lengtha;
}
static u8 get_hex_digit(const u8 c)
{
u8 ret = 0;
@ -51,21 +78,78 @@ static u8 get_hex_digit(const u8 c)
ret = c - 'a' + 0x0a;
}
if (ret > 0x0f) {
printk(BIOS_DEBUG, "Error: Invalid hex digit found: "
"%c - 0x%02x\n", (char)c, c);
printk(BIOS_ERR, "Error: Invalid hex digit found: "
"%c - 0x%02x\n", (char)c, c);
ret = 0;
}
return ret;
}
#define MACLEN 17
static enum cb_err fetch_mac_string_vpd(u8 *macstrbuf)
{
struct region_device rdev;
void *search_address;
size_t search_length;
size_t offset;
char key[] = "ethernet_mac";
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(key, search_address, strlen(key),
search_length);
if (offset == search_length) {
printk(BIOS_ERR,
"Error: Could not locate '%s' in VPD\n", key);
return CB_ERR;
}
printk(BIOS_DEBUG, "Located '%s' in VPD\n", key);
offset += sizeof(key); /* 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)
{
struct cbfsf fh;
uint32_t matchraw = CBFS_TYPE_RAW;
if (!cbfs_boot_locate(&fh, "rt8168-macaddress", &matchraw)) {
/* check the cbfs for the mac address */
if (rdev_readat(&fh.data, macstrbuf, 0, MACLEN) != MACLEN) {
printk(BIOS_ERR, "r8168: Error reading MAC from CBFS\n");
return CB_ERR;
}
return CB_SUCCESS;
}
return CB_ERR;
}
static void get_mac_address(u8 *macaddr, const u8 *strbuf)
{
size_t offset = 0;
int i;
if ( (strbuf[2] != ':') || (strbuf[5] != ':') ||
(strbuf[8] != ':') || (strbuf[11] != ':') ||
(strbuf[14] != ':') ) {
if ((strbuf[2] != ':') || (strbuf[5] != ':') ||
(strbuf[8] != ':') || (strbuf[11] != ':') ||
(strbuf[14] != ':')) {
printk(BIOS_ERR, "r8168: ignore invalid MAC address in cbfs\n");
return;
}
@ -78,25 +162,24 @@ static void get_mac_address(u8 *macaddr, const u8 *strbuf)
}
}
#define MACLEN 17
static void program_mac_address(struct device *dev, u16 io_base)
{
struct cbfsf fh;
uint32_t matchraw = CBFS_TYPE_RAW;
u8 macstrbuf[MACLEN] = { 0 };
int i = 0;
/* Default MAC Address of 00:E0:4C:00:C0:B0 */
u8 mac[6] = { 0x00, 0xe0, 0x4c, 0x00, 0xc0, 0xb0 };
if (!cbfs_boot_locate(&fh, "rt8168-macaddress", &matchraw)) {
if (rdev_readat(&fh.data, macstrbuf, 0, MACLEN) == MACLEN)
get_mac_address(mac, macstrbuf);
else
printk(BIOS_ERR, "r8168: Error reading MAC from CBFS\n");
/* check the VPD for the mac address */
if (IS_ENABLED(CONFIG_RT8168_GET_MAC_FROM_VPD)) {
if (fetch_mac_string_vpd(macstrbuf) != 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: 'rt8168-macaddress' not found in CBFS,"
" using default 00:e0:4c:00:c0:b0\n");
if (fetch_mac_string_cbfs(macstrbuf) != CB_SUCCESS)
printk(BIOS_ERR, "r8168: Error reading MAC from CBFS,"
" using default 00:e0:4c:00:c0:b0\n");
}
get_mac_address(mac, macstrbuf);
/* Reset NIC */
printk(BIOS_DEBUG, "r8168: Resetting NIC...");
@ -106,7 +189,7 @@ static void program_mac_address(struct device *dev, u16 io_base)
while (i < NIC_TIMEOUT && (inb(io_base + CMD_REG) & CMD_REG_RESET)) {
udelay(1000);
if (++i >= NIC_TIMEOUT)
printk(BIOS_DEBUG, "timeout waiting for nic to reset\n");
printk(BIOS_ERR, "timeout waiting for nic to reset\n");
}
if (i < NIC_TIMEOUT)
printk(BIOS_DEBUG, "done\n");
@ -143,7 +226,7 @@ static void r8168_init(struct device *dev)
if (io_base)
program_mac_address(dev, io_base);
else
printk(BIOS_DEBUG, "r8168: Error cant find MMIO resource\n");
printk(BIOS_ERR, "r8168: Error cant find MMIO resource\n");
}
static struct device_operations r8168_ops = {