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 <elvin.li@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14932 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Elvin Li 2013-12-05 05:30:27 +00:00 committed by li-elvin
parent b4e7b2d2cd
commit b68237300a
5 changed files with 197 additions and 18 deletions

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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

View File

@ -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.<BR>
# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#
# 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]

View File

@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <FrameworkDxe.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/SmBios.h>
#include <Guid/SmBios.h>
#include <Guid/Acpi.h>

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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 (

View File

@ -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
);