Vladimir Serbinenko (phcoder@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4774
-gerrit
commit a0d54f382ef65a48850651a3212fba4c6003674e Author: Vladimir Serbinenko phcoder@gmail.com Date: Tue Jan 21 11:19:45 2014 +0100
lenovo: Handle EEPROM/RFID chip.
EEPROM/RFID chip present in thinkpad should be locked in a way to avoid any potential RFID access.
Read serial number, UUID and P/N from EEPROM.
This info is stored on AT24RF08 chip acessible through SMBUS.
Change-Id: Ia3e766d90a094f63c8c854cd37e165221ccd8acd Signed-off-by: Vladimir Serbinenko phcoder@gmail.com --- src/drivers/i2c/Makefile.inc | 1 + src/drivers/i2c/lenovo/Makefile.inc | 1 + src/drivers/i2c/lenovo/eeprom.c | 110 ++++++++++++++++++++++++++++++++++ src/drivers/i2c/lenovo/eeprom.h | 6 ++ src/mainboard/lenovo/t60/mainboard.c | 8 +++ src/mainboard/lenovo/x201/mainboard.c | 26 +++++--- src/mainboard/lenovo/x230/mainboard.c | 5 ++ src/mainboard/lenovo/x60/mainboard.c | 4 ++ 8 files changed, 153 insertions(+), 8 deletions(-)
diff --git a/src/drivers/i2c/Makefile.inc b/src/drivers/i2c/Makefile.inc index ef7ac4b..2cd1db0 100644 --- a/src/drivers/i2c/Makefile.inc +++ b/src/drivers/i2c/Makefile.inc @@ -7,3 +7,4 @@ subdirs-y += lm63 subdirs-y += rtd2132 subdirs-y += w83795 subdirs-y += w83793 +subdirs-y += lenovo diff --git a/src/drivers/i2c/lenovo/Makefile.inc b/src/drivers/i2c/lenovo/Makefile.inc new file mode 100644 index 0000000..87f0dbf --- /dev/null +++ b/src/drivers/i2c/lenovo/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_VENDOR_LENOVO) += eeprom.c diff --git a/src/drivers/i2c/lenovo/eeprom.c b/src/drivers/i2c/lenovo/eeprom.c new file mode 100644 index 0000000..df7cf5f --- /dev/null +++ b/src/drivers/i2c/lenovo/eeprom.c @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Vladimir Serbinenko + * + * 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 <types.h> +#include <string.h> +#include <arch/io.h> +#include <device/device.h> +#include <device/smbus.h> +#include <smbios.h> +#include "eeprom.h" + +static void smbus_read_string(u8 addr, u8 start, u8 len, char *result) +{ + int i; + + for (i = 0; i < len; i++) { + int t = smbus_read_byte_main_bus(addr, start + i); + if (t < 0x20 || t > 0x7f) { + memcpy(result, "*INVALID*", sizeof ("*INVALID*")); + return; + } + result[i] = t; + } +} + +const char *smbios_mainboard_serial_number(void) +{ + static char result[12]; + static int already_read; + + if (already_read) + return result; + + memset(result, 0, sizeof (result)); + + smbus_read_string(0x54, 0x2e, 7, result); + already_read = 1; + return result; +} + +const char *smbios_mainboard_product_name(void) +{ + static char result[12]; + static int already_read; + + if (already_read) + return result; + memset (result, 0, sizeof (result)); + + smbus_read_string(0x54, 0x27, 7, result); + + already_read = 1; + return result; +} + +void smbios_mainboard_set_uuid(u8 *uuid) +{ + static char result[16]; + unsigned i; + static int already_read; + const int remap[16] = { + /* UUID byteswap. */ + 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 + }; + + + if (already_read) { + memcpy (uuid, result, 16); + return; + } + + memset (result, 0, sizeof (result)); + + for (i = 0; i < 16; i++) { + int t = smbus_read_byte_main_bus(0x56, 0x12 + i); + if (t < 0) { + memset (result, 0, sizeof (result)); + break; + } + result[remap[i]] = t; + } + + already_read = 1; + + memcpy (uuid, result, 16); +} + +/* Ensure that EEPROM/RFID chip is not accessible through RFID. */ +void lenovo_eeprom_lock(void) +{ + int i; + for (i = 0; i < 8; i++) + smbus_write_byte_main_bus(0x5c, i, 0x0f); +} diff --git a/src/drivers/i2c/lenovo/eeprom.h b/src/drivers/i2c/lenovo/eeprom.h new file mode 100644 index 0000000..7fabac0 --- /dev/null +++ b/src/drivers/i2c/lenovo/eeprom.h @@ -0,0 +1,6 @@ +#ifndef LENOVO_EEPROM_H +#define LENOVO_EEPROM_H + +void lenovo_eeprom_lock(void); + +#endif diff --git a/src/mainboard/lenovo/t60/mainboard.c b/src/mainboard/lenovo/t60/mainboard.c index 52f5dcf..070e78d 100644 --- a/src/mainboard/lenovo/t60/mainboard.c +++ b/src/mainboard/lenovo/t60/mainboard.c @@ -33,6 +33,7 @@ #include <northbridge/intel/i945/i945.h> #include <pc80/mc146818rtc.h> #include <arch/x86/include/arch/acpigen.h> +#include "drivers/i2c/lenovo/eeprom.h"
static acpi_cstate_t cst_entries[] = { { 1, 1, 1000, { 0x7f, 1, 2, { 0 }, 1, 0 } }, @@ -46,12 +47,19 @@ int get_cst_entries(acpi_cstate_t **entries) return ARRAY_SIZE(cst_entries); }
+static void mainboard_init(device_t dev) +{ + lenovo_eeprom_lock(); +} + static void mainboard_enable(device_t dev) { struct southbridge_intel_i82801gx_config *config; device_t dev0, idedev; u8 defaults_loaded = 0;
+ dev->ops->init = mainboard_init; + /* If we're resuming from suspend, blink suspend LED */ dev0 = dev_find_slot(0, PCI_DEVFN(0,0)); if (dev0 && pci_read_config32(dev0, SKPAD) == SKPAD_ACPI_S3_MAGIC) diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index 6321777..c023251 100644 --- a/src/mainboard/lenovo/x201/mainboard.c +++ b/src/mainboard/lenovo/x201/mainboard.c @@ -34,6 +34,7 @@ #include <ec/lenovo/h8/h8.h> #include <northbridge/intel/nehalem/nehalem.h> #include <southbridge/intel/bd82x6x/pch.h> +#include <string.h>
#include <pc80/mc146818rtc.h> #include "dock.h" @@ -46,6 +47,7 @@ #include <cpu/x86/lapic.h> #include <device/pci.h> #include <smbios.h> +#include "drivers/i2c/lenovo/eeprom.h"
static acpi_cstate_t cst_entries[] = { {1, 1, 1000, {0x7f, 1, 2, {0}, 1, 0}}, @@ -89,13 +91,14 @@ static int int15_handler(void)
const char *smbios_mainboard_version(void) { + /* Is available from SMBUS as well but why read it if we know + what we'll find? */ return "Lenovo X201"; }
-static void mainboard_enable(device_t dev) +static void mainboard_init(device_t dev) { - device_t dev0; - u16 pmbase; + lenovo_eeprom_lock();
printk(BIOS_SPEW, "starting SPI configuration\n");
@@ -122,6 +125,18 @@ static void mainboard_enable(device_t dev) RCBA32(0x3804) = 0x3f04e008;
printk(BIOS_SPEW, "SPI configured\n"); + /* This sneaked in here, because X201 SuperIO chip isn't really + connected to anything and hence we don't init it. + */ + pc_keyboard_init(0); +} + +static void mainboard_enable(device_t dev) +{ + device_t dev0; + u16 pmbase; + + dev->ops->init = mainboard_init;
pmbase = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), PMBASE) & 0xff80; @@ -145,11 +160,6 @@ static void mainboard_enable(device_t dev) /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif - - /* This sneaked in here, because X201 SuperIO chip isn't really - connected to anything and hence we don't init it. - */ - pc_keyboard_init(0); }
struct chip_operations mainboard_ops = { diff --git a/src/mainboard/lenovo/x230/mainboard.c b/src/mainboard/lenovo/x230/mainboard.c index 91965b6..d32a75d 100644 --- a/src/mainboard/lenovo/x230/mainboard.c +++ b/src/mainboard/lenovo/x230/mainboard.c @@ -38,6 +38,7 @@ #include <device/pci.h> #include <cbfs.h> #include <pc80/keyboard.h> +#include "drivers/i2c/lenovo/eeprom.h"
void mainboard_suspend_resume(void) { @@ -132,6 +133,8 @@ static int int15_handler(void)
const char *smbios_mainboard_version(void) { + /* Is available from SMBUS as well but why read it if we know + what we'll find? */ return "ThinkPad X230"; }
@@ -153,6 +156,8 @@ static void verb_setup(void)
static void mainboard_init(device_t dev) { + lenovo_eeprom_lock(); + RCBA32(0x38c8) = 0x00002005; RCBA32(0x38c4) = 0x00802005; RCBA32(0x38c0) = 0x00000007; diff --git a/src/mainboard/lenovo/x60/mainboard.c b/src/mainboard/lenovo/x60/mainboard.c index d1fcb7b..0342580 100644 --- a/src/mainboard/lenovo/x60/mainboard.c +++ b/src/mainboard/lenovo/x60/mainboard.c @@ -38,6 +38,8 @@ #include <arch/x86/include/arch/acpigen.h> #include <smbios.h> #include <x86emu/x86emu.h> +#include "drivers/i2c/lenovo/eeprom.h" + #define PANEL INT15_5F35_CL_DISPLAY_DEFAULT
int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio, @@ -90,6 +92,8 @@ static void mainboard_init(device_t dev) { device_t dev0, idedev, sdhci_dev;
+ lenovo_eeprom_lock(); + ec_clr_bit(0x03, 2);
if (inb(0x164c) & 0x08) {