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