[coreboot-gerrit] Patch set updated for coreboot: a0d54f3 lenovo: Handle EEPROM/RFID chip.

Vladimir Serbinenko (phcoder@gmail.com) gerrit at coreboot.org
Wed Jan 22 18:37:11 CET 2014


Vladimir Serbinenko (phcoder at 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 at 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 at 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) {



More information about the coreboot-gerrit mailing list