Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/36298 )
Change subject: drivers/secunet: Add driver to read DMI info from I2C EEPROM ......................................................................
drivers/secunet: Add driver to read DMI info from I2C EEPROM
The EEPROM layout is rather arbitrary and /just happened/. It needs a 256kbit part at least.
Change-Id: Iae5c9138e8404acfc3a43dc2c7b55d47d4147060 Signed-off-by: Nico Huber nico.huber@secunet.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/36298 Reviewed-by: Patrick Georgi pgeorgi@google.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- A src/drivers/secunet/dmi/Kconfig A src/drivers/secunet/dmi/Makefile.inc A src/drivers/secunet/dmi/eeprom.h A src/drivers/secunet/dmi/smbios.c 4 files changed, 175 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Patrick Georgi: Looks good to me, approved
diff --git a/src/drivers/secunet/dmi/Kconfig b/src/drivers/secunet/dmi/Kconfig new file mode 100644 index 0000000..7e83f90 --- /dev/null +++ b/src/drivers/secunet/dmi/Kconfig @@ -0,0 +1,3 @@ +config SECUNET_DMI + bool + select SMBIOS_PROVIDED_BY_MOBO diff --git a/src/drivers/secunet/dmi/Makefile.inc b/src/drivers/secunet/dmi/Makefile.inc new file mode 100644 index 0000000..9c85485 --- /dev/null +++ b/src/drivers/secunet/dmi/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_SECUNET_DMI) += smbios.c diff --git a/src/drivers/secunet/dmi/eeprom.h b/src/drivers/secunet/dmi/eeprom.h new file mode 100644 index 0000000..c4cdd41 --- /dev/null +++ b/src/drivers/secunet/dmi/eeprom.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef _SECUNET_DMI_EEPROM_H +#define _SECUNET_DMI_EEPROM_H + +#include <stdint.h> + +enum bx26_strings { + BOARD_MATNR, + BOARD_SERIAL_NUMBER, + BOARD_VERSION, + BOARD_MCTRL_FW_VERSION, + BOARD_CCR_FW_VERSION, + BOARD_NIC_FW_VERSION, + BOARD_LP_VERSION, + BOARD_VERSION_ID, + + SYSTEM_PRODUCT_NAME, + SYSTEM_VERSION, + SYSTEM_SERIAL_NUMBER, + SYSTEM_UUID, + SYSTEM_MANUFACTURER, + SYSTEM_PRODUCTION_DATE, + SYSTEM_MLFB, + SYSTEM_MATNR, +}; + +struct bx26_location { + uint16_t offset; + uint16_t length; +}; + +static const struct bx26_location bx26_locations[] = { + [BOARD_MATNR] = { 0x0000, 0x20 }, + [BOARD_SERIAL_NUMBER] = { 0x0020, 0x20 }, + [BOARD_VERSION] = { 0x0040, 0x20 }, + [BOARD_MCTRL_FW_VERSION] = { 0x0060, 0x20 }, + [BOARD_CCR_FW_VERSION] = { 0x0080, 0x20 }, + [BOARD_NIC_FW_VERSION] = { 0x00a0, 0x20 }, + [BOARD_LP_VERSION] = { 0x00c0, 0x20 }, + [BOARD_VERSION_ID] = { 0x0100, 0x20 }, + + [SYSTEM_PRODUCT_NAME] = { 0x4000, 0x20 }, + [SYSTEM_VERSION] = { 0x4040, 0x10 }, + [SYSTEM_SERIAL_NUMBER] = { 0x4060, 0x10 }, + [SYSTEM_UUID] = { 0x4080, 0x24 }, + [SYSTEM_MANUFACTURER] = { 0x40c0, 0x20 }, + [SYSTEM_PRODUCTION_DATE] = { 0x4100, 0x20 }, + [SYSTEM_MLFB] = { 0x4140, 0x20 }, + [SYSTEM_MATNR] = { 0x4180, 0x20 }, +}; + +#endif diff --git a/src/drivers/secunet/dmi/smbios.c b/src/drivers/secunet/dmi/smbios.c new file mode 100644 index 0000000..5dfbb5d --- /dev/null +++ b/src/drivers/secunet/dmi/smbios.c @@ -0,0 +1,109 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 secunet Security Networks AG + * + * 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. + */ + +#include <stdint.h> +#include <string.h> +#include <ctype.h> +#include <commonlib/helpers.h> +#include <uuid.h> +#include <console/console.h> +#include <device/device.h> +#include <device/i2c_bus.h> +#include <smbios.h> + +#include "eeprom.h" + +#define MAX_STRING_LENGTH UUID_STRLEN + +static struct device *eeprom; + +static const char *eeprom_read_string(const enum bx26_strings idx) +{ + static char str[MAX_STRING_LENGTH + 1]; + + if (!eeprom) { + printk(BIOS_WARNING, "DMI: Serial EEPROM not found\n"); + str[0] = '\0'; + return str; + } + + const size_t offset = bx26_locations[idx].offset; + const size_t length = MIN(bx26_locations[idx].length, MAX_STRING_LENGTH); + + if (i2c_dev_read_at16(eeprom, (u8 *)str, length, offset) != length) { + printk(BIOS_WARNING, "DMI: Failed to read serial EEPROM\n"); + str[0] = '\0'; + } else { + unsigned int i; + /* Terminate at first non-printable character. */ + for (i = 0; i < length; ++i) { + if (!isprint(str[i])) + break; + } + str[i] = '\0'; + } + + return str; +} + +const char *smbios_system_manufacturer(void) +{ + return eeprom_read_string(SYSTEM_MANUFACTURER); +} + +const char *smbios_system_product_name(void) +{ + return eeprom_read_string(SYSTEM_PRODUCT_NAME); +} + +const char *smbios_system_serial_number(void) +{ + return eeprom_read_string(SYSTEM_SERIAL_NUMBER); +} + +const char *smbios_system_version(void) +{ + return eeprom_read_string(SYSTEM_VERSION); +} + +void smbios_system_set_uuid(u8 *const uuid) +{ + if (parse_uuid(uuid, eeprom_read_string(SYSTEM_UUID))) { + printk(BIOS_WARNING, "DMI: Cannot parse UUID\n"); + memset(uuid, 0x00, UUID_LEN); + } +} + +const char *smbios_mainboard_serial_number(void) +{ + return eeprom_read_string(BOARD_SERIAL_NUMBER); +} + +const char *smbios_mainboard_version(void) +{ + return eeprom_read_string(BOARD_VERSION); +} + +static void enable_dev(struct device *dev) +{ + if (dev->path.type != DEVICE_PATH_I2C || (dev->path.i2c.device & 0xf0) != 0x50) + return; + eeprom = dev; +} + +struct chip_operations drivers_secunet_dmi_ops = { + CHIP_NAME("secunet DMI") + .enable_dev = enable_dev, +};