Vladimir Serbinenko (phcoder@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4770
-gerrit
commit 245043688edfab74c74462edb30975953e216376 Author: Vladimir Serbinenko phcoder@gmail.com Date: Tue Jan 21 11:19:45 2014 +0100
lenovo/x201 & x230: Read serial number, UUID and P/N from EEPROM.
This info is stored on AT24RF08 chip acessible through SMBUS.
Change-Id: I40b052f14fc733d4cc9b0c08bedc5597d8b474cb Signed-off-by: Vladimir Serbinenko phcoder@gmail.com --- src/mainboard/lenovo/x201/mainboard.c | 79 +++++++++++++++++++++++++++++++++++ src/mainboard/lenovo/x230/mainboard.c | 79 +++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+)
diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index 6321777..8a2d926 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 <southbridge/intel/bd82x6x/smbus.h>
#include <pc80/mc146818rtc.h> #include "dock.h" @@ -89,9 +90,87 @@ 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 smbus_read_string(u8 addr, u8 start, u8 len, char *result) +{ + int i; + + for (i = 0; i < len; i++) { + int t = do_smbus_read_byte(SMBUS_IO_BASE, 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 = do_smbus_read_byte(SMBUS_IO_BASE, 0x56, 0x12 + i); + if (t < 0) { + memset (result, 0, sizeof (result)); + break; + } + result[remap[i]] = t; + } + + already_read = 1; + + memcpy (uuid, result, 16); +} + static void mainboard_enable(device_t dev) { device_t dev0; diff --git a/src/mainboard/lenovo/x230/mainboard.c b/src/mainboard/lenovo/x230/mainboard.c index 91965b6..22afce4 100644 --- a/src/mainboard/lenovo/x230/mainboard.c +++ b/src/mainboard/lenovo/x230/mainboard.c @@ -34,6 +34,7 @@ #include <boot/coreboot_tables.h> #include "hda_verb.h" #include <southbridge/intel/bd82x6x/pch.h> +#include <southbridge/intel/bd82x6x/smbus.h> #include <smbios.h> #include <device/pci.h> #include <cbfs.h> @@ -132,9 +133,87 @@ 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"; }
+static void smbus_read_string(u8 addr, u8 start, u8 len, char *result) +{ + int i; + + for (i = 0; i < len; i++) { + int t = do_smbus_read_byte(SMBUS_IO_BASE, 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 = do_smbus_read_byte(SMBUS_IO_BASE, 0x56, 0x12 + i); + if (t < 0) { + memset (result, 0, sizeof (result)); + break; + } + result[remap[i]] = t; + } + + already_read = 1; + + memcpy (uuid, result, 16); +} + /* Audio Setup */
extern const u32 *cim_verb_data;