dxeload.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,324 行 · 第 1/3 页
C
1,324 行
IN EFI_PEI_FV_FILE_LOADER_PPI *This,
IN EFI_FFS_FILE_HEADER *FfsHeader,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
)
/*++
Routine Description:
Given a pointer to an FFS file containing a PE32 image, get the
information on the PE32 image, and then "load" it so that it
can be executed.
Arguments:
This - pointer to our file loader protocol
FfsHeader - pointer to the FFS file header of the FFS file that
contains the PE32 image we want to load
ImageAddress - returned address where the PE32 image is loaded
ImageSize - returned size of the loaded PE32 image
EntryPoint - entry point to the loaded PE32 image
Returns:
EFI_SUCCESS - The FFS file was successfully loaded.
EFI_ERROR - Unable to load the FFS file.
--*/
{
EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *PeiEfiPeiFlushInstructionCache;
EFI_STATUS Status;
VOID *Pe32Data;
Pe32Data = NULL;
InstallEfiPeiFlushInstructionCache (&PeiEfiPeiFlushInstructionCache);
InstallEfiPeiPeCoffLoader (gPeiServices, &PeiEfiPeiPeCoffLoader, NULL);
//
// Preprocess the FFS file to get a pointer to the PE32 information
// in the enclosed PE32 image.
//
Status = PeiProcessFile (
gPeiServices,
EFI_SECTION_PE32,
&FfsHeader,
&Pe32Data
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Load the PE image from the FFS file
//
Status = PeiLoadFile (
gPeiServices,
PeiEfiPeiPeCoffLoader,
PeiEfiPeiFlushInstructionCache,
Pe32Data,
ImageAddress,
ImageSize,
EntryPoint
);
return Status;
}
EFI_STATUS
PeiProcessFile (
IN EFI_PEI_SERVICES **PeiServices,
IN UINT16 SectionType,
IN OUT EFI_FFS_FILE_HEADER **FfsFileHeaderPoint,
OUT VOID **Pe32Data
)
/*++
Routine Description:
Arguments:
PeiServices - General purpose services available to every PEIM.
SectionType - The type of section in the FFS file to process.
FfsFileHeaderPoint - Pointer to pointer to the FFS file to process, looking for the
specified SectionType and return pointer to FFS file that PE32 image is found
Pe32Data - returned pointer to the start of the PE32 image found
in the FFS file.
Returns:
EFI_SUCCESS - found the PE32 section in the FFS file
--*/
{
EFI_STATUS Status;
VOID *SectionData;
EFI_TIANO_DECOMPRESS_PROTOCOL *DecompressProtocol;
EFI_PHYSICAL_ADDRESS OldTopOfMemory;
UINT8 *DstBuffer;
UINT8 *ScratchBuffer;
UINT32 DstBufferSize;
UINTN ScratchBufferSize;
EFI_COMMON_SECTION_HEADER *CmpSection;
UINTN CmpSectionLength;
UINTN OccupiedCmpSectionLength;
VOID *CmpFileData;
UINTN CmpFileSize;
EFI_COMMON_SECTION_HEADER *Section;
UINTN SectionLength;
UINTN OccupiedSectionLength;
UINT64 FileSize;
EFI_GUID_DEFINED_SECTION *GuidedSectionHeader;
UINT32 AuthenticationStatus;
EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;
UINT32 BufferSize;
UINT8 *Buffer;
PEI_SECURITY_PPI *Security;
BOOLEAN StartCrisisRecovery;
EFI_GUID TempGuid;
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
EFI_COMPRESSION_SECTION *CompressionSection;
EFI_FFS_FILE_HEADER *FfsFileHeader;
FfsFileHeader = *FfsFileHeaderPoint;
Status = (*PeiServices)->FfsFindSectionData (
PeiServices,
EFI_SECTION_COMPRESSION,
FfsFileHeader,
&SectionData
);
//
// Upon finding a DXE Core file, see if there is first a compression section
//
if (!EFI_ERROR (Status)) {
//
// Yes, there is a compression section, so extract the contents
// Decompress the image here
//
Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));
do {
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
//
// Was the DXE Core file encapsulated in a GUID'd section?
//
if (Section->Type == EFI_SECTION_GUID_DEFINED) {
//
// Locate the GUID'd Section Extractor
//
GuidedSectionHeader = (VOID *) (Section + 1);
//
// This following code constitutes the addition of the security model
// to the DXE IPL.
//
//
// Set a default authenticatino state
//
AuthenticationStatus = 0;
Status = (*PeiServices)->LocatePpi (
PeiServices,
&gPeiSectionExtractionPpiGuid,
0,
NULL,
&SectionExtract
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Verify Authentication State
//
(*PeiServices)->CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));
Status = SectionExtract->PeiGetSection (
PeiServices,
SectionExtract,
(EFI_SECTION_TYPE *) &SectionType,
&TempGuid,
0,
(VOID **) &Buffer,
&BufferSize,
&AuthenticationStatus
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If not ask the Security PPI, if exists, for disposition
//
//
Status = (*PeiServices)->LocatePpi (
PeiServices,
&gPeiSecurityPpiGuid,
0,
NULL,
&Security
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Security->AuthenticationState (
PeiServices,
(struct _PEI_SECURITY_PPI *) Security,
AuthenticationStatus,
FfsFileHeader,
&StartCrisisRecovery
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If there is a security violation, report to caller and have
// the upper-level logic possible engender a crisis recovery
//
if (StartCrisisRecovery) {
return EFI_SECURITY_VIOLATION;
}
}
if (Section->Type == EFI_SECTION_PE32) {
//
// This is what we want
//
*Pe32Data = (VOID *) (Section + 1);
return EFI_SUCCESS;
} else if (Section->Type == EFI_SECTION_COMPRESSION) {
//
// This is a compression set, expand it
//
CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
DecompressProtocol = NULL;
switch (CompressionSection->CompressionType) {
case EFI_STANDARD_COMPRESSION:
Status = InstallTianoDecompress (&DecompressProtocol);
break;
case EFI_CUSTOMIZED_COMPRESSION:
//
// Load user customized compression protocol.
//
Status = InstallCustomizedDecompress ((EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL **) &DecompressProtocol);
break;
case EFI_NOT_COMPRESSED:
//
// Need to support not compressed file
//
Status = EFI_UNSUPPORTED;
break;
default:
Status = EFI_UNSUPPORTED;
}
//
// Unsupport compression type
//
if (EFI_ERROR (Status)) {
ASSERT_PEI_ERROR (PeiServices, Status);
return EFI_NOT_FOUND;
}
Status = (*PeiServices)->AllocatePages (
PeiServices,
EfiBootServicesData,
1, // EFI_PAGE_SIZE,
&OldTopOfMemory
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
DstBufferSize = 0;
ScratchBufferSize = 0;
DstBuffer = (UINT8 *) (UINTN) (OldTopOfMemory);
ScratchBuffer = (UINT8 *) (UINTN) (OldTopOfMemory);
Status = DecompressProtocol->GetInfo (
DecompressProtocol,
(UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
(UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
(UINT32 *) &DstBufferSize,
(UINT32 *) &ScratchBufferSize
);
if (EFI_SUCCESS == Status) {
//
// This is a compression set, expand it
//
Status = (*PeiServices)->AllocatePages (
PeiServices,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (ScratchBufferSize),
&OldTopOfMemory
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ScratchBuffer = (UINT8 *) (UINTN) (OldTopOfMemory);
//
// Allocate destination buffer
//
Status = (*PeiServices)->AllocatePages (
PeiServices,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (DstBufferSize),
&OldTopOfMemory
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
DstBuffer = (UINT8 *) (UINTN) (OldTopOfMemory);
//
// Call decompress function
//
Status = DecompressProtocol->Decompress (
DecompressProtocol,
(CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
(UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
DstBuffer,
(UINT32) DstBufferSize,
ScratchBuffer,
(UINT32) ScratchBufferSize
);
}
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
return EFI_NOT_FOUND;
}
CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;
if (CmpSection->Type == EFI_SECTION_RAW) {
//
// Skip the section header and
// adjust the pointer alignment to 16
//
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);
if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
FfsFileHeader = NULL;
Status = PeiBuildHobFv (PeiServices, (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);
Status = (*PeiServices)->FfsFindNextFile (
PeiServices,
EFI_FV_FILETYPE_DXE_CORE,
FvHeader,
&FfsFileHeader
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
// Write the pointer to the FFS file processed to FfsFileHeaderPoint.
//
*FfsFileHeaderPoint = FfsFileHeader;
return PeiProcessFile (PeiServices, SectionType, FfsFileHeaderPoint, Pe32Data);
}
}
//
// Decompress successfully.
// Loop the decompressed data searching for expected section.
//
CmpFileData = (VOID *) DstBuffer;
CmpFileSize = DstBufferSize;
do {
CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;
if (CmpSection->Type == EFI_SECTION_PE32) {
//
// This is what we want
//
*Pe32Data = (VOID *) (CmpSection + 1);
return EFI_SUCCESS;
}
OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);
CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);
} while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);
}
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
FileSize = FfsFileHeader->Size[0] & 0xFF;
FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;
FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;
FileSize &= 0x00FFFFFF;
} while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);
//
// End of the decompression activity
//
} else {
Status = (*PeiServices)->FfsFindSectionData (
PeiServices,
EFI_SECTION_PE32,
FfsFileHeader,
&SectionData
);
if (EFI_ERROR (Status)) {
Status = (*PeiServices)->FfsFindSectionData (
PeiServices,
EFI_SECTION_TE,
FfsFileHeader,
&SectionData
);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
*Pe32Data = SectionData;
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?