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>
Reviewed-on: http://review.coreboot.org/4774
Tested-by: build bot (Jenkins)
Reviewed-by: Rudolf Marek <r.marek@assembler.cz>
This commit is contained in:
Vladimir Serbinenko 2014-01-23 09:06:08 +01:00 committed by Rudolf Marek
parent 5f20dbfbe3
commit 62adc4c610
8 changed files with 260 additions and 2 deletions

View File

@ -7,3 +7,4 @@ subdirs-y += lm63
subdirs-y += rtd2132 subdirs-y += rtd2132
subdirs-y += w83795 subdirs-y += w83795
subdirs-y += w83793 subdirs-y += w83793
subdirs-y += at24rf08c

View File

@ -0,0 +1,2 @@
ramstage-$(CONFIG_VENDOR_LENOVO) += at24rf08c.c
ramstage-$(CONFIG_VENDOR_LENOVO) += lenovo_serials.c

View File

@ -0,0 +1,74 @@
/*
* 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 <console/console.h>
static void at24rf08c_init(device_t dev)
{
int i, j;
if (!dev->enabled)
return;
/* Ensure that EEPROM/RFID chip is not accessible through RFID.
Need to do it only on 5c. */
if (dev->path.type != DEVICE_PATH_I2C || dev->path.i2c.device != 0x5c)
return;
printk (BIOS_DEBUG, "Locking EEPROM RFID\n");
for (i = 0; i < 8; i++)
{
/* After a register write AT24RF08C sometimes stops responding.
Retry several times in case of failure.
*/
for (j = 0; j < 100; j++)
if (smbus_write_byte(dev, i, 0x0f) >= 0)
break;
}
printk (BIOS_DEBUG, "init EEPROM done\n");
}
static void at24rf08c_noop(device_t dummy)
{
}
static struct device_operations at24rf08c_operations = {
.read_resources = at24rf08c_noop,
.set_resources = at24rf08c_noop,
.enable_resources = at24rf08c_noop,
.init = at24rf08c_init,
};
static void enable_dev(device_t dev)
{
dev->ops = &at24rf08c_operations;
}
struct chip_operations drivers_i2c_at24rf08c_ops = {
CHIP_NAME("AT24RF08C")
.enable_dev = enable_dev,
};

View File

@ -0,0 +1,137 @@
/*
* 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 <console/console.h>
static void at24rf08c_read_string(u8 bank, u8 start, u8 len, char *result)
{
int i;
device_t dev;
dev = dev_find_slot_on_smbus(1, 0x54 | bank);
if (dev == 0) {
printk(BIOS_WARNING, "EEPROM not found\n");
memcpy(result, "*INVALID*", sizeof ("*INVALID*"));
return;
}
for (i = 0; i < len; i++) {
int t;
int j;
/* After a register write AT24RF08C (which we issued in init function) sometimes stops responding.
Retry several times in case of failure.
*/
for (j = 0; j < 100; j++) {
t = smbus_read_byte(dev, start + i);
if (t >= 0)
break;
}
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));
at24rf08c_read_string(0, 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));
at24rf08c_read_string(0, 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;
device_t dev;
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));
dev = dev_find_slot_on_smbus(1, 0x56);
if (dev == 0) {
printk(BIOS_WARNING, "eeprom not found\n");
already_read = 1;
memset (uuid, 0, 16);
return;
}
for (i = 0; i < 16; i++) {
int t;
int j;
/* After a register write AT24RF08C (which we issued in init function) sometimes stops responding.
Retry several times in case of failure.
*/
for (j = 0; j < 100; j++) {
t = smbus_read_byte(dev, 0x12 + i);
if (t >= 0)
break;
}
if (t < 0) {
memset (result, 0, sizeof (result));
break;
}
result[remap[i]] = t;
}
already_read = 1;
memcpy (uuid, result, 16);
}

View File

@ -213,6 +213,17 @@ chip northbridge/intel/i945
register "reg11" = "0x07" register "reg11" = "0x07"
device i2c 69 on end device i2c 69 on end
end end
# eeprom, 8 virtual devices, same chip
chip drivers/i2c/at24rf08c
device i2c 54 on end
device i2c 55 on end
device i2c 56 on end
device i2c 57 on end
device i2c 5c on end
device i2c 5d on end
device i2c 5e on end
device i2c 5f on end
end
end end
end end
end end

View File

@ -145,6 +145,17 @@ chip northbridge/intel/nehalem
end end
device pci 1f.3 on # SMBUS device pci 1f.3 on # SMBUS
subsystemid 0x17aa 0x2167 subsystemid 0x17aa 0x2167
# eeprom, 8 virtual devices, same chip
chip drivers/i2c/at24rf08c
device i2c 54 on end
device i2c 55 on end
device i2c 56 on end
device i2c 57 on end
device i2c 5c on end
device i2c 5d on end
device i2c 5e on end
device i2c 5f on end
end
end end
end end
end end

View File

@ -127,7 +127,19 @@ chip northbridge/intel/sandybridge
end end
end # LPC bridge end # LPC bridge
device pci 1f.2 on end # SATA Controller 1 device pci 1f.2 on end # SATA Controller 1
device pci 1f.3 on end # SMBus device pci 1f.3 on
# eeprom, 8 virtual devices, same chip
chip drivers/i2c/at24rf08c
device i2c 54 on end
device i2c 55 on end
device i2c 56 on end
device i2c 57 on end
device i2c 5c on end
device i2c 5d on end
device i2c 5e on end
device i2c 5f on end
end
end # SMBus
device pci 1f.5 off end # SATA Controller 2 device pci 1f.5 off end # SATA Controller 2
device pci 1f.6 on end # Thermal device pci 1f.6 on end # Thermal
end end

View File

@ -190,7 +190,17 @@ chip northbridge/intel/i945
register "reg11" = "0x07" register "reg11" = "0x07"
device i2c 69 on end device i2c 69 on end
end end
# eeprom, 8 virtual devices, same chip
chip drivers/i2c/at24rf08c
device i2c 54 on end
device i2c 55 on end
device i2c 56 on end
device i2c 57 on end
device i2c 5c on end
device i2c 5d on end
device i2c 5e on end
device i2c 5f on end
end
end end
end end
chip southbridge/ricoh/rl5c476 chip southbridge/ricoh/rl5c476