dxeload.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,324 行 · 第 1/3 页
C
1,324 行
//
// Add HOB for the Flush Instruction Cache Protocol
//
Interface = (VOID *) PeiEfiPeiFlushInstructionCache;
Status = PeiBuildHobGuidData (
PeiServices,
&mPeiEfiPeiFlushInstructionCacheGuid,
&Interface,
sizeof (VOID *)
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Add HOB for the PE/COFF Loader Protocol
//
Interface = (VOID *) PeiEfiPeiPeCoffLoader;
Status = PeiBuildHobGuidData (
PeiServices,
&mPeiEfiPeiPeCoffLoaderGuid,
&Interface,
sizeof (VOID *)
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Add HOB for the Transfer Control Protocol
//
Interface = (VOID *) PeiEfiPeiTransferControl;
Status = PeiBuildHobGuidData (
PeiServices,
&mPeiEfiPeiTransferControlGuid,
&Interface,
sizeof (VOID *)
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// See if we are in crisis recovery
//
Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {
Status = (*PeiServices)->LocatePpi (
PeiServices,
&gPeiRecoveryModulePpiGuid,
0,
NULL,
&PeiRecovery
);
ASSERT_PEI_ERROR (PeiServices, Status);
Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Now should have a HOB with the DXE core w/ the old HOB destroyed
//
}
//
// Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block
// 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 which is provided for DXE
// core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks
// for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned
// status
//
Status = PeiFindFile (
PeiServices,
EFI_FV_FILETYPE_RAW,
EFI_SECTION_PE32,
&FirmwareFileName,
&Pe32Data
);
//
// Find the DXE Core in a Firmware Volume
//
Status = PeiFindFile (
PeiServices,
EFI_FV_FILETYPE_DXE_CORE,
EFI_SECTION_PE32,
&DxeCoreFileName,
&Pe32Data
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Load the DXE Core from a Firmware Volume
//
Status = PeiLoadFile (
PeiServices,
PeiEfiPeiPeCoffLoader,
PeiEfiPeiFlushInstructionCache,
Pe32Data,
&DxeCoreAddress,
&DxeCoreSize,
&DxeCoreEntryPoint
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Transfer control to the DXE Core
// The handoff state is simply a pointer to the HOB list
//
PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0);
Status = (*PeiServices)->InstallPpi (PeiServices, &mPpiSignal);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Add HOB for the DXE Core
//
Status = PeiBuildHobModule (
PeiServices,
&DxeCoreFileName,
DxeCoreAddress,
DxeCoreSize,
DxeCoreEntryPoint
);
ASSERT_PEI_ERROR (PeiServices, Status);
//
// Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
//
PEI_REPORT_STATUS_CODE (
PeiServices,
EFI_PROGRESS_CODE,
EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT,
0,
NULL,
NULL
);
PEI_DEBUG ((PeiServices, EFI_D_INFO, "DXE Core Entry\n"));
SwitchStacks (
(VOID *) (UINTN) DxeCoreEntryPoint,
(UINTN) (HobList.Raw),
(VOID *) (UINTN) TopOfStack,
(VOID *) (UINTN) BspStore
);
//
// If we get here, then the DXE Core returned. This is an error
//
ASSERT_PEI_ERROR (PeiServices, Status);
return EFI_OUT_OF_RESOURCES;
}
EFI_STATUS
PeiFindFile (
IN EFI_PEI_SERVICES **PeiServices,
IN UINT8 Type,
IN UINT16 SectionType,
OUT EFI_GUID *FileName,
OUT VOID **Pe32Data
)
/*++
Routine Description:
Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
described in the HOB list. Able to search in a compression set in a FFS file.
But only one level of compression is supported, that is, not able to search
in a compression set that is within another compression set.
Arguments:
PeiServices - General purpose services available to every PEIM.
Type - The Type of file to retrieve
SectionType - The type of section to retrieve from a file
FileName - The name of the file found in the Firmware Volume
Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
Returns:
EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
the PE/COFF image is returned in Pe32Data
EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
--*/
{
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_FFS_FILE_HEADER *FfsFileHeader;
VOID *SectionData;
EFI_STATUS Status;
BOOLEAN Found;
EFI_PEI_HOB_POINTERS Hob;
Status = (*PeiServices)->GetHobList (PeiServices, &Hob.Raw);
if (EFI_ERROR (Status)) {
return Status;
}
Found = FALSE;
Status = EFI_SUCCESS;
FwVolHeader = NULL;
FfsFileHeader = NULL;
SectionData = NULL;
//
// Foreach Firmware Volume, look for a specified type
// of file and break out when one is found
//
Hob.Raw = GetHob (EFI_HOB_TYPE_FV, Hob.Raw);
if (Hob.Header->HobType != EFI_HOB_TYPE_FV) {
return EFI_NOT_FOUND;
}
while (!END_OF_HOB_LIST (Hob)) {
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);
Status = (*PeiServices)->FfsFindNextFile (
PeiServices,
Type,
FwVolHeader,
&FfsFileHeader
);
if (EFI_ERROR (Status)) {
Hob.Raw = GET_NEXT_HOB (Hob);
Hob.Raw = GetHob (EFI_HOB_TYPE_FV, Hob.Raw);
if (Hob.Header->HobType != EFI_HOB_TYPE_FV) {
break;
}
continue;
} else {
Status = PeiProcessFile (
PeiServices,
SectionType,
&FfsFileHeader,
Pe32Data
);
//
// Copy the File GUID from the FFS file that Pe32Data is found
//
(*PeiServices)->CopyMem (
FileName,
&FfsFileHeader->Name,
sizeof (EFI_GUID)
);
return Status;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
PeiLoadFile (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *PeiEfiPeiFlushInstructionCache,
IN VOID *Pe32Data,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
)
/*++
Routine Description:
Loads and relocates a PE/COFF image into memory.
Arguments:
PeiService - General purpose services available to every PEIM.
PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
PeiEfiPeiFlushInstructionCache - Pointer to a flush-instruction-cache protocol so
we can flush the cache after loading
Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
ImageAddress - The base address of the relocated PE/COFF image
ImageSize - The size of the relocated PE/COFF image
EntryPoint - The entry point of the relocated PE/COFF image
Returns:
EFI_SUCCESS - The file was loaded and relocated
EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
--*/
{
EFI_STATUS Status;
EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
EFI_PHYSICAL_ADDRESS MemoryBuffer;
(*PeiServices)->SetMem (
&ImageContext,
sizeof (ImageContext),
0
);
ImageContext.Handle = Pe32Data;
Status = GetImageReadFunction (PeiServices, &ImageContext);
ASSERT_PEI_ERROR (PeiServices, Status);
Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Allocate Memory for the image
//
Status = (*PeiServices)->AllocatePages (
PeiServices,
EfiBootServicesData,
EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize),
&MemoryBuffer
);
ASSERT_PEI_ERROR (PeiServices, Status);
ImageContext.ImageAddress = MemoryBuffer;
//
// Load the image to our new buffer
//
Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Relocate the image in our new buffer
//
Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Flush the instruction cache so the image data is written before we execute it
//
Status = PeiEfiPeiFlushInstructionCache->Flush (
PeiEfiPeiFlushInstructionCache,
ImageContext.ImageAddress,
ImageContext.ImageSize
);
if (EFI_ERROR (Status)) {
return Status;
}
*ImageAddress = ImageContext.ImageAddress;
*ImageSize = ImageContext.ImageSize;
*EntryPoint = ImageContext.EntryPoint;
return EFI_SUCCESS;
}
EFI_STATUS
ShadowDxeIpl (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_FFS_FILE_HEADER *DxeIpl,
IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *PeiEfiPeiFlushInstructionCache
)
/*++
Routine Description:
Shadow the DXE IPL to a different memory location. This occurs after permanent
memory has been discovered.
Arguments:
PeiService - General purpose services available to every PEIM.
DxeIpl - Pointer to the FFS file header of the DXE IPL driver
PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
PeiEfiPeiFlushInstructionCache - Pointer to a flush-instruction-cache protocol so
we can flush the cache after shadowing the image
Returns:
EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
EFI_ ERROR - The shadow was unsuccessful.
--*/
{
UINTN SectionLength;
UINTN OccupiedSectionLength;
EFI_PHYSICAL_ADDRESS DxeIplAddress;
UINT64 DxeIplSize;
EFI_PHYSICAL_ADDRESS DxeIplEntryPoint;
EFI_STATUS Status;
EFI_COMMON_SECTION_HEADER *Section;
Section = (EFI_COMMON_SECTION_HEADER *) (DxeIpl + 1);
while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {
SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);
Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);
}
//
// Relocate DxeIpl into memory by using loadfile service
//
Status = PeiLoadFile (
PeiServices,
PeiEfiPeiPeCoffLoader,
PeiEfiPeiFlushInstructionCache,
(VOID *) (Section + 1),
&DxeIplAddress,
&DxeIplSize,
&DxeIplEntryPoint
);
if (Status == EFI_SUCCESS) {
//
// Install PeiInMemory to indicate the Dxeipl is shadowed
//
Status = (*PeiServices)->InstallPpi (PeiServices, &mPpiPeiInMemory);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ((DXE_IPL_ENTRYPOINT) (UINTN) DxeIplEntryPoint) (DxeIpl, PeiServices);
}
return Status;
}
EFI_STATUS
EFIAPI
DxeIplLoadFile (
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?