X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxeIplPeim%2FDxeLoad.c;h=dea627e16282afc88bb9c5bb61c6c3d7468c4346;hb=a95b6045c32b8ea2c564c6848f00d785056dd56f;hp=fc485b9d24c37767411c46b7431ed430628ff755;hpb=6d3ea23f1183f3378a53e44d34c0a27aebec7d9a;p=mirror_edk2.git diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c index fc485b9d24..dea627e162 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -2,8 +2,8 @@ Last PEIM. Responsibility of this module is to load the DXE Core from a Firmware Volume. -Copyright (c) 2006 - 2009, Intel Corporation.
-All rights reserved. This program and the accompanying materials +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -124,6 +124,53 @@ PeimInitializeDxeIpl ( return Status; } +/** + Validate variable data for the MemoryTypeInformation. + + @param MemoryData Variable data. + @param MemoryDataSize Variable data length. + + @return TRUE The variable data is valid. + @return FALSE The variable data is invalid. + +**/ +BOOLEAN +ValidateMemoryTypeInfoVariable ( + IN EFI_MEMORY_TYPE_INFORMATION *MemoryData, + IN UINTN MemoryDataSize + ) +{ + UINTN Count; + UINTN Index; + + // Check the input parameter. + if (MemoryData == NULL) { + return FALSE; + } + + // Get Count + Count = MemoryDataSize / sizeof (*MemoryData); + + // Check Size + if (Count * sizeof(*MemoryData) != MemoryDataSize) { + return FALSE; + } + + // Check last entry type filed. + if (MemoryData[Count - 1].Type != EfiMaxMemoryType) { + return FALSE; + } + + // Check the type filed. + for (Index = 0; Index < Count - 1; Index++) { + if (MemoryData[Index].Type >= EfiMaxMemoryType) { + return FALSE; + } + } + + return TRUE; +} + /** Main entry point to last PEIM. @@ -154,7 +201,12 @@ DxeLoadCore ( EFI_BOOT_MODE BootMode; EFI_PEI_FILE_HANDLE FileHandle; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + EFI_PEI_LOAD_FILE_PPI *LoadFile; + UINTN Instance; + UINT32 AuthenticationState; UINTN DataSize; + EFI_PEI_S3_RESUME2_PPI *S3Resume; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; // @@ -163,10 +215,26 @@ DxeLoadCore ( BootMode = GetBootModeHob (); if (BootMode == BOOT_ON_S3_RESUME) { - Status = AcpiS3ResumeOs(); + Status = PeiServicesLocatePpi ( + &gEfiPeiS3Resume2PpiGuid, + 0, + NULL, + (VOID **) &S3Resume + ); + ASSERT_EFI_ERROR (Status); + + Status = S3Resume->S3RestoreConfig2 (S3Resume); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_IN_RECOVERY_MODE) { - Status = PeiRecoverFirmware (); + Status = PeiServicesLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **) &PeiRecovery + ); + ASSERT_EFI_ERROR (Status); + + Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status)); CpuDeadLoop (); @@ -193,7 +261,7 @@ DxeLoadCore ( &DataSize, &MemoryData ); - if (!EFI_ERROR (Status)) { + if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) { // // Build the GUID'd HOB for DXE // @@ -211,15 +279,25 @@ DxeLoadCore ( FileHandle = DxeIplFindDxeCore (); // - // Load the DXE Core from a Firmware Volume, may use LoadFile PPI to do this to save code size. + // Load the DXE Core from a Firmware Volume. // - Status = PeiLoadFile ( - FileHandle, - &DxeCoreAddress, - &DxeCoreSize, - &DxeCoreEntryPoint - ); - ASSERT_EFI_ERROR (Status); + Instance = 0; + do { + Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile); + // + // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully. + // + ASSERT_EFI_ERROR (Status); + + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint, + &AuthenticationState + ); + } while (EFI_ERROR (Status)); // // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name. @@ -240,7 +318,7 @@ DxeLoadCore ( // // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT // - REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdStatusCodeValuePeiHandoffToDxe)); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT)); DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint))); @@ -287,6 +365,9 @@ DxeIplFindDxeCore ( // If some error occurs here, then we cannot find any firmware // volume that may contain DxeCore. // + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT)); + } ASSERT_EFI_ERROR (Status); // @@ -309,95 +390,6 @@ DxeIplFindDxeCore ( } -/** - Loads and relocates a PE/COFF image into memory. - - @param FileHandle The image file handle - @param ImageAddress The base address of the relocated PE/COFF image - @param ImageSize The size of the relocated PE/COFF image - @param EntryPoint The entry point of the relocated PE/COFF image - - @return EFI_SUCCESS The file was loaded and relocated - @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file - -**/ -EFI_STATUS -PeiLoadFile ( - IN EFI_PEI_FILE_HANDLE FileHandle, - OUT EFI_PHYSICAL_ADDRESS *ImageAddress, - OUT UINT64 *ImageSize, - OUT EFI_PHYSICAL_ADDRESS *EntryPoint - ) -{ - - EFI_STATUS Status; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - VOID *Pe32Data; - - // - // First try to find the PE32 section in this ffs file. - // - Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_PE32, - FileHandle, - &Pe32Data - ); - if (EFI_ERROR (Status)) { - // - // NO image types we support so exit. - // - return Status; - } - - ZeroMem (&ImageContext, sizeof (ImageContext)); - ImageContext.Handle = Pe32Data; - ImageContext.ImageRead = PeiImageRead; - - - Status = PeCoffLoaderGetImageInfo (&ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Allocate Memory for the image - // - Status = PeiServicesAllocatePages ( - EfiBootServicesCode, - EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), - &ImageContext.ImageAddress - ); - ASSERT_EFI_ERROR (Status); - ASSERT (ImageContext.ImageAddress != 0); - - // - // Load the image to our new buffer - // - Status = PeCoffLoaderLoadImage (&ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Relocate the image in our new buffer - // - Status = PeCoffLoaderRelocateImage (&ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Flush the instruction cache so the image data are written before we execute it - // - InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize); - - *ImageAddress = ImageContext.ImageAddress; - *ImageSize = ImageContext.ImageSize; - *EntryPoint = ImageContext.EntryPoint; - - return EFI_SUCCESS; -} - - - /** The ExtractSection() function processes the input section and @@ -568,82 +560,102 @@ Decompress ( EFI_STATUS Status; UINT8 *DstBuffer; UINT8 *ScratchBuffer; - UINTN DstBufferSize; + UINT32 DstBufferSize; UINT32 ScratchBufferSize; - EFI_COMMON_SECTION_HEADER *Section; - UINTN SectionLength; + VOID *CompressionSource; + UINT32 CompressionSourceSize; + UINT32 UncompressedLength; + UINT8 CompressionType; if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) { ASSERT (FALSE); return EFI_INVALID_PARAMETER; } - Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection; - SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + if (IS_SECTION2 (CompressionSection)) { + CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2)); + CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2)); + UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength; + CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType; + } else { + CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION)); + CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION)); + UncompressedLength = CompressionSection->UncompressedLength; + CompressionType = CompressionSection->CompressionType; + } // // This is a compression set, expand it // - switch (CompressionSection->CompressionType) { + switch (CompressionType) { case EFI_STANDARD_COMPRESSION: - // - // Load EFI standard compression. - // For compressed data, decompress them to destination buffer. - // - Status = UefiDecompressGetInfo ( - (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), - (UINT32 *) &DstBufferSize, - &ScratchBufferSize - ); - if (EFI_ERROR (Status)) { + if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) { // - // GetInfo failed + // Load EFI standard compression. + // For compressed data, decompress them to destination buffer. // - DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status)); - return EFI_NOT_FOUND; - } - // - // Allocate scratch buffer - // - ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); - if (ScratchBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Allocate destination buffer, extra one page for adjustment - // - DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); - if (DstBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header - // to make section data at page alignment. - // - DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER); - // - // Call decompress function - // - Status = UefiDecompress ( - (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - DstBuffer, - ScratchBuffer - ); - if (EFI_ERROR (Status)) { + Status = UefiDecompressGetInfo ( + CompressionSource, + CompressionSourceSize, + &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate destination buffer, extra one page for adjustment + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } // - // Decompress failed + // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header + // to make section data at page alignment. // - DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status)); + DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER); + // + // Call decompress function + // + Status = UefiDecompress ( + CompressionSource, + DstBuffer, + ScratchBuffer + ); + if (EFI_ERROR (Status)) { + // + // Decompress failed + // + DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + break; + } else { + // + // PcdDxeIplSupportUefiDecompress is FALSE + // Don't support UEFI decompression algorithm. + // + ASSERT (FALSE); return EFI_NOT_FOUND; } - break; case EFI_NOT_COMPRESSED: // // Allocate destination buffer // - DstBufferSize = CompressionSection->UncompressedLength; + DstBufferSize = UncompressedLength; DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); if (DstBuffer == NULL) { return EFI_OUT_OF_RESOURCES; @@ -656,7 +668,7 @@ Decompress ( // // stream is not actually compressed, just encapsulated. So just copy it. // - CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize); + CopyMem (DstBuffer, CompressionSource, DstBufferSize); break; default: @@ -696,13 +708,14 @@ UpdateStackHob ( while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { // - // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type - // to be reclaimed by DXE core. + // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to + // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some + // PEIMs may also keep key information on stack // BuildMemoryAllocationHob ( Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress, Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength, - EfiConventionalMemory + EfiBootServicesData ); // // Update the BSP Stack Hob to reflect the new stack info.