From: Patrick Rudolph <patrick.rudo...@9elements.com> Reads board specific configuration values from an EEPROM that is written to by the BMC.
Cc: Guo Dong <guo.d...@intel.com> Cc: Ray Ni <ray...@intel.com> Cc: Maurice Ma <maurice...@intel.com> Cc: Benjamin You <benjamin....@intel.com> Signed-off-by: Patrick Rudolph <patrick.rudo...@9elements.com> --- .../Include/Guid/BoardSettingsGuid.h | 36 +++ .../SmbusConfigLoaderDxe/SMBusConfigLoader.c | 269 ++++++++++++++++++ .../SmbusConfigLoaderDxe/SMBusConfigLoader.h | 23 ++ .../SMBusConfigLoader.inf | 54 ++++ UefiPayloadPkg/UefiPayloadPkg.dec | 1 + UefiPayloadPkg/UefiPayloadPkg.dsc | 1 + UefiPayloadPkg/UefiPayloadPkg.fdf | 11 +- 7 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 UefiPayloadPkg/Include/Guid/BoardSettingsGuid.h create mode 100644 UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.c create mode 100644 UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.h create mode 100644 UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf diff --git a/UefiPayloadPkg/Include/Guid/BoardSettingsGuid.h b/UefiPayloadPkg/Include/Guid/BoardSettingsGuid.h new file mode 100644 index 0000000000..415b49dcde --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/BoardSettingsGuid.h @@ -0,0 +1,36 @@ +/** @file + This file defines the hob structure for board settings + + Copyright (c) 2020, 9elements GmbH. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BOARD_SETTINGS_GUID_H__ +#define __BOARD_SETTINGS_GUID_H__ + +/// +/// Board information GUID +/// +extern EFI_GUID gEfiBoardSettingsVariableGuid; + +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT8 SecureBoot; + UINT8 PrimaryVideo; + UINT8 DeepSx; + UINT8 WakeOnUSB; + UINT8 USBPowerinS5; + UINT8 PowerStateAfterG3; + UINT8 BlueRearPort; + UINT8 InternalAudioConnection; + UINT8 PxeBootCapability; +} BOARD_SETTINGS; + +#pragma pack() + +#define BOARD_SETTINGS_NAME L"BoardSettings" + +#endif // __BOARD_SETTINGS_GUID_H__ diff --git a/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.c b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.c new file mode 100644 index 0000000000..c2edbaa74f --- /dev/null +++ b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.c @@ -0,0 +1,269 @@ +/** @file + Implementation for a generic i801 SMBus driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "SMBusConfigLoader.h" +#include <Library/SmbusLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/PciLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Guid/GlobalVariable.h> +#include <Guid/AuthenticatedVariableFormat.h> + +/** + GetPciConfigSpaceAddress + + Return the PCI Config Space Address if found, zero otherwise. + + @retval 0 Can not find any SMBusController + @retval UINT32 PCI Config Space Address +**/ +STATIC UINT32 +EFIAPI +GetPciConfigSpaceAddress ( + ) +{ + UINT8 Device; + UINT8 Function; + UINT8 BaseClass; + UINT8 SubClass; + + // + // Search for SMBus Controller within PCI Devices on root bus + // + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + for (Function = 0; Function <= PCI_MAX_FUNC; Function++) { + if (PciRead16 (PCI_LIB_ADDRESS (0, Device, Function, 0x00)) != 0x8086) { + continue; + } + + BaseClass = PciRead8 (PCI_LIB_ADDRESS (0, Device, Function, 0x0B)); + + if (BaseClass == PCI_CLASS_SERIAL) { + SubClass = PciRead8 (PCI_LIB_ADDRESS (0, Device, Function, 0xA)); + + if (SubClass == PCI_CLASS_SERIAL_SMB) { + return PCI_LIB_ADDRESS (0, Device, Function, 0x00); + } + } + } + } + + return 0; +} + +/** + ReadBoardOptionFromEEPROM + + Reads the Board options like Primary Video from the EEPROM + + @param Buffer Pointer to the Buffer Array + +**/ +STATIC +EFI_STATUS +EFIAPI +ReadBoardOptionFromEEPROM ( + IN OUT UINT8 *Buffer, + IN UINT32 Size + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 Value; + + for (Index = BOARD_SETTINGS_OFFSET; Index < BOARD_SETTINGS_OFFSET + Size; Index += 2) { + Value = SmBusProcessCall (SMBUS_LIB_ADDRESS (0x57, 0, 0, 0), ((Index & 0xff) << 8) | ((Index & 0xff00) >> 8), &Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to read SMBUS byte at offset 0x%x\n", Index)); + return Status; + } + + DEBUG ((EFI_D_ERROR, "Read %x\n", Value)); + CopyMem (&Buffer[Index-BOARD_SETTINGS_OFFSET], &Value, sizeof (Value)); + } + + return EFI_SUCCESS; +} + +STATIC +UINT32 +EFIAPI +crc32_byte ( + UINT32 prev_crc, + UINT8 data + ) +{ + prev_crc ^= (UINT32)data << 24; + + for (int i = 0; i < 8; i++) { + if ((prev_crc & 0x80000000UL) != 0) { + prev_crc = ((prev_crc << 1) ^ 0x04C11DB7UL); + } else { + prev_crc <<= 1; + } + } + + return prev_crc; +} + +/** + Computes and returns a 32-bit CRC for a data buffer. + CRC32 value bases on ITU-T V.42. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param[in] Buffer A pointer to the buffer on which the 32-bit CRC is to be computed. + @param[in] Length The number of bytes in the buffer Data. + + @retval Crc32 The 32-bit CRC was computed for the data buffer. + +**/ +STATIC +UINT32 +EFIAPI +CalculateCrc32 ( + IN VOID *Buffer, + IN UINTN Length + ) +{ + int i; + UINT32 crc = 0x0; + + for ( i = 0; i < Length; i++ ) { + crc = crc32_byte (crc, ((UINT8 *)Buffer)[i]); + } + + return crc; +} + +/** + The Entry Point for SMBUS driver. + + It installs DriverBinding. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InstallSMBusConfigLoader ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + BOARD_SETTINGS BoardSettings; + UINT32 BaseAddress; + UINT32 CRC32Array; + UINT32 HostCBackup; + UINT8 Array[sizeof (BOARD_SETTINGS)]; + + DEBUG ((DEBUG_INFO, "SMBusConfigLoader: InstallSMBusConfigLoader\n")); + + BaseAddress = GetPciConfigSpaceAddress (); + if (BaseAddress == 0) { + return EFI_NOT_FOUND; + } + + ZeroMem (&BoardSettings, sizeof (BOARD_SETTINGS)); + + // Set I2C_EN Bit + HostCBackup = PciRead32 (BaseAddress + HOSTC); + PciWrite32 (BaseAddress + HOSTC, HostCBackup | I2C_EN_HOSTC); + + Status = ReadBoardOptionFromEEPROM (Array, sizeof (Array)); + + CRC32Array = 0; + if (!EFI_ERROR (Status)) { + CopyMem (&BoardSettings, Array, sizeof (BOARD_SETTINGS)); + + DEBUG ((DEBUG_INFO, "SMBusConfigLoader: Board Settings:\n")); + DEBUG (( + DEBUG_INFO, + "SMBusConfigLoader: CRC: %08x - SecureBoot: %02x - PrimaryVideo: %02x\n", + BoardSettings.Signature, + BoardSettings.SecureBoot, + BoardSettings.PrimaryVideo + )); + + CRC32Array = CalculateCrc32 (&Array[sizeof (UINT32)], sizeof (BOARD_SETTINGS) - sizeof (UINT32)); + if (CRC32Array != BoardSettings.Signature) { + DEBUG ((DEBUG_ERROR, "SMBusConfigLoader: Checksum invalid. Should be %04X - is: %04x.\nReseting to defaults.\n", CRC32Array, BoardSettings.Signature)); + } + } + + if (EFI_ERROR (Status) || (CRC32Array != BoardSettings.Signature)) { + BoardSettings.PrimaryVideo = 0; + BoardSettings.SecureBoot = 1; + } + + // Set SecureBootEnable. Only affects SecureBootSetupDxe. + Status = gRT->SetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof BoardSettings.SecureBoot, + &BoardSettings.SecureBoot + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SMBusConfigLoader: Failed to set SecureBootEnable: %x\n", Status)); + } + + // Set SecureBoot. Only affects code outside of SecureBootSetupDxe. + Status = gRT->SetVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof BoardSettings.SecureBoot, + &BoardSettings.SecureBoot + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SMBusConfigLoader: Failed to set SecureBoot: %x\n", Status)); + } + + if (BoardSettings.SecureBoot == 0) { + UINT8 SetupMode; + // Hide the UI if secureboot is disabled + SetupMode = 1; + Status = gRT->SetVariable ( + EFI_SETUP_MODE_NAME, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof SetupMode, + &SetupMode + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SMBusConfigLoader: Failed to set SetupMode: %x\n", Status)); + } + } + + // Restore I2C_EN Bit + PciWrite32 (BaseAddress + HOSTC, HostCBackup); + + // Save data into UEFI Variable for later use + Status = gRT->SetVariable ( + BOARD_SETTINGS_NAME, // Variable Name + &gEfiBoardSettingsVariableGuid, // Variable Guid + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS), // Variable Attributes + sizeof (BOARD_SETTINGS), + &BoardSettings + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SMBusConfigLoader: Failed to save BoardSettings %x\n", Status)); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.h b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.h new file mode 100644 index 0000000000..5e589cefff --- /dev/null +++ b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.h @@ -0,0 +1,23 @@ +/** @file + Header file for a generic i801 SMBUS driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +#ifndef _PCI_PLATFORM_DXE_H_ +#define _PCI_PLATFORM_DXE_H_ +#include <PiDxe.h> + +#include <IndustryStandard/Pci.h> +#include <IndustryStandard/Pci22.h> +#include <Protocol/SmbusHc.h> +#include <Guid/BoardSettingsGuid.h> + +#define BOARD_SETTINGS_OFFSET 0x1f00 + +#define HOSTC 0x40 +#define I2C_EN_HOSTC (1 << 2) + +#endif diff --git a/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf new file mode 100644 index 0000000000..a2c2656a4d --- /dev/null +++ b/UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf @@ -0,0 +1,54 @@ +## @file +# This driver produces gEfiSmbusHcProtocolGuid protocol to load access SMBUS devices +# +# Copyright (c) 2020, 9elements Agency GmbH +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SMBusConfigLoader + FILE_GUID = FCBA64FC-BC6B-4B8B-A0E2-D1EC78B8C01A + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InstallSMBusConfigLoader + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + SMBusConfigLoader.h + SMBusConfigLoader.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + SecurityPkg/SecurityPkg.dec + +[Guids] + gEfiBoardSettingsVariableGuid + gEfiSecureBootEnableDisableGuid + gEfiGlobalVariableGuid + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + DevicePathLib + SmbusLib + UefiRuntimeServicesTableLib + PciLib + +[Depex] + gEfiSmbusHcProtocolGuid AND + gEfiVariableArchProtocolGuid + +[Protocols] + gEfiSmbusHcProtocolGuid ## CONSUMES + gEfiVariableArchProtocolGuid ## CONSUMES diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec index 551f0a4915..e902180349 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dec +++ b/UefiPayloadPkg/UefiPayloadPkg.dec @@ -19,6 +19,7 @@ [Guids] + gEfiBoardSettingsVariableGuid = { 0xae2029d1, 0x11f2, 0x483d, { 0xbf, 0xbc, 0xad, 0x63, 0x5d, 0xe3, 0x32, 0x26 }} # ae2029d1-11f2-483d-bfbc-ad635de33226 # ## Defines the token space for the UEFI Payload Package PCDs. # diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 54543b7623..9321fa958c 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -663,6 +663,7 @@ # SMBUS Support # UefiPayloadPkg/SmbusDxe/SMBusi801Dxe.inf + UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf # # Console Support diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index 8861d29162..b241613507 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -158,6 +158,12 @@ INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +# +# SMBUS Support +# +INF UefiPayloadPkg/SmbusDxe/SMBusi801Dxe.inf +INF UefiPayloadPkg/SmbusConfigLoaderDxe/SMBusConfigLoader.inf + # # PCI Support # @@ -178,11 +184,6 @@ INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf !endif INF MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf -# -# SMBUS Support -# -INF UefiPayloadPkg/SmbusDxe/SMBusi801Dxe.inf - # # Console Support # -- 2.32.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#86729): https://edk2.groups.io/g/devel/message/86729 Mute This Topic: https://groups.io/mt/89214990/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-