X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=IntelFrameworkModulePkg%2FCsm%2FLegacyBiosDxe%2FLegacyBios.c;h=8f14687b28335988844407e9e5fb3dd10afa80d0;hb=cb9ee5a14180ba44581c0bf5089bf13e500e6494;hp=99a76c9f21acdd7b12f340621615c91122af8104;hpb=3e5eb447019c1ffcd3d28f2221cacf087174b119;p=mirror_edk2.git diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c index 99a76c9f21..8f14687b28 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 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -29,11 +29,24 @@ 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; +BOOLEAN mEndOfDxe = FALSE; + /** - Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode - memory. + Allocate memory for legacy usage. - @param AllocateType Allocated Legacy Memory Type + @param AllocateType The type of allocation to perform. + @param MemoryType The type of memory to allocate. @param StartPageAddress Start address of range @param Pages Number of pages to allocate @param Result Result of allocation @@ -45,6 +58,7 @@ LEGACY_BIOS_INSTANCE mPrivateData; EFI_STATUS AllocateLegacyMemory ( IN EFI_ALLOCATE_TYPE AllocateType, + IN EFI_MEMORY_TYPE MemoryType, IN EFI_PHYSICAL_ADDRESS StartPageAddress, IN UINTN Pages, OUT EFI_PHYSICAL_ADDRESS *Result @@ -59,7 +73,7 @@ AllocateLegacyMemory ( MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress; Status = gBS->AllocatePages ( AllocateType, - EfiBootServicesCode, + MemoryType, Pages, &MemPage ); @@ -132,7 +146,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; @@ -257,7 +271,7 @@ ShadowAndStartLegacy16 ( if (EFI_ERROR (Status)) { // // Bugbug: need to figure out whether C/D/E/F segment should be marked as reserved memory. - // + // DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = %r", Status)); } } @@ -401,7 +415,7 @@ ShadowAndStartLegacy16 ( Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); NewMask = 0xFFFF; Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, NULL); - + // // Call into Legacy16 code to do an INIT // @@ -423,7 +437,7 @@ ShadowAndStartLegacy16 ( // Restore original legacy interrupt mask value // Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL); - + if (Regs.X.AX != 0) { return EFI_DEVICE_ERROR; } @@ -639,7 +653,7 @@ GetPciInterfaceVersion ( UINT16 PciInterfaceVersion; PciInterfaceVersion = 0; - + Reg.X.AX = 0xB101; Reg.E.EDI = 0; @@ -661,6 +675,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. @@ -697,6 +823,8 @@ LegacyBiosInstall ( EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINT64 Length; UINT8 *SecureBoot; + EFI_EVENT InstallSmbiosEvent; + EFI_EVENT EndOfDxeEvent; // // Load this driver's image to memory @@ -715,7 +843,7 @@ LegacyBiosInstall ( FreePool (SecureBoot); return EFI_SECURITY_VIOLATION; } - + if (SecureBoot != NULL) { FreePool (SecureBoot); } @@ -847,6 +975,7 @@ LegacyBiosInstall ( // AllocateLegacyMemory ( AllocateAddress, + EfiReservedMemoryType, 0, 1, &MemoryAddress @@ -859,8 +988,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 @@ -870,6 +1001,7 @@ LegacyBiosInstall ( Status = AllocateLegacyMemory ( AllocateAddress, + EfiReservedMemoryType, CONVENTIONAL_MEMORY_TOP - MemorySize, EFI_SIZE_TO_PAGES (MemorySize), &MemoryAddress @@ -898,12 +1030,13 @@ LegacyBiosInstall ( for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) { Status = AllocateLegacyMemory ( AllocateAddress, + EfiBootServicesCode, 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)); @@ -914,9 +1047,10 @@ LegacyBiosInstall ( // Allocate low PMM memory and zero it out // MemorySize = PcdGet32 (PcdLowPmmMemorySize); - ASSERT ((MemorySize & 0xFFF) == 0); + ASSERT ((MemorySize & 0xFFF) == 0); Status = AllocateLegacyMemory ( AllocateMaxAddress, + EfiBootServicesCode, CONVENTIONAL_MEMORY_TOP, EFI_SIZE_TO_PAGES (MemorySize), &MemoryAddressUnder1MB @@ -930,6 +1064,7 @@ LegacyBiosInstall ( // Status = AllocateLegacyMemory ( AllocateMaxAddress, + EfiReservedMemoryType, CONVENTIONAL_MEMORY_TOP, (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2, &MemoryAddress @@ -954,9 +1089,10 @@ LegacyBiosInstall ( ASSERT ((MemorySize & 0xFFF) == 0); // // Allocate high PMM Memory under 16 MB - // + // Status = AllocateLegacyMemory ( AllocateMaxAddress, + EfiBootServicesCode, 0x1000000, EFI_SIZE_TO_PAGES (MemorySize), &MemoryAddress @@ -964,18 +1100,19 @@ LegacyBiosInstall ( if (EFI_ERROR (Status)) { // // If it fails, allocate high PMM Memory under 4GB - // + // Status = AllocateLegacyMemory ( AllocateMaxAddress, + EfiBootServicesCode, 0xFFFFFFFF, EFI_SIZE_TO_PAGES (MemorySize), &MemoryAddress - ); + ); } if (!EFI_ERROR (Status)) { EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize; - } + } // // ShutdownAPs(); @@ -999,17 +1136,52 @@ 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 // @@ -1021,9 +1193,9 @@ LegacyBiosInstall ( &Private->LegacyBios ); Private->Csm16PciInterfaceVersion = GetPciInterfaceVersion (Private); - - DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", - (UINT8) (Private->Csm16PciInterfaceVersion >> 8), + + DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", + (UINT8) (Private->Csm16PciInterfaceVersion >> 8), (UINT8) Private->Csm16PciInterfaceVersion )); ASSERT (Private->Csm16PciInterfaceVersion != 0);