public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Abdul Lateef Attar via groups.io" <AbdulLateef.Attar=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>,
	Abner Chang <abner.chang@amd.com>,
	Paul Grimes <paul.grimes@amd.com>
Subject: [edk2-devel] [PATCH 4/5] AmdMinBoardPkg: Implement BoardInitLib for DXE phase
Date: Fri, 17 May 2024 09:19:12 +0530	[thread overview]
Message-ID: <fc284dcd746a7a7d061d866a24582fefe4deb7ea.1715917637.git.AbdulLateef.Attar@amd.com> (raw)
In-Reply-To: <cover.1715917637.git.AbdulLateef.Attar@amd.com>

DxeBoardInitLib library provides board-specific
initialization functions for the DXE phase.

Cc: Abner Chang <abner.chang@amd.com>
Cc: Paul Grimes <paul.grimes@amd.com>
Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
---
 .../AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc     |   6 +-
 .../Library/DxeBoardInitLib/DxeBoardInitLib.c | 253 +++++++++++++++
 .../DxeBoardInitLib/DxeBoardInitLib.inf       |  51 +++
 .../DxeBoardInitLib/DxeBoardInitLibInternal.c | 306 ++++++++++++++++++
 .../DxeBoardInitLib/DxeBoardInitLibInternal.h | 159 +++++++++
 .../DxeBoardInitLib/MadtAcpiTablePatch.c      | 243 ++++++++++++++
 6 files changed, 1017 insertions(+), 1 deletion(-)
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.c
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.c
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.h
 create mode 100644 Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/MadtAcpiTablePatch.c

diff --git a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
index 335e875f70..e0afe1e755 100644
--- a/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
+++ b/Platform/AMD/AmdMinBoardPkg/AmdMinBoardPkg.dsc
@@ -40,6 +40,9 @@
   SetCacheMtrrLib|AmdMinBoardPkg/Library/SetCacheMtrrLib/SetCacheMtrrLib.inf
   BoardInitLib|AmdMinBoardPkg/Library/PeiBoardInitPreMemLib/PeiBoardInitPreMemLib.inf
 
+[LibraryClasses.common.DXE_DRIVER]
+  BoardInitLib|AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
+
 [Components]
   AmdMinBoardPkg/Library/SpcrDeviceLib/SpcrDeviceLib.inf
 
@@ -49,4 +52,5 @@
   AmdMinBoardPkg/Library/PeiBoardInitPreMemLib/PeiBoardInitPreMemLib.inf
 
 [Components.X64]
