📄 load.c
字号:
//
CloseSimpleReadFile (FHand);
//
// There was an error. If there's an Image structure, free it
//
if (EFI_ERROR(Status)) {
if (Image) {
UnloadImage (Image);
*ImageHandle = NULL;
}
}
return Status;
}
EFI_STATUS
BOOTSERVICE
StartImage (
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
)
{
START_IMAGE Si;
START_IMAGE *LastSi;
BOOLEAN Flag;
UINT64 HandleDatabaseKey;
ZeroMem (&Si, sizeof(Si));
Si.Image = LoadedImageInfo(ImageHandle);
if (!Si.Image || Si.Image->Started) {
return EFI_INVALID_PARAMETER;
}
//
// Save some information about the handle database
//
HandleDatabaseKey = CoreGetHandleDatabaseKey();
//
// Push the current start image context, and
// link the current image to the head. This is the
// only image that can call Exit()
//
LastSi = CurrentStartImage;
CurrentStartImage = &Si;
Si.Image->StartImageContext = &Si;
Si.Tpl = CurrentTPL();
//
// Set long jump for Exit() support
//
Flag = SetJump (&Si.Exit);
if (!Flag) {
//
// Call platform code to set handoff state
//
if (PL->SI_HandoffState) {
PL->SI_HandoffState();
}
//
// Call the image's entry point
//
Si.Image->Started = TRUE;
DEBUG ((D_LOAD, "StartImage: Calling %hs entry point\n", Si.Image->Name));
Si.Status = Si.Image->EntryPoint (ImageHandle, Si.Image->Info.SystemTable);
//
// If the image returns, exit it through Exit()
//
BS->Exit(ImageHandle, Si.Status, 0, NULL);
//
// Call platform code to verify state on exit
//
if (PL->EI_ReturnState) {
PL->EI_ReturnState();
}
}
//
// Image has completed. Verify the tpl is the same
//
ASSERT (Si.Tpl == CurrentTPL());
RestoreTPL (Si.Tpl);
//
// Pop the current start image context
//
Si.Image->StartImageContext = NULL;
CurrentStartImage = LastSi;
DEBUG ((D_LOAD, "StartImage: Image %hs returned %x\n", Si.Image->Name, Si.Status));
//
// Connect any handles that were created or modified while the image executed.
//
CoreConnectHandlesByKey (HandleDatabaseKey);
//
// Handle the image's returned ExitData
//
if (ExitData != NULL) {
DEBUG ((D_LOAD, "StartImage: ExitDataSize %d, ExitData %x (%hs)\n",
Si.ExitDataSize,
Si.ExitData,
Si.ExitData
));
//
// Return the exit data to the caller
//
if (ExitDataSize != NULL) {
*ExitDataSize = Si.ExitDataSize;
*ExitData = Si.ExitData;
} else {
//
// Caller doesn't want the exit data, free it
//
FreePool (ExitData);
}
}
//
// If the image returned an error, of if the image is an application
// unload it
//
if (EFI_ERROR(Si.Status) || Si.Image->Type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
UnloadImage (Si.Image);
}
//
// Done
//
return Si.Status;
}
VOID
UnloadImage (
IN LOADED_IMAGE *Image
)
{
EFI_STATUS Status;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN HandleIndex;
EFI_GUID **ProtocolGuidArray;
UINTN ArrayCount;
UINTN ProtocolIndex;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
UINTN OpenInfoCount;
UINTN OpenInfoIndex;
DEBUG((D_LOAD, "UnloadImage: unloading %s\n", Image->Name));
//
// If this image is on the runtime list, free it
//
if (Image->ImageLink.Flink) {
AcquireLock (&ImageListLock);
RemoveEntryList (&Image->ImageLink);
ReleaseLock (&ImageListLock);
}
//
// Free our references to the image handle
//
if (Image->Handle) {
Status = LibLocateHandle (
AllHandles,
NULL,
NULL,
&HandleCount,
&HandleBuffer
);
if (!EFI_ERROR (Status)) {
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
Status = EFI_UNSUPPORTED;
ArrayCount = 0;
ProtocolGuidArray = NULL;
Status = BS->ProtocolsPerHandle (
HandleBuffer[HandleIndex],
&ProtocolGuidArray,
&ArrayCount
);
if (!EFI_ERROR (Status)) {
for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
Status = BS->OpenProtocolInformation (
HandleBuffer[HandleIndex],
ProtocolGuidArray[ProtocolIndex],
&OpenInfo,
&OpenInfoCount
);
if (!EFI_ERROR (Status)) {
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
Status = BS->CloseProtocol (
HandleBuffer[HandleIndex],
ProtocolGuidArray[ProtocolIndex],
OpenInfo[OpenInfoIndex].AgentHandle,
OpenInfo[OpenInfoIndex].ControllerHandle
);
}
}
if (OpenInfo != NULL) {
BS->FreePool(OpenInfo);
}
}
}
if (ProtocolGuidArray != NULL) {
BS->FreePool(ProtocolGuidArray);
}
}
}
if (HandleBuffer != NULL) {
BS->FreePool (HandleBuffer);
}
}
//
// Remove image handle from debug image info table
// This step is optional and not required by architecture. It is
// used by debuggers to determine image information
//
DeleteDebugImageInfoEntry (Image->Handle);
LibUninstallProtocolInterfaces (
Image->Handle,
&LoadedImageProtocol, &Image->Info,
&InternalImageStructure, Image,
NULL
);
}
//
// Free the Image from memory
//
if (Image->ImageBasePage) {
FreePages (Image->ImageBasePage, Image->NumberOfPages);
}
//
// Done with the Image structure
//
if (Image->Info.FilePath) {
FreePool (Image->Info.FilePath);
}
if (Image->Name) {
FreePool (Image->Name);
}
if (Image->FixupData) {
FreePool (Image->FixupData);
}
FreePool (Image);
}
EFI_STATUS
BOOTSERVICE
Exit (
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS Status,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
)
{
LOADED_IMAGE *Image;
START_IMAGE *Si;
Image = LoadedImageInfo(ImageHandle);
if (!Image) {
return EFI_INVALID_PARAMETER;
}
//
// If this Image has been started, then unload it
//
if (!Image->Started) {
UnloadImage (Image);
return EFI_SUCCESS;
}
//
// Image has been started, verify this image can exit
//
if (!Image->StartImageContext ||
Image->StartImageContext != CurrentStartImage) {
DEBUG ((D_LOAD|D_ERROR, "Exit: Image is not exitable image\n"));
return EFI_INVALID_PARAMETER;
}
//
// Set status
//
Si = (START_IMAGE *) Image->StartImageContext;
Si->Status = Status;
//
// If there's ExitData info, move it
//
if (ExitData) {
Si->ExitData = ReallocatePool (ExitData, ExitDataSize, ExitDataSize);
Si->ExitDataSize = ExitDataSize;
}
//
// return to StartImage
//
LongJump (&Si->Exit);
ASSERT (FALSE);
return EFI_ACCESS_DENIED;
}
#pragma RUNTIME_CODE(RtLoaderExitBootServices)
VOID
RUNTIMEFUNCTION
RtLoaderExitBootServices (
VOID
)
{
LIST_ENTRY *Link;
LOADED_IMAGE *Image;
//
// Walk all the boot service driver images
//
Link = BootImageList.Flink;
while (Link != &BootImageList) {
Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);
Link = Link->Flink;
//
// Clear memory of old components
//
ZeroMem (Image->ImageBase, Image->NumberOfPages << EFI_PAGE_SHIFT);
ZeroMem (Image, sizeof(LOADED_IMAGE));
}
//
// Walk all the runtime images
//
for(Link=RuntimeImageList.Flink; Link != &RuntimeImageList; Link=Link->Flink) {
Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);
//
// Clear non-runtime pointers
//
Image->Handle = NULL;
Image->Name = NULL;
Image->Info.ParentHandle = NULL;
Image->Info.SystemTable = NULL;
Image->Info.DeviceHandle = NULL;
Image->Info.FilePath = NULL;
Image->Info.LoadOptions = NULL;
}
}
#pragma RUNTIME_CODE(RtLoaderVirtualAddressFixup)
VOID
RUNTIMEFUNCTION
RtLoaderVirtualAddressFixup (
VOID
)
// Switching into virtual mode. reapply fix ups to all runtime images
{
LIST_ENTRY *Link;
LOADED_IMAGE *Image;
for(Link=RuntimeImageList.Flink; Link != &RuntimeImageList; Link=Link->Flink) {
Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);
ConvertPeImage (Image);
RT->ConvertPointer (0, &Image->ImageBase);
RT->ConvertPointer (0, &Image->ImageEof);
RT->ConvertPointer (0, &Image->Info.ImageBase);
}
RtConvertList(EFI_INTERNAL_PTR, &RuntimeImageList);
}
EFI_STATUS
BSUnloadImage (
IN EFI_HANDLE ImageHandle
)
// Unload a driver
{
EFI_STATUS Status;
LOADED_IMAGE *Image;
EFI_EBC_PROTOCOL *EbcProtocol;
//
// Make sure ImageHandle is a valid handle
//
if (ImageHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Get the Loaded Image Protocol that is installed on ImageHandle
//
Image = LoadedImageInfo (ImageHandle);
//
// If ImageHandle does not support a Loaded Image Protocol, then return an error
//
if (Image == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// If this Image hasn't been started, then it can be unloaded immediately
//
if (!Image->Started) {
UnloadImage (Image);
return EFI_SUCCESS;
}
//
// The image has been started, request it to unload.
// If the Loaded Image Protocol does not have an Unload() function, then the
// image can not be unloaded, so return an error.
//
if (Image->Info.Unload == NULL) {
return EFI_UNSUPPORTED;
}
//
// Call the image specific Unload() function. If it fails, then return an error
//
Status = Image->Info.Unload (ImageHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Determine if this is an EBC image. If so, then make a call into the
// EBC protocol to perform any cleanup for this image.
//
if (Image->Machine == EFI_IMAGE_MACHINE_EBC) {
//
// Try to get the EBC protocol
//
Status = BS->LocateProtocol (&gEfiEbcProtocolGuid, NULL, &EbcProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Free the thunks that were created when the EBC image was loaded and initialized
//
Status = EbcProtocol->UnloadImage (EbcProtocol, ImageHandle);
if (EFI_ERROR(Status)) {
return Status;
}
}
//
// Unload the image from system memory
//
UnloadImage (Image);
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -