From b68237300a036c59dcb1231708e64e12fd2f734f Mon Sep 17 00:00:00 2001 From: Elvin Li Date: Thu, 5 Dec 2013 05:30:27 +0000 Subject: [PATCH] Following UEFI spec, update SmbiosDxe to use EfiRuntimeServicesData to put SMBIOS table. Update LegacyBiosDxe to move SMBIOS table to reserved memory for backward compatibility. Signed-off-by: Elvin Li Reviewed-by: Jiewen Yao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14932 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Csm/LegacyBiosDxe/LegacyBios.c | 125 +++++++++++++++++- .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 3 +- .../Csm/LegacyBiosDxe/LegacyBiosInterface.h | 1 + .../Csm/LegacyBiosDxe/LegacyBootSupport.c | 78 +++++++++-- MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c | 8 +- 5 files changed, 197 insertions(+), 18 deletions(-) diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c index 99a76c9f21..452487b66c 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c @@ -1,6 +1,6 @@ /** @file -Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -29,6 +29,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // LEGACY_BIOS_INSTANCE mPrivateData; +// +// The SMBIOS table in EfiRuntimeServicesData memory +// +VOID *mRuntimeSmbiosEntryPoint = NULL; + +// +// The SMBIOS table in EfiReservedMemoryType memory +// +EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0; +EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0; +UINTN mStructureTablePages = 0; + /** Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode memory. @@ -661,6 +673,98 @@ GetPciInterfaceVersion ( return PciInterfaceVersion; } +/** + Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table. + SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path. + + @param Event Event whose notification function is being invoked. + @param Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +InstallSmbiosEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + // + // Get SMBIOS table from EFI configuration table + // + Status = EfiGetSystemConfigurationTable ( + &gEfiSmbiosTableGuid, + &mRuntimeSmbiosEntryPoint + ); + if (EFI_ERROR (Status)) { + return; + } + + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; + + // + // Allocate memory for SMBIOS Entry Point Structure. + // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE. + // + if (mReserveSmbiosEntryPoint == 0) { + // + // Entrypoint structure with fixed size is allocated only once. + // + mReserveSmbiosEntryPoint = SIZE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)), + &mReserveSmbiosEntryPoint + ); + if (EFI_ERROR (Status)) { + mReserveSmbiosEntryPoint = 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n")); + } + + if ((mStructureTableAddress != 0) && + (mStructureTablePages < (UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength))) { + // + // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate + // + gBS->FreePages (mStructureTableAddress, mStructureTablePages); + mStructureTableAddress = 0; + mStructureTablePages = 0; + DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n")); + } + + if (mStructureTableAddress == 0) { + // + // Allocate reserved memory below 4GB. + // Smbios spec requires the structure table is below 4GB. + // + mStructureTableAddress = SIZE_4GB - 1; + mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + mStructureTablePages, + &mStructureTableAddress + ); + if (EFI_ERROR (Status)) { + gBS->FreePages ( + mReserveSmbiosEntryPoint, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)) + ); + mReserveSmbiosEntryPoint = 0; + mStructureTableAddress = 0; + mStructureTablePages = 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n")); + } +} + /** Install Driver to produce Legacy BIOS protocol. @@ -697,6 +801,7 @@ LegacyBiosInstall ( EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINT64 Length; UINT8 *SecureBoot; + EFI_EVENT InstallSmbiosEvent; // // Load this driver's image to memory @@ -1009,6 +1114,24 @@ LegacyBiosInstall ( // Save EFI value // Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode)); + + // + // Allocate reserved memory for SMBIOS table used in legacy boot if SMBIOS table exists + // + InstallSmbiosEventCallback (NULL, NULL); + + // + // Create callback function to update the size of reserved memory after LegacyBiosDxe starts + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + InstallSmbiosEventCallback, + NULL, + &gEfiSmbiosTableGuid, + &InstallSmbiosEvent + ); + ASSERT_EFI_ERROR (Status); // // Make a new handle and install the protocol diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf index a5ad0dfd26..e3084e601f 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf @@ -3,7 +3,7 @@ # # This driver installs Legacy Bios Protocol to support CSM module work in EFI system. # -# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions @@ -103,6 +103,7 @@ [Guids] gEfiDiskInfoIdeInterfaceGuid # ALWAYS_CONSUMED + gEfiSmbiosTableGuid # ALWAYS_CONSUMED gEfiLegacyBiosGuid # ALWAYS_PRODUCED [Guids.IA32] diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h index d60851a42c..cc893a49a7 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h @@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include #include #include diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c index dfdac356cf..bf27605504 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c @@ -1,6 +1,6 @@ /** @file -Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -33,6 +33,10 @@ UINT64 mLowWater = 0xffffffffffffffffULL; extern BBS_TABLE *mBbsTable; +extern VOID *mRuntimeSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mStructureTableAddress; + /** Print the BBS Table. @@ -777,6 +781,63 @@ LegacyGetDataOrTable ( return EFI_SUCCESS; } +/** + Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot. + +**/ +VOID +CreateSmbiosTableInReservedMemory ( + VOID + ) +{ + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + if ((mRuntimeSmbiosEntryPoint == NULL) || + (mReserveSmbiosEntryPoint == 0) || + (mStructureTableAddress == 0)) { + return; + } + + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint; + + // + // Copy SMBIOS Entry Point Structure + // + CopyMem ( + (VOID *)(UINTN) mReserveSmbiosEntryPoint, + EntryPointStructure, + EntryPointStructure->EntryPointLength + ); + + // + // Copy SMBIOS Structure Table into EfiReservedMemoryType memory + // + CopyMem ( + (VOID *)(UINTN) mStructureTableAddress, + (VOID *)(UINTN) EntryPointStructure->TableAddress, + EntryPointStructure->TableLength + ); + + // + // Update TableAddress in Entry Point Structure + // + EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbiosEntryPoint; + EntryPointStructure->TableAddress = (UINT32)(UINTN) mStructureTableAddress; + + // + // Fixup checksums in the Entry Point Structure + // + EntryPointStructure->IntermediateChecksum = 0; + EntryPointStructure->EntryPointStructureChecksum = 0; + + EntryPointStructure->IntermediateChecksum = + CalculateCheckSum8 ( + (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString), + EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString) + ); + EntryPointStructure->EntryPointStructureChecksum = + CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength); +} /** Assign drive number to legacy HDD drives prior to booting an EFI @@ -815,7 +876,6 @@ GenericLegacyBoot ( EFI_HANDLE IdeController; UINTN HandleCount; EFI_HANDLE *HandleBuffer; - VOID *SmbiosTable; VOID *AcpiTable; UINTN ShadowAddress; UINT32 Granularity; @@ -904,21 +964,15 @@ GenericLegacyBoot ( ); Private->Legacy16Table->E820Length = (UINT32) CopySize; } - // - // Get SMBIOS and ACPI table pointers - // - SmbiosTable = NULL; - EfiGetSystemConfigurationTable ( - &gEfiSmbiosTableGuid, - &SmbiosTable - ); + // // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable. // - if (SmbiosTable == NULL) { + if (mReserveSmbiosEntryPoint == 0) { DEBUG ((EFI_D_INFO, "Smbios table is not found!\n")); } - EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)SmbiosTable; + CreateSmbiosTableInReservedMemory (); + EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)mReserveSmbiosEntryPoint; AcpiTable = NULL; Status = EfiGetSystemConfigurationTable ( diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c index 8bf5d443a1..329bdbfc49 100644 --- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c +++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c @@ -981,7 +981,7 @@ SmbiosCreateTable ( PhysicalAddress = 0xffffffff; Status = gBS->AllocatePages ( AllocateMaxAddress, - EfiReservedMemoryType, + EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength), &PhysicalAddress ); @@ -1093,7 +1093,7 @@ SmbiosDriverEntryPoint ( PhysicalAddress = 0xffffffff; Status = gBS->AllocatePages ( AllocateMaxAddress, - EfiReservedMemoryType, + EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)), &PhysicalAddress ); @@ -1101,7 +1101,7 @@ SmbiosDriverEntryPoint ( DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate EntryPointStructure < 4GB\n")); Status = gBS->AllocatePages ( AllocateAnyPages, - EfiReservedMemoryType, + EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)), &PhysicalAddress ); @@ -1127,7 +1127,7 @@ SmbiosDriverEntryPoint ( PhysicalAddress = 0xffffffff; Status = gBS->AllocatePages ( AllocateMaxAddress, - EfiReservedMemoryType, + EfiRuntimeServicesData, 1, &PhysicalAddress ); -- 2.39.2