-  AmdMinBoardPkg/PciHotPlug/PciHotPlugInit.inf
+  AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
+  AmdMinBoardPkg/PciHotPlug/PciHotPlugInit.inf
\ No newline at end of file
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.c b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.c
new file mode 100644
index 0000000000..7c41d3e38b
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.c
@@ -0,0 +1,253 @@
+/** @file
+  BoardInitLib library implementation for DXE phase.
+
+  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BoardInitLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include "DxeBoardInitLibInternal.h"
+
+EFI_HANDLE        mImageHandle;
+EFI_SYSTEM_TABLE  *mSystemTable;
+
+/**
+  This board service detects the board type.
+
+  @retval EFI_SUCCESS   The board was detected successfully.
+  @retval EFI_NOT_FOUND The board could not be detected.
+**/
+EFI_STATUS
+EFIAPI
+BoardDetect (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This board service initializes board-specific debug devices.
+
+  @retval EFI_SUCCESS   Board-specific debug initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardDebugInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This board service detects the boot mode.
+
+  @retval EFI_BOOT_MODE The boot mode.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_BOOT_MODE
+EFIAPI
+BoardBootModeDetect (
+  VOID
+  )
+{
+  return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+  A hook for board-specific initialization prior to memory initialization.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitBeforeMemoryInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization after memory initialization.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitAfterMemoryInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization prior to disabling temporary RAM.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitBeforeTempRamExit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization after disabling temporary RAM.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitAfterTempRamExit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization prior to silicon initialization.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitBeforeSiliconInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization after silicon initialization.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitAfterSiliconInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific initialization after PCI enumeration.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitAfterPciEnumeration (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "%a - ENTRY\n", __FUNCTION__));
+
+  Status = ReserveLegacyVgaIoSpace ();
+  DEBUG ((DEBUG_INFO, "ReserveLegacyVgaIoSpace...%r.\n", Status));
+
+  Status = ReservePcieExtendedConfigSpace (mImageHandle, mSystemTable);
+  DEBUG ((DEBUG_INFO, "ReservePcieExtendedConfigSpace...%r.\n", Status));
+
+  return Status;
+}
+
+/**
+  A hook for board-specific functionality for the ReadyToBoot event.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitReadyToBoot (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = UpdateReinstallAcpiTable (
+             EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+             (PATCH_ACPITABLE)FadtAcpiTablePatch
+             );
+  DEBUG ((DEBUG_INFO, "Patching FADT ACPI Table ... Status = %r.\n", Status));
+
+  Status = UpdateReinstallAcpiTable (
+             EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+             (PATCH_ACPITABLE)MadtAcpiTablePatch
+             );
+  DEBUG ((DEBUG_INFO, "Patching MADT ACPI Table ... Status = %r.\n", Status));
+
+  UpdateReinstallAcpiTable (
+    EFI_ACPI_6_5_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+    (PATCH_ACPITABLE)AcpiTableAmlUpdate
+    );
+
+  UpdateReinstallAcpiTable (
+    EFI_ACPI_6_5_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+    (PATCH_ACPITABLE)AcpiTableAmlUpdate
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A hook for board-specific functionality for the ExitBootServices event.
+
+  @retval EFI_SUCCESS   The board initialization was successful.
+  @retval EFI_NOT_READY The board has not been detected yet.
+**/
+EFI_STATUS
+EFIAPI
+BoardInitEndOfFirmware (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  The constructor function caches the PCI Express Base Address and creates a
+  Set Virtual Address Map event to convert physical address to virtual addresses.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor completed successfully.
+  @retval Other value   The constructor did not complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeBoardInitLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  mImageHandle = ImageHandle;
+  mSystemTable = SystemTable;
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
new file mode 100644
index 0000000000..919777d016
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLib.inf
@@ -0,0 +1,51 @@
+## @file
+#  Implements BoardInitLib Library Class in DXE phase.
+#
+# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = DxeBoardInitLib
+  FILE_GUID                      = B3C8F348-B528-4CA0-928E-3193ADEA65E6
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BoardInitLib
+  CONSTRUCTOR                    = DxeBoardInitLibConstructor
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  LocalApicLib
+  PcdLib
+  PcieConfigLib
+  PlatformSocLib
+  SortLib
+
+[Packages]
+  AmdPlatformPkg/AmdPlatformPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  PcAtChipsetPkg/PcAtChipsetPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[Sources]
+  DxeBoardInitLib.c
+  DxeBoardInitLibInternal.c
+  DxeBoardInitLibInternal.h
+  MadtAcpiTablePatch.c
+
+[Protocols]
+  gEfiAcpiSdtProtocolGuid
+  gEfiAcpiTableProtocolGuid
+  gEfiMpServiceProtocolGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+[DEPEX]
+  gEfiMpServiceProtocolGuid
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.c b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.c
new file mode 100644
index 0000000000..2ffc249792
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.c
@@ -0,0 +1,306 @@
+/** @file
+  BoardInitLib library internal implementation for DXE phase.
+
+Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "DxeBoardInitLibInternal.h"
+
+/**
+  A helper function to uninstall or update the ACPI table.
+  It searches for ACPI table for provided table signature,
+  if found then creates a copy of the table and calls the callbackfunction.
+
+  @param[in] Signature           ACPI table signature
+  @param[in] CallbackFunction    The function to call to patch the searching ACPI table.
+                                 If NULL then uninstalls the table.
+
+  @return EFI_SUCCESS            Successfully Re-install the ACPI Table
+  @return EFI_NOT_FOUND          Table not found
+  @return EFI_STATUS             returns non-EFI_SUCCESS value in case of failure
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateReinstallAcpiTable (
+  IN UINT32           Signature,
+  IN PATCH_ACPITABLE  CallbackFunction
+  )
+{
+  EFI_ACPI_SDT_PROTOCOL    *AcpiSdtProtocol;
+  EFI_STATUS               Status;
+  UINTN                    Index;
+  EFI_ACPI_SDT_HEADER      *Table;
+  EFI_ACPI_TABLE_VERSION   Version;
+  UINTN                    OriginalTableKey;
+  EFI_ACPI_TABLE_PROTOCOL  *AcpiTableProtocol;
+  EFI_ACPI_SDT_HEADER      *NewTable;
+  UINTN                    NewTableKey;
+  BOOLEAN                  Found;
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Error(%r): Unable to locate ACPI Table protocol.\n", Status));
+    return Status;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdtProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Error(%r): Unable to locate ACPI SDT protocol.\n", Status));
+    return Status;
+  }
+
+  Found = FALSE;
+  Index = 0;
+  do {
+    Status = AcpiSdtProtocol->GetAcpiTable (Index, &Table, &Version, &OriginalTableKey);
+    if (EFI_ERROR (Status)) {
+      goto END_OF_SEARCH;
+    }
+
+    // Look for given table
+    if (Table->Signature == Signature) {
+      if (CallbackFunction == NULL) {
+        Status = AcpiTableProtocol->UninstallAcpiTable (AcpiTableProtocol, OriginalTableKey);
+        return Status;
+      }
+
+      NewTable = AllocateCopyPool (Table->Length, Table);
+      if (NULL == NewTable) {
+        Status = EFI_OUT_OF_RESOURCES;
+        DEBUG ((DEBUG_ERROR, "Error(%r): Not enough resource to allocate table.\n", Status));
+        return Status;
+      }
+
+      Status = CallbackFunction (NewTable);
+      if (!EFI_ERROR (Status)) {
+        // Uninstall the old table
+        Status = AcpiTableProtocol->UninstallAcpiTable (AcpiTableProtocol, OriginalTableKey);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_ERROR, "Error(%r): Uninstall old table error.\n", Status));
+          FreePool (NewTable);
+          return Status;
+        }
+
+        // Install the new table
+        Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, NewTable, NewTable->Length, &NewTableKey);
+        FreePool (NewTable);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_ERROR, "Error(%r): Failed to install new table.\n", Status));
+          return Status;
+        }
+
+        // If non SSDT table, then return status
+        if (Table->Signature != EFI_ACPI_6_5_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+          return Status;
+        }
+
+        // Atleast one SSDT table update is success
+        Found = TRUE;
+      }
+
+      // continue to search next SSDT table.
+      Status = EFI_SUCCESS;
+    }
+
+    Index++;
+  } while (!EFI_ERROR (Status));
+
+END_OF_SEARCH:
+  if (!Found) {
+    DEBUG ((DEBUG_ERROR, "Error(%r): Unable to locate ACPI Table.\n", Status));
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A Callback function to patch the ACPI FADT table.
+  Updates FADT table with AMD specific values, which
+  are different than MinPlatformPkg.
+
+  @param[in, out] NewTable       Pointer to ACPI FADT table
+
+  @return         EFI_SUCCESS    Always return EFI_SUCCESSe
+
+**/
+EFI_STATUS
+EFIAPI
+FadtAcpiTablePatch (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  )
+{
+  EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE  *NewFadt;
+
+  NewFadt = (EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE *)NewTable;
+  // Patch the Table
+  NewFadt->PLvl2Lat                  = 0x64;
+  NewFadt->Pm2CntLen                 = 0;
+  NewFadt->XGpe0Blk.RegisterBitWidth = 0x40;
+  NewFadt->FlushSize                 = 0x400;
+  NewFadt->FlushStride               = 0x10;
+  NewFadt->XGpe1Blk.AccessSize       = 0x01;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A Callback function to patch the ACPI DSDT/SSDT table.
+  Which has ASL code that needs to be updated.
+
+  @param[in, out] NewTable       Pointer to ACPI FADT table
+
+  @return         EFI_SUCCESS    If table is modified.
+                  EFI_NOT_FOUND  If table is not modified.
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiTableAmlUpdate (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  )
+{
+  UINT64  OemTableId;
+
+  if ((AsciiStrnCmp (NewTable->OemTableId, "AmdTable", 8) == 0)) {
+    DEBUG ((DEBUG_INFO, "Found (D/S)SDT table for patching OemTableId.\n"));
+    OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+    CopyMem (NewTable->OemTableId, &OemTableId, 8);
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Reserve Legacy VGA IO space.
+
+  @retval  EFI_SUCCESS  MMIO at Legacy VGA region has been allocated.
+  @retval  !EFI_SUCCESS Error allocating the legacy VGA region.
+
+**/
+EFI_STATUS
+EFIAPI
+ReserveLegacyVgaIoSpace (
+  VOID
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  VgaMemAddress;
+
+  VgaMemAddress = (EFI_PHYSICAL_ADDRESS)VGA_MEM_BASE;
+  Status        = gBS->AllocatePages (
+                         AllocateAddress,
+                         EfiMemoryMappedIO,
+                         EFI_SIZE_TO_PAGES (VGA_MEM_SIZE),
+                         &VgaMemAddress
+                         );
+  return Status;
+}
+
+/**
+  Helper function to get size of MMIO region required for the Bus Range
+  configured.
+
+  @param[in]    BusRange      Chipset representation of Bus Range
+
+  @retval                     Size of MMIO required for bus range
+**/
+UINT64
+DecodeMmioBusRange (
+  UINT64  BusRange
+  )
+{
+  // Minimum MMIO region required is 1MB (1 Segment - 1 Bus).
+  // Set Mmio Size to 1MB.
+  UINT64  MmioSize;
+
+  MmioSize = 0x100000;
+
+  if (BusRange > 0x0E) {
+    MmioSize = SIZE_32GB;
+  } else {
+    MmioSize = (MmioSize << BusRange);
+  }
+
+  return MmioSize;
+}
+
+/**
+  Reserve PCIe Extended Config Space MMIO in the GCD and mark it runtime
+
+  @param[in]  ImageHandle  ImageHandle of the loaded driver.
+  @param[in]  SystemTable  Pointer to the EFI System Table.
+
+  @retval  EFI_SUCCESS  One or more of the drivers returned a success code.
+  @retval  !EFI_SUCCESS  Error initializing the Legacy PIC.
+
+**/
+EFI_STATUS
+EFIAPI
+ReservePcieExtendedConfigSpace (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS        Status;
+  AMD_MMIO_CFG_MSR  MmioCfgMsr;
+  UINT64            MmioCfgBase;
+  UINT64            MmioCfgSize;
+
+  Status = EFI_SUCCESS;
+  //
+  // Reserve MMIO for PCI-Config space
+  //
+  MmioCfgMsr.AsUint64 = AsmReadMsr64 (AMD_MMIO_CFG_MSR_ADDR);
+  MmioCfgBase         = MmioCfgMsr.AsUint64 & AMD_MMIO_CFG_ADDR_MASK;
+  MmioCfgSize         = DecodeMmioBusRange (MmioCfgMsr.AsBits.BusRange);
+  DEBUG ((DEBUG_INFO, "\nMMIO_CFG MSR = 0x%08lX\n", MmioCfgMsr.AsUint64));
+  DEBUG ((DEBUG_INFO, "  Enable = %d\n", MmioCfgMsr.AsBits.Enable));
+  DEBUG ((DEBUG_INFO, "  BusRange = %d\n", MmioCfgMsr.AsBits.BusRange));
+  DEBUG ((DEBUG_INFO, "  MmioCfgBase = 0x%08lX\n", MmioCfgBase));
+  DEBUG ((DEBUG_INFO, "  MmioCfgSize = 0x%08lX\n", MmioCfgSize));
+
+  if (MmioCfgMsr.AsBits.Enable) {
+    // Free Memory if it is allocated (call will likely return Not Found)
+    Status = gDS->FreeMemorySpace (
+                    MmioCfgBase,
+                    MmioCfgSize
+                    );
+    // Remove Memory Space from GCD map (could return Not Found)
+    Status = gDS->RemoveMemorySpace (
+                    MmioCfgBase,
+                    MmioCfgSize
+                    );
+    // Make sure Adding memory space succeeds or assert
+    Status = gDS->AddMemorySpace (
+                    EfiGcdMemoryTypeReserved,
+                    MmioCfgBase,
+                    MmioCfgSize,
+                    EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+                    );
+    ASSERT_EFI_ERROR (Status);
+    // Make sure Allocating memory space succeed or assert
+    Status = gDS->AllocateMemorySpace (
+                    EfiGcdAllocateAddress,
+                    EfiGcdMemoryTypeReserved,
+                    0,
+                    MmioCfgSize,
+                    &MmioCfgBase,
+                    ImageHandle,
+                    NULL
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    DEBUG ((
+      DEBUG_INFO,
+      "\nReserved PciCfg MMIO: Base = 0x%lX, Size = 0x%lX\n",
+      MmioCfgBase,
+      MmioCfgSize
+      ));
+  }
+
+  return Status;
+}
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.h b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.h
new file mode 100644
index 0000000000..037328a34c
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/DxeBoardInitLibInternal.h
@@ -0,0 +1,159 @@
+/** @file
+
+Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef DXE_BOARD_INIT_LIB_INTERNAL_H_
+#define DXE_BOARD_INIT_LIB_INTERNAL_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Register/Intel/Cpuid.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <IndustryStandard/Acpi65.h>
+#include <Library/SortLib.h>
+#include <Library/IoLib.h>
+#include <Register/IoApic.h>
+#include <Protocol/MpService.h>
+#include <Library/BaseLib.h>
+
+// Define temp buffer length for save IoApic data
+#define MAX_IOAPIC_NUM  0x20
+
+#define VGA_MEM_BASE  0xA0000
+#define VGA_MEM_SIZE  0x20000
+
+//
+// 48-bit MMIO space (MB-aligned)
+//
+#define AMD_MMIO_CFG_MSR_ADDR   0xC0010058UL
+#define AMD_MMIO_CFG_ADDR_MASK  0xFFFFFFF00000ULL
+
+typedef struct {
+  UINT8    Type;
+  UINT8    Length;
+} STRUCTURE_HEADER;
+
+#pragma pack(1)
+typedef union {
+  struct {
+    // HACK-HACK: Use UINT32 to keep compiler from using SHIFT intrinsics on NOOPT build
+    UINT32    Enable          : 1;    // [0]
+    UINT32    Reserved1       : 1;    // [1]
+    UINT32    BusRange        : 4;    // [5:2]
+    UINT32    Reserved2       : 14;   // [19:6]
+    UINT32    MmioCfgBaseAddr : 28;   // [47:20]
+    UINT32    Reserved3       : 16;   // [63:48]
+  } AsBits;
+
+  UINT64    AsUint64;
+} AMD_MMIO_CFG_MSR;
+#pragma pack()
+
+/**
+  Reserve PCIe Extended Config Space MMIO in the GCD and mark it runtime
+
+  @param[in]  ImageHandle  ImageHandle of the loaded driver.
+  @param[in]  SystemTable  Pointer to the EFI System Table.
+
+  @retval  EFI_SUCCESS  One or more of the drivers returned a success code.
+  @retval  !EFI_SUCCESS  Error initializing the Legacy PIC.
+**/
+EFI_STATUS
+EFIAPI
+ReservePcieExtendedConfigSpace (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Prototype for callback function to patch ACPI table.
+
+  @param[in, out] NewTable            The pointer to ACPI table.
+  @return         EFI_SUCCESS         Always return EFI_SUCCESS
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PATCH_ACPITABLE)(
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  );
+
+/**
+  A helper function to update and re-install ACPI table.
+  It search for ACPI table for provided table signature,
+  if found then creates a copy of the table and invokes
+  the call back function.
+
+  @param[in] Signature           ACPI table signature
+  @param[in] CallbackFunction    The function to call to patch the searching ACPI table.
+
+  @return EFI_SUCCESS            Successfully Re-install the ACPI Table
+  @return EFI_NOT_FOUND          Table not found
+  @return EFI_STATUS             returns non-EFI_SUCCESS value in case of failure
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateReinstallAcpiTable (
+  IN UINT32           Signature,
+  IN PATCH_ACPITABLE  CallbackFunction
+  );
+
+/**
+  A Callback function to patch the ACPI FADT table.
+  Updates FADT table with AMD specific values, which
+  are different than MinPlatformPkg.
+
+  @param[in, out] NewTable       Pointer to ACPI FADT table
+
+  @return         EFI_SUCCESS    Always return EFI_SUCCESSe
+
+**/
+EFI_STATUS
+EFIAPI
+FadtAcpiTablePatch (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  );
+
+EFI_STATUS
+EFIAPI
+MadtAcpiTablePatch (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  );
+
+/**
+  A Callback function to patch the ACPI DSDT/SSDT table.
+  Which has ASL code that needs to be updated.
+
+  @param[in, out] NewTable       Pointer to ACPI FADT table
+
+  @return         EFI_SUCCESS    Always return EFI_SUCCESSe
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiTableAmlUpdate (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  );
+
+/**
+  Reserve Legacy VGA IO space.
+
+  @retval  EFI_SUCCESS  MMIO at Legacy VGA region has been allocated.
+  @retval  !EFI_SUCCESS Error allocating the legacy VGA region.
+
+**/
+EFI_STATUS
+EFIAPI
+ReserveLegacyVgaIoSpace (
+  VOID
+  );
+
+#endif
diff --git a/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/MadtAcpiTablePatch.c b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/MadtAcpiTablePatch.c
new file mode 100644
index 0000000000..aefb378981
--- /dev/null
+++ b/Platform/AMD/AmdMinBoardPkg/Library/DxeBoardInitLib/MadtAcpiTablePatch.c
@@ -0,0 +1,243 @@
+/** @file
+  This file patches the ACPI MADT table for AMD specific values.
+
+  Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "DxeBoardInitLibInternal.h"
+#include <Library/AmdPlatformSocLib.h>
+#include <Library/LocalApicLib.h>
+#define   AMD_CPUID_EXTENDED_TOPOLOGY_V2                 0x26
+#define   AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_CCX  0x03
+#define   AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_CCD  0x04
+#define   AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE  0x05
+
+UINT32  mCcdOrder[16] = { 0, 4, 8, 12, 2, 6, 10, 14, 3, 7, 11, 15, 1, 5, 9, 13 };
+
+/**
+  Callback compare function.
+  Compares CCD number of provided arguments.
+
+  @param[in] LocalX2ApicLeft   Pointer to Left Buffer.
+  @param[in] LocalX2ApicRight  Pointer to Right Buffer.
+  @return    0                 If both are same
+             -1                If left value is less than righ value.
+             1                 If left value is greater than righ value.
+
+**/
+INTN
+EFIAPI
+SortByCcd (
+  CONST VOID  *LocalX2ApicLeft,
+  CONST VOID  *LocalX2ApicRight
+  )
+{
+  CONST EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE  *Left;
+  CONST EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE  *Right;
+  EFI_CPU_PHYSICAL_LOCATION2                           LeftLocation;
+  EFI_CPU_PHYSICAL_LOCATION2                           RightLocation;
+  UINT32                                               LeftCcdIndex;
+  UINT32                                               RightCcdIndex;
+  UINT32                                               Index;
+
+  Left  = (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)LocalX2ApicLeft;
+  Right = (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)LocalX2ApicRight;
+
+  GetProcessorLocation2ByApicId (
+    Left->X2ApicId,
+    &LeftLocation.Package,
+    &LeftLocation.Die,
+    &LeftLocation.Tile,
+    &LeftLocation.Module,
+    &LeftLocation.Core,
+    &LeftLocation.Thread
+    );
+
+  GetProcessorLocation2ByApicId (
+    Right->X2ApicId,
+    &RightLocation.Package,
+    &RightLocation.Die,
+    &RightLocation.Tile,
+    &RightLocation.Module,
+    &RightLocation.Core,
+    &RightLocation.Thread
+    );
+
+  // Get the CCD Index number
+  LeftCcdIndex = MAX_UINT32;
+  for (Index = 0; Index < ARRAY_SIZE (mCcdOrder); Index++) {
+    if (LeftLocation.Die == mCcdOrder[Index]) {
+      LeftCcdIndex = Index;
+      break;
+    }
+  }
+
+  RightCcdIndex = MAX_UINT32;
+  for (Index = 0; Index < ARRAY_SIZE (mCcdOrder); Index++) {
+    if (RightLocation.Die == mCcdOrder[Index]) {
+      RightCcdIndex = Index;
+      break;
+    }
+  }
+
+  // Now compare for quick sort
+  if (LeftCcdIndex < RightCcdIndex) {
+    return -1;
+  }
+
+  if (LeftCcdIndex > RightCcdIndex) {
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+  A Callback function to patch the ACPI MADT table.
+  Updates MADT table with AMD specific values, which
+  are different than MinPlatformPkg.
+
+  @param[in, out] NewTable       Pointer to ACPI MADT table
+
+  @return         EFI_SUCCESS    Always return EFI_SUCCESSe
+
+**/
+EFI_STATUS
+EFIAPI
+MadtAcpiTablePatch (
+  IN OUT  EFI_ACPI_SDT_HEADER  *NewTable
+  )
+{
+  UINT32                                               Index;
+  EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER  *NewMadtTable;
+  UINT8                                                *TablePtr;
+  UINT64                                               Length;
+  EFI_ACPI_6_5_IO_APIC_STRUCTURE                       *NbioIoApic;
+  UINT8                                                IoApicCount;
+  UINTN                                                LapicCount;
+  EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE        *LocalX2ApicPtr;
+  EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE        *SortedItem;
+  EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE        *Src;
+  EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE        *Dst;
+
+  // Patch the Table
+  NewMadtTable                  = (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)NewTable;
+  NewMadtTable->Header.Revision = 6;
+  // Get the IoApic information
+  NbioIoApic     = NULL;
+  IoApicCount    = 0;
+  LapicCount     = 0;
+  LocalX2ApicPtr = NULL;
+  GetIoApicInfo (&NbioIoApic, &IoApicCount);
+  if ((NbioIoApic == NULL) || (IoApicCount == 0)) {
+    DEBUG ((DEBUG_INFO, "%a:%d Cannot obtain NBIO IOAPIC information.\n", __FUNCTION__, __LINE__));
+    return EFI_SUCCESS;
+  }
+
+  // Create MADT header
+  TablePtr = (UINT8 *)NewMadtTable;
+  TablePtr = TablePtr + sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+  Length   = sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+
+  // Get the IOAPIC structure
+  Index = 0;    // now holds the IoApic Index
+  do {
+    if (((STRUCTURE_HEADER *)TablePtr)->Type == EFI_ACPI_6_5_IO_APIC) {
+      // Patch the IoApic Strucure
+      if (Index >= IoApicCount) {
+        /// Mark the extra IOAPIC structure Type as reserved, so that OSPM can ignore it.
+        /// As per ACPI specification 6.5 for MADT table
+        /// Subtype 0x18-0x7F are reserved, OSPM skips structures of the reserved type.
+        ((EFI_ACPI_6_5_IO_APIC_STRUCTURE *)TablePtr)->Type = 0x7F;
+      } else {
+        ((EFI_ACPI_6_5_IO_APIC_STRUCTURE *)TablePtr)->IoApicId                  = NbioIoApic[Index].IoApicId;
+        ((EFI_ACPI_6_5_IO_APIC_STRUCTURE *)TablePtr)->IoApicAddress             = NbioIoApic[Index].IoApicAddress;
+        ((EFI_ACPI_6_5_IO_APIC_STRUCTURE *)TablePtr)->GlobalSystemInterruptBase = NbioIoApic[Index].GlobalSystemInterruptBase;
+      }
+
+      Index++;
+    }
+
+    if (((STRUCTURE_HEADER *)TablePtr)->Type == EFI_ACPI_6_5_INTERRUPT_SOURCE_OVERRIDE) {
+      // Patch Flags
+      ((EFI_ACPI_6_5_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)TablePtr)->Flags = 0xF;
+    }
+
+    if (((STRUCTURE_HEADER *)TablePtr)->Type == EFI_ACPI_6_5_LOCAL_X2APIC_NMI) {
+      // Patch  Flags - Edge-triggered, Active High
+      ((EFI_ACPI_6_5_LOCAL_X2APIC_NMI_STRUCTURE *)TablePtr)->Flags = 0x0005;
+    }
+
+    if (((STRUCTURE_HEADER *)TablePtr)->Type == EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC) {
+      if (LapicCount == 0) {
+        // Get the first entry pointer
+        LocalX2ApicPtr = (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)TablePtr;
+      }
+
+      LapicCount += 1;
+    }
+
+    Length   += ((STRUCTURE_HEADER *)TablePtr)->Length;
+    TablePtr += ((STRUCTURE_HEADER *)TablePtr)->Length;
+  } while (Length < NewMadtTable->Header.Length);
+
+  FreePool (NbioIoApic);
+
+  if (LocalX2ApicPtr != NULL) {
+    if (FixedPcdGet32 (PcdMaxCpuSocketCount) > 1) {
+      /// Sort by CCD location
+      PerformQuickSort (LocalX2ApicPtr, LapicCount/2, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE), SortByCcd);
+      PerformQuickSort (LocalX2ApicPtr+(LapicCount/2), LapicCount/2, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE), SortByCcd);
+    } else {
+      /// Sort by CCD location
+      PerformQuickSort (LocalX2ApicPtr, LapicCount, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE), SortByCcd);
+    }
+
+    /// Now allocate the Uid
+    SortedItem = LocalX2ApicPtr;
+    for (Index = 0; Index < LapicCount; Index++, SortedItem++) {
+      SortedItem->AcpiProcessorUid = Index;
+    }
+
+    // Now separate the second thread list
+    SortedItem = LocalX2ApicPtr + 1;
+    if ((SortedItem->X2ApicId & 0x1) == 0x1) {
+      // It has multi-thread on
+      SortedItem = NULL;
+      SortedItem = AllocateZeroPool (sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE) * LapicCount);
+      if (SortedItem == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Src = LocalX2ApicPtr;
+      Dst = SortedItem;
+      for (Index = 0; Index < LapicCount; Index++) {
+        if ((Src->X2ApicId & 0x1) == 0) {
+          CopyMem (Dst, Src, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE));
+          Src++;
+          Dst++;
+        } else {
+          Src++;
+        }
+      }
+
+      Src = LocalX2ApicPtr;
+      for (Index = 0; Index < LapicCount; Index++) {
+        if ((Src->X2ApicId & 0x1) == 1) {
+          CopyMem (Dst, Src, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE));
+          Src++;
+          Dst++;
+        } else {
+          Src++;
+        }
+      }
+
+      CopyMem (LocalX2ApicPtr, SortedItem, sizeof (EFI_ACPI_6_5_PROCESSOR_LOCAL_X2APIC_STRUCTURE) * LapicCount);
+      FreePool (SortedItem);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118977): https://edk2.groups.io/g/devel/message/118977
Mute This Topic: https://groups.io/mt/106148092/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-05-17  3:49 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-17  3:49 [edk2-devel] [PATCH 0/5] AmdMinBoardPkg: AMD board specific modules Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 1/5] AmdMinBoardPkg: Uncrustify PciHotPlug module Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 2/5] AmdMinBoardPkg/Library: Uncrustify the Library module Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` [edk2-devel] [PATCH 3/5] AmdMinBoardPkg: Implement BoardInitLib for PEI phase Abdul Lateef Attar via groups.io
2024-05-17  3:49 ` Abdul Lateef Attar via groups.io [this message]
2024-05-17  3:49 ` [edk2-devel] [PATCH 5/5] AmdMinBoardPkg: Implements BoardBdsHookLib library Abdul Lateef Attar via groups.io
2024-05-17  5:53 ` [edk2-devel] [PATCH 0/5] AmdMinBoardPkg: AMD board specific modules Chang, Abner via groups.io

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=fc284dcd746a7a7d061d866a24582fefe4deb7ea.1715917637.git.AbdulLateef.Attar@amd.com \
    --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