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:
parent
5aa64b97db
commit
0528b6132e
|
@ -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
|
||||
|
|
|
@ -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: "
|
||||
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] != ':') ||
|
||||
if ((strbuf[2] != ':') || (strbuf[5] != ':') ||
|
||||
(strbuf[8] != ':') || (strbuf[11] != ':') ||
|
||||
(strbuf[14] != ':') ) {
|
||||
(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,"
|
||||
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 = {
|
||||
|
|
Loading…
Reference in New Issue