X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=IntelFrameworkModulePkg%2FCsm%2FLegacyBiosDxe%2FLegacyBios.c;h=fca08a8fa26d4be275576f8b6156290f96a9e5fc;hp=75add5e39ded6f9712569fc35d54fb8aa1afd7f5;hb=2ea3576e16a2af9e21e06ef4b759833989efced2;hpb=bcecde140a561c64e297225904afebebd62336ce
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
index 75add5e39d..fca08a8fa2 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -30,9 +30,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
LEGACY_BIOS_INSTANCE mPrivateData;
//
-// The end of OPROM shadow address
+// The SMBIOS table in EfiRuntimeServicesData memory
//
-UINTN mEndOpromShadowAddress = 0;
+VOID *mRuntimeSmbiosEntryPoint = NULL;
+
+//
+// The SMBIOS table in EfiReservedMemoryType memory
+//
+EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0;
+EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0;
+UINTN mStructureTablePages = 0;
+BOOLEAN mEndOfDxe = FALSE;
/**
Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode
@@ -137,7 +145,7 @@ LegacyBiosGetLegacyRegion (
);
if (Regs.X.AX == 0) {
- *LegacyMemoryAddress = (VOID *) (UINTN) ((Regs.X.DS << 4) + Regs.X.BX);
+ *LegacyMemoryAddress = (VOID *) (((UINTN) Regs.X.DS << 4) + Regs.X.BX);
Status = EFI_SUCCESS;
} else {
Status = EFI_OUT_OF_RESOURCES;
@@ -387,23 +395,6 @@ ShadowAndStartLegacy16 (
//
Table->EfiSystemTable = (UINT32) (UINTN) gST;
- //
- // Get the end of OPROM shadow address
- //
- Status = Private->LegacyBiosPlatform->GetPlatformInfo (
- Private->LegacyBiosPlatform,
- EfiGetPlatformEndOpromShadowAddr,
- NULL,
- NULL,
- &mEndOpromShadowAddress,
- NULL,
- 0,
- 0
- );
- if (EFI_ERROR (Status)) {
- mEndOpromShadowAddress = 0xDFFFF;
- }
-
//
// IPF CSM integration -Bug
//
@@ -683,6 +674,118 @@ 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)) || (mRuntimeSmbiosEntryPoint == NULL)) {
+ 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 < EFI_SIZE_TO_PAGES ((UINT32)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"));
+ }
+}
+
+/**
+ Callback function to toggle EndOfDxe status. NULL pointer detection needs
+ this status to decide if it's necessary to change attributes of page 0.
+
+ @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
+ToggleEndOfDxeStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mEndOfDxe = TRUE;
+ return;
+}
+
/**
Install Driver to produce Legacy BIOS protocol.
@@ -704,6 +807,7 @@ LegacyBiosInstall (
LEGACY_BIOS_INSTANCE *Private;
EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;
EFI_PHYSICAL_ADDRESS MemoryAddress;
+ EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress;
VOID *MemoryPtr;
EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB;
UINTN Index;
@@ -717,6 +821,9 @@ LegacyBiosInstall (
UINT32 MemorySize;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
UINT64 Length;
+ UINT8 *SecureBoot;
+ EFI_EVENT InstallSmbiosEvent;
+ EFI_EVENT EndOfDxeEvent;
//
// Load this driver's image to memory
@@ -726,6 +833,20 @@ LegacyBiosInstall (
return Status;
}
+ //
+ // When UEFI Secure Boot is enabled, CSM module will not start any more.
+ //
+ SecureBoot = NULL;
+ GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);
+ if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) {
+ FreePool (SecureBoot);
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ if (SecureBoot != NULL) {
+ FreePool (SecureBoot);
+ }
+
Private = &mPrivateData;
ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE));
@@ -736,6 +857,9 @@ LegacyBiosInstall (
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Private->Cpu);
ASSERT_EFI_ERROR (Status);
+ Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Private->Timer);
+ ASSERT_EFI_ERROR (Status);
+
Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Private->LegacyRegion);
ASSERT_EFI_ERROR (Status);
@@ -862,8 +986,10 @@ LegacyBiosInstall (
// Initialize region from 0x0000 to 4k. This initializes interrupt vector
// range.
//
- gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
- ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+ ACCESS_PAGE0_CODE (
+ gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
+ ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+ );
//
// Allocate pages for OPROM usage
@@ -884,17 +1010,29 @@ LegacyBiosInstall (
//
// Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that
// don't use PMM but look for zeroed memory. Note that various non-BBS
- // SCSIs expect different areas to be free
+ // OpROMs expect different areas to be free
+ //
+ EbdaReservedBaseAddress = MemoryAddress;
+ MemoryAddress = PcdGet32 (PcdOpromReservedMemoryBase);
+ MemorySize = PcdGet32 (PcdOpromReservedMemorySize);
+ //
+ // Check if base address and size for reserved memory are 4KB aligned.
//
- for (MemStart = 0x60000; MemStart < 0x88000; MemStart += 0x1000) {
+ ASSERT ((MemoryAddress & 0xFFF) == 0);
+ ASSERT ((MemorySize & 0xFFF) == 0);
+ //
+ // Check if the reserved memory is below EBDA reserved range.
+ //
+ ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + MemorySize - 1) < EbdaReservedBaseAddress));
+ for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) {
Status = AllocateLegacyMemory (
AllocateAddress,
MemStart,
1,
- &MemoryAddress
+ &StartAddress
);
if (!EFI_ERROR (Status)) {
- MemoryPtr = (VOID *) ((UINTN) MemoryAddress);
+ MemoryPtr = (VOID *) ((UINTN) StartAddress);
ZeroMem (MemoryPtr, 0x1000);
} else {
DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart));
@@ -902,17 +1040,19 @@ LegacyBiosInstall (
}
//
- // Allocate a 64k area (16 4k pages) for 16-bit code for scratch pad and zero it out
+ // Allocate low PMM memory and zero it out
//
+ MemorySize = PcdGet32 (PcdLowPmmMemorySize);
+ ASSERT ((MemorySize & 0xFFF) == 0);
Status = AllocateLegacyMemory (
AllocateMaxAddress,
CONVENTIONAL_MEMORY_TOP,
- 16,
+ EFI_SIZE_TO_PAGES (MemorySize),
&MemoryAddressUnder1MB
);
ASSERT_EFI_ERROR (Status);
- ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), 0x10000);
+ ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), MemorySize);
//
// Allocate space for thunker and Init Thunker
@@ -937,21 +1077,34 @@ LegacyBiosInstall (
//
EfiToLegacy16InitTable->BiosLessThan1MB = (UINT32) MemoryAddressUnder1MB;
EfiToLegacy16InitTable->LowPmmMemory = (UINT32) MemoryAddressUnder1MB;
- EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = 0x10000;
+ EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = MemorySize;
+ MemorySize = PcdGet32 (PcdHighPmmMemorySize);
+ ASSERT ((MemorySize & 0xFFF) == 0);
//
- // Allocate 4 MB of PMM Memory under 16 MB
- //
+ // Allocate high PMM Memory under 16 MB
+ //
Status = AllocateLegacyMemory (
AllocateMaxAddress,
0x1000000,
- 0x400,
+ EFI_SIZE_TO_PAGES (MemorySize),
&MemoryAddress
);
+ if (EFI_ERROR (Status)) {
+ //
+ // If it fails, allocate high PMM Memory under 4GB
+ //
+ Status = AllocateLegacyMemory (
+ AllocateMaxAddress,
+ 0xFFFFFFFF,
+ EFI_SIZE_TO_PAGES (MemorySize),
+ &MemoryAddress
+ );
+ }
if (!EFI_ERROR (Status)) {
EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress;
- EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = PMM_MEMORY_SIZE;
- }
+ EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize;
+ }
//
// ShutdownAPs();
@@ -975,16 +1128,51 @@ LegacyBiosInstall (
//
// Save Unexpected interrupt vector so can restore it just prior to boot
//
- BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
- Private->BiosUnexpectedInt = BaseVectorMaster[0];
- IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;
- for (Index = 0; Index < 8; Index++) {
- BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);
- }
+ ACCESS_PAGE0_CODE (
+ BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
+ Private->BiosUnexpectedInt = BaseVectorMaster[0];
+ IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;
+ for (Index = 0; Index < 8; Index++) {
+ BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);
+ }
+ );
+
//
// 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);
+
+ //
+ // Create callback to update status of EndOfDxe, which is needed by NULL
+ // pointer detection
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ToggleEndOfDxeStatus,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
//
// Make a new handle and install the protocol