public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sean Rhodes" <sean@starlabs.systems>
To: devel@edk2.groups.io
Cc: guo.dong@intel.com,
	Patrick Rudolph <patrick.rudolph@9elements.com>,
	Ray Ni <ray.ni@intel.com>, Maurice Ma <maurice.ma@intel.com>,
	Benjamin You <benjamin.you@intel.com>
Subject: [PATCH 2/2] UefipayloadPkg: Add SmbusConfigLoaderDxe
Date: Thu, 17 Feb 2022 17:51:27 +0000	[thread overview]
Message-ID: <1a141c15226d8ffbecfcdbe5b51d34a1f4b8887d.1645120287.git.sean@starlabs.systems> (raw)
In-Reply-To: <c8070771e19c158e3512319a33ae68bf32beab36.1645120287.git.sean@starlabs.systems>

From: Patrick Rudolph <patrick.rudolph@9elements.com>

Reads board specific configuration values from an EEPROM that is written
to by the BMC.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Signed-off-by: Patrick Rudolph <patrick.rudolph@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


  reply	other threads:[~2022-02-17 17:51 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-17 17:51 [PATCH 1/2] UefiPayloadPkg: Add i801 SMBus controller DXE Sean Rhodes
2022-02-17 17:51 ` Sean Rhodes [this message]
2022-02-17 18:24 ` [edk2-devel] " Ma, Maurice
2022-02-24 10:46   ` Patrick Rudolph
2022-02-24 15:53     ` Guo Dong
2022-02-25  1:25       ` Guo Dong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1a141c15226d8ffbecfcdbe5b51d34a1f4b8887d.1645120287.git.sean@starlabs.systems \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox