X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FCore%2FDxeIplX64Peim%2FDxeLoadX64.c;h=8e4f1126b69c1121822af0a14ef741003b3a69c5;hp=4015222036eee951fa1f98689c90a58a6495d85f;hb=5ab95f33d1a22fbb28697d559eb04c916d83743d;hpb=fc198a79e05d1e9fe6099f5284a1cd2aba0f0410 diff --git a/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c b/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c index 4015222036..8e4f1126b6 100644 --- a/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c +++ b/EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c @@ -62,17 +62,17 @@ static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { NULL }; -DECOMPRESS_LIBRARY gEfiDecompress = { +GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = { UefiDecompressGetInfo, UefiDecompress }; -DECOMPRESS_LIBRARY gTianoDecompress = { +GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress = { TianoDecompressGetInfo, TianoDecompress }; -DECOMPRESS_LIBRARY gCustomDecompress = { +GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = { CustomDecompressGetInfo, CustomDecompress }; @@ -207,7 +207,9 @@ Returns: EFI_PHYSICAL_ADDRESS BaseOfStack; EFI_PHYSICAL_ADDRESS BspStore; EFI_GUID DxeCoreFileName; + EFI_GUID FirmwareFileName; VOID *DxeCorePe32Data; + VOID *FvImageData; EFI_PHYSICAL_ADDRESS DxeCoreAddress; UINT64 DxeCoreSize; EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; @@ -257,11 +259,21 @@ Returns: ASSERT (BaseOfStack != 0); // - // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes - // for safety (PpisNeededByDxe and DxeCore). + // Compute the top of the stack we were allocated, which is used to load X64 dxe core. + // Pre-allocate a 32 bytes which confroms to x64 calling convention. + // + // The first four parameters to a function are passed in rcx, rdx, r8 and r9. + // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the + // register parameters is reserved on the stack, in case the called function + // wants to spill them; this is important if the function is variadic. // TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + // + // X64 Calling Conventions requires that the stack must be aligned to 16 bytes + // + TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16); + // // Add architecture-specifc HOBs (including the BspStore HOB) // @@ -288,6 +300,18 @@ Returns: } } + // + // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file + // The file found will be processed by PeiProcessFile: It will first be decompressed to + // a normal FV, then a corresponding FV type hob will be built. + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + &FirmwareFileName, + &FvImageData + ); + // // Find the DXE Core in a Firmware Volume // @@ -300,8 +324,9 @@ Returns: ASSERT_EFI_ERROR (Status); // - // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \ + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA // memory, it may be corrupted when copying FV to high-end memory + // LoadGo64Gdt(); // @@ -418,10 +443,11 @@ Returns: FwVolHeader = NULL; FfsFileHeader = NULL; SectionData = NULL; + Status = EFI_SUCCESS; // - // Foreach Firmware Volume, look for a specified type - // of file and break out when one is found + // For each Firmware Volume, look for a specified type + // of file and break out until no one is found // Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { @@ -434,11 +460,14 @@ Returns: if (!EFI_ERROR (Status)) { Status = PeiProcessFile ( SectionType, - &FfsFileHeader, - Pe32Data + FfsFileHeader, + Pe32Data, + &Hob ); CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); - return Status; + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } } Hob.Raw = GET_NEXT_HOB (Hob); } @@ -649,8 +678,9 @@ Returns: // Status = PeiProcessFile ( EFI_SECTION_PE32, - &FfsHeader, - &Pe32Data + FfsHeader, + &Pe32Data, + NULL ); if (EFI_ERROR (Status)) { @@ -674,8 +704,9 @@ Returns: EFI_STATUS PeiProcessFile ( IN UINT16 SectionType, - IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader, - OUT VOID **Pe32Data + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data, + IN EFI_PEI_HOB_POINTERS *OrigHob ) /*++ @@ -723,9 +754,7 @@ Returns: EFI_GUID TempGuid; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; EFI_COMPRESSION_SECTION *CompressionSection; - EFI_FFS_FILE_HEADER *FfsFileHeader; - - FfsFileHeader = *RealFfsFileHeader; + UINT32 FvAlignment; Status = PeiServicesFfsFindSectionData ( EFI_SECTION_COMPRESSION, @@ -734,7 +763,7 @@ Returns: ); // - // Upon finding a DXE Core file, see if there is first a compression section + // First process the compression section // if (!EFI_ERROR (Status)) { // @@ -842,14 +871,24 @@ Returns: switch (CompressionSection->CompressionType) { case EFI_STANDARD_COMPRESSION: - DecompressLibrary = &gTianoDecompress; + if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) { + DecompressLibrary = &gTianoDecompress; + } else { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } break; case EFI_CUSTOMIZED_COMPRESSION: // // Load user customized compression protocol. // - DecompressLibrary = &gCustomDecompress; + if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) { + DecompressLibrary = &gCustomDecompress; + } else { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } break; case EFI_NOT_COMPRESSED: @@ -900,31 +939,64 @@ Returns: ); CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; - if (CmpSection->Type == EFI_SECTION_RAW) { - // - // Skip the section header and - // adjust the pointer alignment to 16 + if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + // + // Firmware Volume Image in this Section + // Skip the section header to get FvHeader // - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16); + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1); - if (FvHeader->Signature == EFI_FVH_SIGNATURE) { - FfsFileHeader = NULL; + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + // + // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header + // + + // + // When FvImage support Alignment, we need to check whether + // its alignment is correct. + // + if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) { + + // + // Calculate the mini alignment for this FvImage + // + FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1); + + // + // If current FvImage base address doesn't meet the its alignment, + // we need to reload this FvImage to another correct memory address. + // + if (((UINTN) FvHeader % FvAlignment) != 0) { + DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength); + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; + } + } + // + // Build new FvHob for new decompressed Fv image. + // BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); - Status = PeiServicesFfsFindNextFile ( - EFI_FV_FILETYPE_DXE_CORE, - FvHeader, - &FfsFileHeader - ); - - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; + + // + // Set the original FvHob to unused. + // + if (OrigHob != NULL) { + OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED; } - + // - // Reture the FfsHeader that contain Pe32Data. + // when search FvImage Section return true. // - *RealFfsFileHeader = FfsFileHeader; - return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data); + if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + *Pe32Data = (VOID *) FvHeader; + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } + } } // @@ -947,6 +1019,9 @@ Returns: CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); } + // + // End of the decompression activity + // Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); FileSize = FfsFileHeader->Size[0] & 0xFF; @@ -954,11 +1029,17 @@ Returns: FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; FileSize &= 0x00FFFFFF; } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); - + // - // End of the decompression activity + // search all sections (compression and non compression) in this FFS, don't + // find expected section. // + return EFI_NOT_FOUND; } else { + // + // For those FFS that doesn't contain compression section, directly search + // PE or TE section in this FFS. + // Status = PeiServicesFfsFindSectionData ( EFI_SECTION_PE32, @@ -981,4 +1062,5 @@ Returns: *Pe32Data = SectionData; return EFI_SUCCESS; -} \ No newline at end of file +} +