Adds SMBIOS common driver which generates various tables for AMD platforms.
Cc: Paul Grimes <paul.gri...@amd.com> Reviewed-by: Abner Chang <abner.ch...@amd.com> Signed-off-by: Abdul Lateef Attar <abdullateef.at...@amd.com> --- .../AMD/AmdPlatformPkg/AmdPlatformPkg.dec | 61 +++++ .../AMD/AmdPlatformPkg/AmdPlatformPkg.dsc | 3 +- .../SmbiosCommonDxe/DefaultLomDevicePath.c | 130 ++++++++++ .../Universal/SmbiosCommonDxe/SmbiosCommon.h | 210 ++++++++++++++++ .../SmbiosCommonDxe/SmbiosCommonDxe.inf | 76 ++++++ .../SmbiosCommonDxe/SmbiosCommonEntryPoint.c | 148 +++++++++++ .../Type11OemStringsFunction.c | 91 +++++++ .../Type12SystemCfgOptionsFunction.c | 90 +++++++ .../Type13BiosLanguageInfoFunction.c | 146 +++++++++++ .../Type38IpmiDeviceInformation.c | 70 ++++++ .../Type41OnboardDevExtInfoFunction.c | 237 ++++++++++++++++++ .../Type8PortConnectorInfoFunction.c | 133 ++++++++++ .../Type9SystemSlotInfoFunction.c | 94 +++++++ 13 files changed, 1488 insertions(+), 1 deletion(-) create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/DefaultLomDevicePath.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommon.h create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonDxe.inf create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonEntryPoint.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type11OemStringsFunction.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type12SystemCfgOptionsFunction.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type13BiosLanguageInfoFunction.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type38IpmiDeviceInformation.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type41OnboardDevExtInfoFunction.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type8PortConnectorInfoFunction.c create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type9SystemSlotInfoFunction.c diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec index 83f57f6d0a..106820dc85 100644 --- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec +++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec @@ -42,3 +42,64 @@ # 3 - BT # 4 - SSIF gAmdPlatformPkgTokenSpaceGuid.PcdIpmiInterfaceType|0|UINT8|0x00020001 + + # + # This PCD is mapped to AMD SMBIOS type 8 record structure + # + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType8Number|0|UINT8|0x00020002 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType8|{0x0}|SMBIOS_PORT_CONNECTOR_RECORD_ARRAY|0x00020003 { + <HeaderFiles> + Pcd/SmbiosPcd.h + <Packages> + AmdPlatformPkg/AmdPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + } + + # + # This PCD is mapped to AMD SMBIOS type 41 record structure + # + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType41Number|0|UINT8|0x00020004 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType41|{0x0}|SMBIOS_ONBOARD_DEV_EXT_INFO_ARRAY|0x00020005 { + <HeaderFiles> + Pcd/SmbiosPcd.h + <Packages> + AmdPlatformPkg/AmdPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + } + + # + # These PCDs are mapped to AMD SMBIOS type 9 record structure + # + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1|{0x0}|MISC_SLOT_CHARACTERISTICS1|0x00020009 { + <HeaderFiles> + IndustryStandard/SmBios.h + } + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.CharacteristicsUnknown|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.Provides50Volts|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.Provides33Volts|1 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.SharedSlot|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.PcCard16Supported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.CardBusSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.ZoomVideoSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1.ModemRingResumeSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2|{0x0}|MISC_SLOT_CHARACTERISTICS2|0x0002000A { + <HeaderFiles> + IndustryStandard/SmBios.h + } + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.PmeSignalSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.HotPlugDevicesSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.SmbusSignalSupported|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.BifurcationSupported|1 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.AsyncSurpriseRemoval|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.FlexbusSlotCxl10Capable|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.FlexbusSlotCxl20Capable|0 + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2.Reserved|0 + +[PcdsDynamic, PcdsDynamicEx] + # SMBIOS + gAmdPlatformPkgTokenSpaceGuid.PcdType11OemStringsCount|0|UINT8|0x00030001 + gAmdPlatformPkgTokenSpaceGuid.PcdType11OemStrings|NULL|VOID*|0x00030002 + gAmdPlatformPkgTokenSpaceGuid.PcdType12SystemCfgOptionsCount|0|UINT8|0x00030003 + gAmdPlatformPkgTokenSpaceGuid.PcdType12SystemCfgOptions|NULL|VOID*|0x00030004 diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc index 99dd5b341f..d11d3594e3 100644 --- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc +++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc @@ -71,4 +71,5 @@ AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf AmdPlatformPkg/Universal/LogoDxe/JpegLogoDxe.inf # Server platform JPEG logo driver AmdPlatformPkg/Universal/LogoDxe/LogoDxe.inf # Server platfrom Bitmap logo driver - AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf \ No newline at end of file + AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf + AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonDxe.inf diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/DefaultLomDevicePath.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/DefaultLomDevicePath.c new file mode 100644 index 0000000000..92c7aa5e07 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/DefaultLomDevicePath.c @@ -0,0 +1,130 @@ +/** @file + This file contains the implementation of the DefaultLomDevicePath protocol. + The DefaultLomDevicePath protocol is used to identify the default LOM device + path for the system. The protocol is installed by the SmbiosCommonDxe driver + and is used by the BDS to identify the default LOM device path for the system. + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <Library/IoLib.h> +#include <Library/PciLib.h> +#include <Protocol/PciEnumerationComplete.h> +#include <IndustryStandard/Ipmi.h> +#include <Bus/Pci/PciBusDxe/PciBus.h> +#include <Pcd/SmbiosPcd.h> +#include <Library/PciSegmentLib.h> +#include <Pcd/SmbiosPcd.h> +#include "SmbiosCommon.h" +#include <IndustryStandard/Ipmi.h> +#include <Library/BoardBdsHookLib.h> + +EFI_HANDLE mBoardBdsHandle = NULL; +BOARD_BDS_BOOT_FROM_DEVICE_PATH_PROTOCOL mBootDevicePathProtocol; + +/** + Find the Lan-On-Motherboard device path. Installs BOARD_BDS_BOOT_FROM_DEVICE_PATH_PROTOCOL + with the LOM device path protocol + + @retval EFI NOT_FOUND LOM device path is not found + @retval EFI_SUCCESS LOM device path found +**/ +EFI_STATUS +EFIAPI +InstallLomDevicePath ( + ) +{ + SMBIOS_ONBOARD_DEV_EXT_INFO_RECORD *DevExtInfoRecord; + EFI_STATUS Status; + EFI_HANDLE *PciHandles; + UINTN PciHandlesSize; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciProtocol; + PCI_IO_DEVICE *PciIoDevice; + UINT8 NumberOfDevices; + UINT8 DevIdx; + UINTN SegmentNumber; + UINTN BusNumber; + UINTN DeviceNumber; + UINTN FunctionNumber; + + NumberOfDevices = PcdGet8 (PcdAmdSmbiosType41Number); + DevExtInfoRecord = (SMBIOS_ONBOARD_DEV_EXT_INFO_RECORD *)PcdGetPtr (PcdAmdSmbiosType41); + + // No device entries found + if (NumberOfDevices == 0) { + DEBUG ((DEBUG_INFO, "No onboard devices found.\n")); + return EFI_NOT_FOUND; + } + + // search through present on board devices, look for onboard ethernet + for (DevIdx = 0; DevIdx < NumberOfDevices; DevIdx++) { + if (AsciiStrCmp (DevExtInfoRecord->RefDesignationStr, "Onboard Ethernet") == 0) { + break; + } + + DevExtInfoRecord++; + } + + // edge case, no Onboard Ethernet designator + if (AsciiStrCmp (DevExtInfoRecord->RefDesignationStr, "Onboard Ethernet") != 0) { + DEBUG ((DEBUG_INFO, "No Onboard ethernet SMBIOS designator found!\n")); + return EFI_NOT_FOUND; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &PciHandlesSize, + &PciHandles + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Can't locate gEfiPciIoProtocolGuid Protocol: Status = %r\n\n", Status)); + return Status; + } + + for (Index = 0; Index < PciHandlesSize; Index++) { + Status = gBS->HandleProtocol ( + PciHandles[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "ERROR - Status = %r when locating PciIoProtocol\n", Status)); + continue; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciProtocol); + Status = PciIoDevice->PciIo.GetLocation (&PciIoDevice->PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber); + + if ((PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegmentNumber, BusNumber, DeviceNumber, FunctionNumber, 2)) == DevExtInfoRecord->DeviceId) && + (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegmentNumber, BusNumber, DeviceNumber, FunctionNumber, 0)) == DevExtInfoRecord->VendorId)) + { + // Making Lan0 default for systems with two LANs + if (FunctionNumber == 0) { + DEBUG ((DEBUG_INFO, "Found Onboard Device with DeviceID=0x%X, VendorID=0x%X\n", DevExtInfoRecord->DeviceId, DevExtInfoRecord->VendorId)); + Status = EFI_SUCCESS; + // install device path protocol here + mBootDevicePathProtocol.Device = PciIoDevice->DevicePath; + mBootDevicePathProtocol.IpmiBootDeviceSelectorType = IPMI_BOOT_DEVICE_SELECTOR_PXE; + Status = gBS->InstallProtocolInterface ( + &mBoardBdsHandle, + &gBoardBdsBootFromDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + &mBootDevicePathProtocol + ); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "BoardBdsBootFromDevicePathProtocol installed successfully\n")); + } + + break; + } + } + } + + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommon.h b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommon.h new file mode 100644 index 0000000000..770053e42b --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommon.h @@ -0,0 +1,210 @@ +/** @file + AMD Smbios common header file. + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMBIOS_COMMON_DRIVER_H_ +#define SMBIOS_COMMON_DRIVER_H_ + +#include <PiDxe.h> +#include <Protocol/Smbios.h> +#include <IndustryStandard/SmBios.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/PciSegmentLib.h> + +/** + Add an SMBIOS record. + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + @param[out] SmbiosHandle A unique handle will be assigned to the SMBIOS record. + @param[in] Record The data for the fixed portion of the SMBIOS record. The format of the record is + determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined + by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or + a set of null terminated strings and a null. + + @retval EFI_SUCCESS Record was added. + @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources. + +**/ +EFI_STATUS +AddCommonSmbiosRecord ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + OUT EFI_SMBIOS_HANDLE *SmbiosHandle, + IN EFI_SMBIOS_TABLE_HEADER *Record + ); + +/** + This function gets the Bus, Device and Segment number of a PCI device when Vendor ID, Device ID and instance + are provided. + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + @param[in] VendorId Vendor ID of the PCI device to be provided. + @param[in] DeviceId Device ID of the PCI device to be provided + @param[out] Instance Instance of the PCI device. If more than one devices with same vendor + and device ID is present, instance number is used. + @param[out] Segment Segment number of the PCI device is assigned. + @param[out] Bus Bus number of the PCI device is assigned. + @param[out] Device Device number of the PCI device is assigned. + @param[out] Functions Bits 0-7 of the Functions variable correspond to respective function numbers. + @param[out] DeviceFound Set to 1 if the device is found. + + @retval EFI_SUCCESS All parameters were valid. +**/ +EFI_STATUS +EFIAPI +GetBusDeviceInfo ( + IN UINT16 *VendorId, + IN UINT16 *DeviceId, + IN UINT8 *Instance, + OUT UINT16 *Segment, + OUT UINT8 *Bus, + OUT UINT8 *Device, + OUT UINT8 *Functions, + OUT UINT8 *DeviceFound + ); + +/** + PciEnumerationComplete Protocol notification event handler. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +OnPciEnumerationComplete ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + This function updates IPMI Device information changes to the contents of the + Table Type 38. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. +**/ +EFI_STATUS +EFIAPI +IpmiDeviceInformation ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function checks for system slot info and adds smbios record (Type 9). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. + +**/ +EFI_STATUS +EFIAPI +SystemSlotInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function adds port connector information smbios record (Type 8). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +PortConnectorInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function adds OEM strings smbios record (Type 11). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +OemStringsFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function adds System Configuration Options record (Type 12). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +SystemCfgOptionsFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function adds bios language information smbios record (Type 13). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. + @retval EFI_NOT_FOUND Not able to locate PlatformLanguage. + +**/ +EFI_STATUS +EFIAPI +BiosLanguageInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + This function adds onboard devices extended information smbios record (Type 41). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +OnboardDevExtInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +/** + Find the Lan-On-Motherboard device path. Installs BOARD_BDS_BOOT_FROM_DEVICE_PATH_PROTOCOL + with the LOM device path protocol + + @retval EFI NOT_FOUND LOM device path is not found + @retval EFI_SUCCESS LOM device path found +**/ +EFI_STATUS +EFIAPI +InstallLomDevicePath ( + ); + +typedef +EFI_STATUS +(EFIAPI EFI_COMMON_SMBIOS_DATA_FUNCTION)( + IN EFI_SMBIOS_PROTOCOL *Smbios + ); + +typedef struct { + EFI_COMMON_SMBIOS_DATA_FUNCTION *Function; +} EFI_COMMON_SMBIOS_DATA; +#endif // SMBIOS_COMMON_DRIVER_H_ diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonDxe.inf b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonDxe.inf new file mode 100644 index 0000000000..fc407c3bec --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonDxe.inf @@ -0,0 +1,76 @@ +## @file +# AMD common SMBIOS DXE library Description File +# +# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmbiosCommonDxe + FILE_GUID = 2546E2B4-8629-47C3-A294-91E244936CBE + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SmbiosCommonEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmbiosCommon.h + SmbiosCommonEntryPoint.c + Type38IpmiDeviceInformation.c + Type9SystemSlotInfoFunction.c + Type8PortConnectorInfoFunction.c + Type11OemStringsFunction.c + Type12SystemCfgOptionsFunction.c + Type13BiosLanguageInfoFunction.c + Type41OnboardDevExtInfoFunction.c + DefaultLomDevicePath.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + AmdPlatformPkg/AmdPlatformPkg.dec + BoardModulePkg/BoardModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + HobLib + MemoryAllocationLib + PcdLib + UefiDriverEntryPoint + UefiLib + PlatformSocLib + +[Protocols] + gEfiSmbiosProtocolGuid ## PROTOCOL ALWAYS_CONSUMED + gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## CONSUMES + gBoardBdsBootFromDevicePathProtocolGuid ## PRODUCES + +[Pcd] + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType8 ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType8Number ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics1 ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType9SlotCharacteristics2 ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType41 ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdAmdSmbiosType41Number ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdIpmiInterfaceType ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdType11OemStringsCount ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdType11OemStrings ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdType12SystemCfgOptionsCount ## CONSUMES + gAmdPlatformPkgTokenSpaceGuid.PcdType12SystemCfgOptions ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdIpmiKcsIoBaseAddress ## CONSUMES + +[Depex] + gEfiSmbiosProtocolGuid diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonEntryPoint.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonEntryPoint.c new file mode 100644 index 0000000000..eaa66be454 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/SmbiosCommonEntryPoint.c @@ -0,0 +1,148 @@ +/** @file + AMD Smbios Common DXE entry point. + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "SmbiosCommon.h" + +EFI_COMMON_SMBIOS_DATA mSmbiosCommonDataFuncTable[] = { + { &IpmiDeviceInformation }, + { &SystemSlotInfoFunction }, + { &PortConnectorInfoFunction }, + { &OemStringsFunction }, + { &SystemCfgOptionsFunction }, + { &BiosLanguageInfoFunction } +}; + +/** + Add an SMBIOS record. + + @param Smbios The EFI_SMBIOS_PROTOCOL instance. + @param SmbiosHandle A unique handle will be assigned to the SMBIOS record. + @param Record The data for the fixed portion of the SMBIOS record. The format of the record is + determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined + by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or + a set of null terminated strings and a null. + + @retval EFI_SUCCESS Record was added. + @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources. + +**/ +EFI_STATUS +AddCommonSmbiosRecord ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + OUT EFI_SMBIOS_HANDLE *SmbiosHandle, + IN EFI_SMBIOS_TABLE_HEADER *Record + ) +{ + *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + return Smbios->Add ( + Smbios, + NULL, + SmbiosHandle, + Record + ); +} + +/** + PciEnumerationComplete Protocol notification event handler. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +OnPciEnumerationComplete ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS EfiStatus; + EFI_SMBIOS_PROTOCOL *Smbios; + + EfiStatus = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **)&Smbios + ); + if (EFI_ERROR (EfiStatus)) { + DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", EfiStatus)); + } + + // Install Type 41 when PCI enumeration is complete + EfiStatus = OnboardDevExtInfoFunction (Smbios); + if (EFI_ERROR (EfiStatus)) { + DEBUG (( + DEBUG_ERROR, + "Skip installing SMBIOS Table 41, ReturnStatus=%r\n", + EfiStatus + )); + } + + EfiStatus = InstallLomDevicePath (); +} + +/** + EFI driver entry point. This driver parses mSmbiosCommonDataFuncTable + structure and generates common platform smbios records. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The data was successfully stored. + +**/ +EFI_STATUS +EFIAPI +SmbiosCommonEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Index; + EFI_STATUS EfiStatus; + EFI_SMBIOS_PROTOCOL *Smbios; + EFI_EVENT ProtocolNotifyEvent; + VOID *Registration; + + DEBUG ((DEBUG_INFO, "%a: Entry.\n", __func__)); + + EfiStatus = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **)&Smbios + ); + if (EFI_ERROR (EfiStatus)) { + DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", EfiStatus)); + return EfiStatus; + } + + ProtocolNotifyEvent = EfiCreateProtocolNotifyEvent ( + &gEfiPciEnumerationCompleteProtocolGuid, + TPL_CALLBACK, + OnPciEnumerationComplete, + NULL, + &Registration + ); + if (ProtocolNotifyEvent == NULL) { + DEBUG ((DEBUG_ERROR, "Could not create PCI enumeration complete event\n")); + } + + for (Index = 0; Index < sizeof (mSmbiosCommonDataFuncTable)/sizeof (mSmbiosCommonDataFuncTable[0]); ++Index) { + EfiStatus = (*mSmbiosCommonDataFuncTable[Index].Function)(Smbios); + if (EFI_ERROR (EfiStatus)) { + // Continue installing remaining tables if one table fails. + DEBUG (( + DEBUG_ERROR, + "Skip installing SMBIOS Table Index=%d, ReturnStatus=%r\n", + Index, + EfiStatus + )); + continue; + } + } + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type11OemStringsFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type11OemStringsFunction.c new file mode 100644 index 0000000000..53e7a57355 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type11OemStringsFunction.c @@ -0,0 +1,91 @@ +/** @file + AMD SMBIOS Type 11 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "SmbiosCommon.h" + +/** + This function adds OEM strings smbios record (Type 11). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +OemStringsFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE11 *SmbiosRecord; + UINT8 OemStrCount; + UINTN OemStrLen; + UINTN OemStrListSize; + CHAR8 *OemStrPtr; + UINT8 Idx; + UINTN StringOffset; + + Status = EFI_SUCCESS; + SmbiosRecord = NULL; + OemStrListSize = 0; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Get number of OEM strings + OemStrCount = PcdGet8 (PcdType11OemStringsCount); + + // Calculate size of all OEM Strings + OemStrPtr = (CHAR8 *)PcdGetPtr (PcdType11OemStrings); + for (Idx = 0; Idx < OemStrCount; Idx++) { + OemStrLen = AsciiStrSize (OemStrPtr); + OemStrPtr += OemStrLen; + OemStrListSize += OemStrLen; + } + + // Allocate memory for Type11 record + SmbiosRecord = AllocateZeroPool ( + sizeof (SMBIOS_TABLE_TYPE11) + OemStrListSize + 1 + ); + + if (SmbiosRecord == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_OEM_STRINGS; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE11); + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->StringCount = OemStrCount; + + StringOffset = SmbiosRecord->Hdr.Length; + + // Append strings at the end + OemStrPtr = (CHAR8 *)PcdGetPtr (PcdType11OemStrings); + for (Idx = 0; Idx < OemStrCount; Idx++) { + OemStrLen = AsciiStrSize (OemStrPtr); + CopyMem ( + (UINT8 *)SmbiosRecord + StringOffset, + OemStrPtr, + OemStrLen + ); + OemStrPtr += OemStrLen; + StringOffset += OemStrLen; + } + + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + + FreePool (SmbiosRecord); + + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type12SystemCfgOptionsFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type12SystemCfgOptionsFunction.c new file mode 100644 index 0000000000..befb122372 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type12SystemCfgOptionsFunction.c @@ -0,0 +1,90 @@ +/** @file + AMD SMBIOS Type 12 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "SmbiosCommon.h" + +/** + This function adds System Configuration Options record (Type 12). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +SystemCfgOptionsFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE12 *SmbiosRecord; + UINT8 SystemCfgOptionsCount; + UINTN SystemCfgOptionsLen; + UINTN SystemCfgOptionsListSize; + CHAR8 *SystemCfgOptionsPtr; + UINT8 Idx; + UINTN StringOffset; + + Status = EFI_SUCCESS; + SmbiosRecord = NULL; + SystemCfgOptionsListSize = 0; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Get number of System Configuration Options + SystemCfgOptionsCount = PcdGet8 (PcdType12SystemCfgOptionsCount); + + // Calculate size of all Strings + SystemCfgOptionsPtr = (CHAR8 *)PcdGetPtr (PcdType12SystemCfgOptions); + for (Idx = 0; Idx < SystemCfgOptionsCount; Idx++) { + SystemCfgOptionsLen = AsciiStrSize (SystemCfgOptionsPtr); + SystemCfgOptionsPtr += SystemCfgOptionsLen; + SystemCfgOptionsListSize += SystemCfgOptionsLen; + } + + // Allocate memory for Type12 record + SmbiosRecord = AllocateZeroPool ( + sizeof (SMBIOS_TABLE_TYPE12) + SystemCfgOptionsListSize + 1 + ); + + if (SmbiosRecord == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE12); + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->StringCount = SystemCfgOptionsCount; + + StringOffset = SmbiosRecord->Hdr.Length; + + // Append strings at the end + SystemCfgOptionsPtr = (CHAR8 *)PcdGetPtr (PcdType12SystemCfgOptions); + for (Idx = 0; Idx < SystemCfgOptionsCount; Idx++) { + SystemCfgOptionsLen = AsciiStrSize (SystemCfgOptionsPtr); + CopyMem ( + (UINT8 *)SmbiosRecord + StringOffset, + SystemCfgOptionsPtr, + SystemCfgOptionsLen + ); + SystemCfgOptionsPtr += SystemCfgOptionsLen; + StringOffset += SystemCfgOptionsLen; + } + + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + FreePool (SmbiosRecord); + + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type13BiosLanguageInfoFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type13BiosLanguageInfoFunction.c new file mode 100644 index 0000000000..7d3ada2769 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type13BiosLanguageInfoFunction.c @@ -0,0 +1,146 @@ +/** @file + AMD SMBIOS Type 13 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "SmbiosCommon.h" + +/** + This function adds bios language information smbios record (Type 13). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. + @retval EFI_NOT_FOUND Not able to locate PlatformLanguage. + +**/ +EFI_STATUS +EFIAPI +BiosLanguageInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE13 *SmbiosRecord; + UINTN TotalSize; + UINTN StringOffset; + UINTN VarSize; + UINTN Idx; + UINT8 NumSupportedLang; + UINT8 CurrLangIdx; + CHAR8 *CurrLang; + CHAR8 *SupportedLang; + CHAR8 *LangStr; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + CurrLang = NULL; + SupportedLang = NULL; + + // Get the current language. + Status = GetEfiGlobalVariable2 ( + L"PlatformLang", + (void **)&CurrLang, + &VarSize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get PlatformLang: %r\n", Status)); + + VarSize = AsciiStrSize ( + (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang) + ); + CurrLang = AllocateCopyPool ( + VarSize, + (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang) + ); + ASSERT (CurrLang != NULL); + } + + // Get the list of supported languages. + Status = GetEfiGlobalVariable2 ( + L"PlatformLangCodes", + (void **)&SupportedLang, + &VarSize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to get PlatformLangCodes: %r\n", Status)); + + VarSize = AsciiStrSize ( + (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) + ); + SupportedLang = AllocateCopyPool ( + VarSize, + (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) + ); + ASSERT (SupportedLang != NULL); + } + + // Calculate number of supported languages and index of current language in list. + CurrLangIdx = 0; + NumSupportedLang = 0; + LangStr = SupportedLang; + + for (Idx = 0; Idx < VarSize; Idx++) { + if ((SupportedLang[Idx] == ';') || (SupportedLang[Idx] == '\0')) { + // Found a language string, increment the language count. + NumSupportedLang++; + + // Replace string separator with null termination. + SupportedLang[Idx] = '\0'; + if (!AsciiStrCmp (LangStr, CurrLang)) { + CurrLangIdx = NumSupportedLang; + } + + // Point LangStr to next string in list. + LangStr = &SupportedLang[Idx + 1]; + } + } + + if (CurrLangIdx == 0) { + DEBUG ((DEBUG_ERROR, "Failed to locate PlatformLang in PlatformLangCode.\n")); + Status = EFI_NOT_FOUND; + } else { + // Calculate record size and allocate memory for smbios record. + TotalSize = sizeof (SMBIOS_TABLE_TYPE13) + VarSize + 1; + + SmbiosRecord = AllocateZeroPool (TotalSize); + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + // Fill record data and strings. + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13); + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->InstallableLanguages = NumSupportedLang; + SmbiosRecord->Flags = 1; // Abbreviated Format. + SmbiosRecord->CurrentLanguages = CurrLangIdx; + + // Add strings to bottom of data block + StringOffset = SmbiosRecord->Hdr.Length; + CopyMem ((UINT8 *)SmbiosRecord + StringOffset, SupportedLang, VarSize); + + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + FreePool (SmbiosRecord); + } + } + + if (CurrLang != NULL) { + FreePool (CurrLang); + } + + if (SupportedLang != NULL) { + FreePool (SupportedLang); + } + + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type38IpmiDeviceInformation.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type38IpmiDeviceInformation.c new file mode 100644 index 0000000000..e2ad2ddb3d --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type38IpmiDeviceInformation.c @@ -0,0 +1,70 @@ +/** @file + AMD SMBIOS Type 38 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "SmbiosCommon.h" + +/** + This function updates IPMI Device information changes to the contents of the + Table Type 38. + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL protocol instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. +**/ +EFI_STATUS +EFIAPI +IpmiDeviceInformation ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE38 *SmbiosRecord; + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE38) + 1 + 1); + if (SmbiosRecord == NULL) { + ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES); + return EFI_OUT_OF_RESOURCES; + } + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_IPMI_DEVICE_INFORMATION; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE38); + SmbiosRecord->Hdr.Handle = 0; + + switch (FixedPcdGet8 (PcdIpmiInterfaceType)) { + case IPMIDeviceInfoInterfaceTypeKCS: + SmbiosRecord->InterfaceType = IPMIDeviceInfoInterfaceTypeKCS; + SmbiosRecord->IPMISpecificationRevision = 0x20; // IPMI v2.0 + SmbiosRecord->I2CSlaveAddress = 0x00; // not used in KCS interface + SmbiosRecord->NVStorageDeviceAddress = 0xFF; + // KCS port number base and set LSB bit 1 to mark IO ADDRESS space + SmbiosRecord->BaseAddress = FixedPcdGet16 (PcdIpmiKcsIoBaseAddress) | 0x1; + SmbiosRecord->BaseAddressModifier_InterruptInfo = 0x00; + SmbiosRecord->InterruptNumber = 0x00; + // + // Now we have got the full smbios record, + // call smbios protocol to add this record. + // + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + break; + default: + // Do not add table + Status = EFI_UNSUPPORTED; + break; + } + + FreePool (SmbiosRecord); + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type41OnboardDevExtInfoFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type41OnboardDevExtInfoFunction.c new file mode 100644 index 0000000000..cbd4c75eaf --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type41OnboardDevExtInfoFunction.c @@ -0,0 +1,237 @@ +/** @file + AMD SMBIOS Type 41 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include <Pcd/SmbiosPcd.h> +#include "SmbiosCommon.h" + +#define MSR_MMIO_CFG_BASE 0xC0010058ul // MMIO Configuration Base Address Register + +/** + This function adds onboard devices extended information smbios record (Type 41). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +OnboardDevExtInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE41 *SmbiosRecord; + SMBIOS_ONBOARD_DEV_EXT_INFO_RECORD *DevExtInfoRecord; + UINT8 DevIdx; + UINT8 Idx; + UINT8 NumberOfDevices; + UINTN StringOffset; + CHAR8 *RefDesStr; + UINTN RefDesStrLen; + UINT16 SegmentNum; + UINT8 BusNum; + UINT8 DevNum; + UINT8 Functions; + UINT8 DeviceFound; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Get the total number of onboard devices. + NumberOfDevices = PcdGet8 (PcdAmdSmbiosType41Number); + DEBUG ((DEBUG_INFO, "%a: Total number of AMD SMBIOS type41 PCD structure %d.\n", __func__, NumberOfDevices)); + DevExtInfoRecord = (SMBIOS_ONBOARD_DEV_EXT_INFO_RECORD *)PcdGetPtr (PcdAmdSmbiosType41); + + // No device entries found + if (NumberOfDevices == 0) { + DEBUG ((DEBUG_INFO, "No onboard devices found.\n")); + return EFI_NOT_FOUND; + } + + // Generate type41 smbios record for each device and add it to Smbios table. + for (DevIdx = 0; DevIdx < NumberOfDevices; DevIdx++) { + DEBUG ((DEBUG_MANAGEABILITY, "Device number %d:\n", DevIdx)); + // Check whether reference designation strings are present. + if (DevExtInfoRecord->ReferenceDesignation != 0) { + RefDesStr = DevExtInfoRecord->RefDesignationStr; + RefDesStrLen = AsciiStrLen (RefDesStr) + 1; + } else { + RefDesStr = NULL; + RefDesStrLen = 1; + } + + DEBUG ((DEBUG_MANAGEABILITY, " - ReferenceDesignation = %d\n", DevExtInfoRecord->ReferenceDesignation)); + DEBUG ((DEBUG_MANAGEABILITY, " - DeviceType = %d\n", DevExtInfoRecord->DeviceType)); + DEBUG ((DEBUG_MANAGEABILITY, " - DeviceEnabled = %d\n", DevExtInfoRecord->DeviceEnabled)); + DEBUG ((DEBUG_MANAGEABILITY, " - DeviceTypeInstance = %d\n", DevExtInfoRecord->DeviceTypeInstance)); + DEBUG ((DEBUG_MANAGEABILITY, " - VendorId = %x\n", DevExtInfoRecord->VendorId)); + DEBUG ((DEBUG_MANAGEABILITY, " - DeviceId = %x\n", DevExtInfoRecord->DeviceId)); + DEBUG ((DEBUG_MANAGEABILITY, " - RefDesignationStr = %a\n", DevExtInfoRecord->RefDesignationStr)); + + Status = GetBusDeviceInfo ( + &DevExtInfoRecord->VendorId, + &DevExtInfoRecord->DeviceId, + &DevExtInfoRecord->DeviceTypeInstance, + &SegmentNum, + &BusNum, + &DevNum, + &Functions, + &DeviceFound + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Could not get SBDF details for idx %d\n", DevIdx)); + continue; + } + + // Device not present + if (DeviceFound == 0) { + Status = EFI_NOT_FOUND; + DEBUG (( + DEBUG_ERROR, + "No onboard device found matching VendorId: %x DeviceId: %x\n", + DevExtInfoRecord->VendorId, + DevExtInfoRecord->DeviceId + )); + continue; + } + + // Create one record for each function in a multi-function device + for (Idx = 0; Idx <= 7; Idx++) { + if ((Functions >> Idx) & 0x1) { + SmbiosRecord = NULL; + SmbiosRecord = AllocateZeroPool ( + sizeof (SMBIOS_TABLE_TYPE41) + RefDesStrLen + 1 + ); + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } else { + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE41); + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->ReferenceDesignation = DevExtInfoRecord->ReferenceDesignation; + SmbiosRecord->DeviceType = (DevExtInfoRecord->DeviceEnabled << 7) | DevExtInfoRecord->DeviceType; + SmbiosRecord->DeviceTypeInstance = DevExtInfoRecord->DeviceTypeInstance; + SmbiosRecord->SegmentGroupNum = SegmentNum; + SmbiosRecord->BusNum = BusNum; + SmbiosRecord->DevFuncNum = (DevNum << 3) + Idx; + + // Add strings to bottom of data block + StringOffset = SmbiosRecord->Hdr.Length; + CopyMem ( + (UINT8 *)SmbiosRecord + StringOffset, + RefDesStr, + RefDesStrLen + ); + StringOffset += RefDesStrLen; + + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + FreePool (SmbiosRecord); + } + } + } + + DevExtInfoRecord++; + } + + return Status; +} + +/** + This function gets the Bus, Device and Segment number of a PCI device when Vendor ID, Device ID and instance + are provided. + + @param[in] VendorId Vendor ID of the PCI device to be provided. + @param[in] DeviceId Device ID of the PCI device to be provided + @param[in] Instance Instance of the PCI device. If more than one devices with same vendor + and device ID is present, instance number is used. + @param[out] Segment Segment number of the PCI device is assigned. + @param[out] Bus Bus number of the PCI device is assigned. + @param[out] Device Device number of the PCI device is assigned. + @param[out] Functions Bits 0-7 of the Functions variable correspond to respective function numbers. + @param[out] DeviceFound Set to 1 if the device is found. + + @retval EFI_SUCCESS All parameters were valid. +**/ +EFI_STATUS +EFIAPI +GetBusDeviceInfo ( + IN UINT16 *VendorId, + IN UINT16 *DeviceId, + IN UINT8 *Instance, + OUT UINT16 *Segment, + OUT UINT8 *Bus, + OUT UINT8 *Device, + OUT UINT8 *Functions, + OUT UINT8 *DeviceFound + ) +{ + UINT16 SegIdx; + UINT8 BusIdx; + UINT16 BusIdx16; + UINT8 DevIdx; + UINT8 FuncIdx; + UINT8 InstanceCount; + UINT16 MaxSegments; + UINT8 BusRangeIdentifier; + + InstanceCount = *Instance; + *DeviceFound = 0; + + BusRangeIdentifier = (AsmReadMsr64 (MSR_MMIO_CFG_BASE) >> 2) & 0xF; + if ( BusRangeIdentifier <= 0x8 ) { + MaxSegments = 1; + } else if ((BusRangeIdentifier >= 0x9) && (BusRangeIdentifier <= 0xF)) { + MaxSegments = 1 << (BusRangeIdentifier - 0x8); + } + + for (SegIdx = 0; SegIdx < MaxSegments; SegIdx++ ) { + for (BusIdx16 = 0; BusIdx16 <= 255; BusIdx16++) { + BusIdx = (UINT8)BusIdx16; + for (DevIdx = 0; DevIdx < 32; DevIdx++) { + if ((PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegIdx, BusIdx, DevIdx, 0, 2)) == *DeviceId) && + (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegIdx, BusIdx, DevIdx, 0, 0)) == *VendorId)) + { + *DeviceFound = 1; + *Functions = 0; + if (InstanceCount > 1) { + *DeviceFound = 0; + InstanceCount--; + continue; + } else { + *Bus = BusIdx; + *Device = DevIdx; + *Segment = SegIdx; + *Functions |= 1; + for (FuncIdx = 1; FuncIdx < 8; FuncIdx++) { + if ((PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegIdx, BusIdx, DevIdx, FuncIdx, 2)) == *DeviceId) && + (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SegIdx, BusIdx, DevIdx, FuncIdx, 0)) == *VendorId)) + { + *Functions |= (1 << FuncIdx); + } + } + + return EFI_SUCCESS; + } + } + } + + if (BusIdx == 255) { + break; + } + } + } + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type8PortConnectorInfoFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type8PortConnectorInfoFunction.c new file mode 100644 index 0000000000..844529d1f0 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type8PortConnectorInfoFunction.c @@ -0,0 +1,133 @@ +/** @file + AMD SMBIOS Type 8 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include <Pcd/SmbiosPcd.h> +#include "SmbiosCommon.h" + +/** + This function adds port connector information smbios record (Type 8). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. +**/ +EFI_STATUS +EFIAPI +PortConnectorInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE8 *SmbiosRecord; + SMBIOS_PORT_CONNECTOR_RECORD *PortConnRecord; + UINT8 PortIdx; + UINT8 NumberOfPortConnector; + UINTN StringOffset; + CHAR8 *IntPortConDesStr; + UINTN IntPortConDesStrLen; + CHAR8 *ExtPortConDesStr; + UINTN ExtPortConDesStrLen; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Get the total number of port connectors. + NumberOfPortConnector = PcdGet8 (PcdAmdSmbiosType8Number); + DEBUG ((DEBUG_INFO, "%a: Total number of AMD SMBIOS type8 PCD structure %d.\n", __func__, NumberOfPortConnector)); + PortConnRecord = (SMBIOS_PORT_CONNECTOR_RECORD *)PcdGetPtr (PcdAmdSmbiosType8); + + if (NumberOfPortConnector == 0) { + DEBUG ((DEBUG_INFO, "No port connectors found.\n")); + return EFI_NOT_FOUND; + } + + // Generate type8 smbios record for each connector and add it to Smbios table. + for (PortIdx = 0; PortIdx < NumberOfPortConnector; PortIdx++) { + DEBUG ((DEBUG_MANAGEABILITY, "Port %d:\n", PortIdx)); + // Check whether Port connector designator strings are present or not. + if (PortConnRecord->Type8Data.InternalReferenceDesignator != 0) { + IntPortConDesStr = PortConnRecord->DesinatorStr.IntDesignatorStr; + IntPortConDesStrLen = AsciiStrLen (IntPortConDesStr) + 1; + DEBUG ((DEBUG_MANAGEABILITY, "-- DesinatorStr.IntDesignatorStr = %a\n", IntPortConDesStr)); + } else { + IntPortConDesStr = NULL; + IntPortConDesStrLen = 0; + } + + if (PortConnRecord->Type8Data.ExternalReferenceDesignator != 0) { + ExtPortConDesStr = PortConnRecord->DesinatorStr.ExtDesignatorStr; + ExtPortConDesStrLen = AsciiStrLen (ExtPortConDesStr) + 1; + DEBUG ((DEBUG_MANAGEABILITY, "-- DesinatorStr.ExtDesignatorStr = %a\n", ExtPortConDesStr)); + } else { + ExtPortConDesStr = NULL; + ExtPortConDesStrLen = 0; + } + + SmbiosRecord = NULL; + SmbiosRecord = AllocateZeroPool ( + sizeof (SMBIOS_TABLE_TYPE8) + IntPortConDesStrLen + ExtPortConDesStrLen + 1 + ); + + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } else { + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE8); + SmbiosRecord->Hdr.Handle = 0; + + SmbiosRecord->InternalReferenceDesignator = + PortConnRecord->Type8Data.InternalReferenceDesignator; + SmbiosRecord->InternalConnectorType = + PortConnRecord->Type8Data.InternalConnectorType; + SmbiosRecord->ExternalReferenceDesignator = + PortConnRecord->Type8Data.ExternalReferenceDesignator; + SmbiosRecord->ExternalConnectorType = + PortConnRecord->Type8Data.ExternalConnectorType; + SmbiosRecord->PortType = + PortConnRecord->Type8Data.PortType; + DEBUG ((DEBUG_MANAGEABILITY, " - InternalReferenceDesignator = %d\n", SmbiosRecord->InternalReferenceDesignator)); + DEBUG ((DEBUG_MANAGEABILITY, " - InternalConnectorType = %d\n", SmbiosRecord->InternalConnectorType)); + DEBUG ((DEBUG_MANAGEABILITY, " - ExternalReferenceDesignator = %d\n", SmbiosRecord->ExternalReferenceDesignator)); + DEBUG ((DEBUG_MANAGEABILITY, " - ExternalConnectorType = %d\n", SmbiosRecord->ExternalConnectorType)); + DEBUG ((DEBUG_MANAGEABILITY, " - PortType = %d\n", SmbiosRecord->PortType)); + + // Add strings to bottom of data block + StringOffset = SmbiosRecord->Hdr.Length; + if (IntPortConDesStr != NULL) { + CopyMem ( + (UINT8 *)SmbiosRecord + StringOffset, + IntPortConDesStr, + IntPortConDesStrLen + ); + StringOffset += IntPortConDesStrLen; + } + + if (ExtPortConDesStr != NULL) { + CopyMem ( + (UINT8 *)SmbiosRecord + StringOffset, + ExtPortConDesStr, + ExtPortConDesStrLen + ); + } + + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + FreePool (SmbiosRecord); + } + + PortConnRecord++; + } + + return Status; +} diff --git a/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type9SystemSlotInfoFunction.c b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type9SystemSlotInfoFunction.c new file mode 100644 index 0000000000..568f44b427 --- /dev/null +++ b/Platform/AMD/AmdPlatformPkg/Universal/SmbiosCommonDxe/Type9SystemSlotInfoFunction.c @@ -0,0 +1,94 @@ +/** @file + AMD SMBIOS Type 9 Record + + Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include <Library/PrintLib.h> +#include "SmbiosCommon.h" +#include <Library/AmdPlatformSocLib.h> + +/** + This function checks for system slot info and adds smbios record (Type 9). + + @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_OUT_OF_RESOURCES Resource not available. + +**/ +EFI_STATUS +EFIAPI +SystemSlotInfoFunction ( + IN EFI_SMBIOS_PROTOCOL *Smbios + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE9 *SmbiosRecord; + UINTN SystemSlotCount; + SMBIOS_TABLE_TYPE9 *SystemSlotInfo; + UINTN Index; + CHAR8 SlotDesignationStr[SMBIOS_STRING_MAX_LENGTH]; + SMBIOS_TABLE_TYPE9_EXTENDED SmbiosRecordExtended; + UINTN SlotDesStrLen; + UINTN TotalSize; + + if (Smbios == NULL) { + return EFI_INVALID_PARAMETER; + } + + SystemSlotInfo = NULL; + SystemSlotCount = 0; + // Invoke GetSystemSlotInfo function to get the number of system slots. + Status = GetSystemSlotInfo (&SystemSlotInfo, &SystemSlotCount); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < SystemSlotCount; Index++) { + SlotDesStrLen = AsciiSPrint ( + SlotDesignationStr, + SMBIOS_STRING_MAX_LENGTH, + "PCIE-%d", + SystemSlotInfo[Index].SlotID + ); + // Two zeros following the last string. + TotalSize = sizeof (SMBIOS_TABLE_TYPE9) + sizeof (SMBIOS_TABLE_TYPE9_EXTENDED) + SlotDesStrLen + 2; + SmbiosRecord = NULL; + SmbiosRecord = AllocateZeroPool (TotalSize); + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + CopyMem (SmbiosRecord, &SystemSlotInfo[Index], sizeof (SMBIOS_TABLE_TYPE9)); + SmbiosRecord->Hdr.Type = SMBIOS_TYPE_SYSTEM_SLOTS; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9) + sizeof (SMBIOS_TABLE_TYPE9_EXTENDED); + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->SlotDesignation = 1; + SmbiosRecordExtended.SlotHeight = SlotHeightUnknown; + SmbiosRecordExtended.SlotPitch = 0; + SmbiosRecordExtended.SlotPhysicalWidth = SmbiosRecord->SlotDataBusWidth; + CopyMem (&SmbiosRecord->SlotCharacteristics1, PcdGetPtr (PcdAmdSmbiosType9SlotCharacteristics1), sizeof (MISC_SLOT_CHARACTERISTICS1)); + CopyMem (&SmbiosRecord->SlotCharacteristics2, PcdGetPtr (PcdAmdSmbiosType9SlotCharacteristics2), sizeof (MISC_SLOT_CHARACTERISTICS2)); + CopyMem ((UINT8 *)SmbiosRecord->PeerGroups + SmbiosRecord->PeerGroupingCount * sizeof (SmbiosRecord->PeerGroups), (UINT8 *)&SmbiosRecordExtended, sizeof (SMBIOS_TABLE_TYPE9_EXTENDED)); + CopyMem ((UINT8 *)SmbiosRecord + SmbiosRecord->Hdr.Length, SlotDesignationStr, SlotDesStrLen); + Status = AddCommonSmbiosRecord ( + Smbios, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord + ); + if (EFI_ERROR (Status)) { + FreePool (SmbiosRecord); + break; + } + + if (SmbiosRecord != NULL) { + FreePool (SmbiosRecord); + } + } + } + + FreePool (SystemSlotInfo); + return EFI_SUCCESS; +} -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119101): https://edk2.groups.io/g/devel/message/119101 Mute This Topic: https://groups.io/mt/106220534/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-