📄 image.c
字号:
//
// Set long jump for Exit() support
//
Image->JumpContext = CoreAllocateBootServicesPool (gEfiPeiTransferControl->JumpContextSize);
if (Image->JumpContext == NULL) {
PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
return EFI_OUT_OF_RESOURCES;
}
Status = gEfiPeiTransferControl->SetJump (gEfiPeiTransferControl, Image->JumpContext);
//
// The SetJump returns EFI_SUCCESS when LongJump Buffer has been armed
// SetJump returns EFI_WARN_RETURN_FROM_LONG_JUMP as a result of the LongJump
// All other return values for SetJump are undefined.
//
if (Status == EFI_SUCCESS) {
//
// Call the image's entry point
//
Image->Started = TRUE;
Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
//
// Add some debug information if the image returned with error.
// This make the user aware and check if the driver image have already released
// all the resource in this situation.
//
DEBUG_CODE (
if (EFI_ERROR (Image->Status)) {
DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));
}
)
//
// If the image returns, exit it through Exit()
//
CoreExit (ImageHandle, Image->Status, 0, NULL);
}
//
// Image has completed. Verify the tpl is the same
//
ASSERT (Image->Tpl == gEfiCurrentTpl);
CoreRestoreTpl (Image->Tpl);
CoreFreePool (Image->JumpContext);
//
// Pop the current start image context
//
mCurrentImage = LastImage;
//
// Go connect any handles that were created or modified while the image executed.
//
CoreConnectHandlesByKey (HandleDatabaseKey);
//
// Handle the image's returned ExitData
//
DEBUG_CODE (
if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
DEBUG (
(EFI_D_LOAD,
"StartImage: ExitDataSize %d, ExitData %x",
Image->ExitDataSize,
Image->ExitData)
);
if (Image->ExitData != NULL) {
DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
}
DEBUG ((EFI_D_LOAD, "\n"));
}
)
//
// Return the exit data to the caller
//
if (ExitData != NULL && ExitDataSize != NULL) {
*ExitDataSize = Image->ExitDataSize;
*ExitData = Image->ExitData;
} else {
//
// Caller doesn't want the exit data, free it
//
CoreFreePool (Image->ExitData);
Image->ExitData = NULL;
}
//
// Save the Status because Image will get destroyed if it is unloaded.
//
Status = Image->Status;
//
// If the image returned an error, or if the image is an application
// unload it
//
if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
CoreUnloadAndCloseImage (Image, TRUE);
}
//
// Done
//
PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
return Status;
}
VOID
CoreUnloadAndCloseImage (
IN LOADED_IMAGE_PRIVATE_DATA *Image,
IN BOOLEAN FreePage
)
/*++
Routine Description:
Unloads EFI image from memory.
Arguments:
Image - EFI image
FreePage - Free allocated pages
Returns:
None
--*/
{
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;
if (Image->Ebc != NULL) {
//
// If EBC protocol exists we must perform cleanups for this image.
//
Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
}
//
// Unload image, free Image->ImageContext->ModHandle
//
gEfiPeiPeCoffLoader->UnloadImage (&Image->ImageContext);
//
// Free our references to the image handle
//
if (Image->Handle != NULL_HANDLE) {
Status = CoreLocateHandleBuffer (
AllHandles,
NULL,
NULL,
&HandleCount,
&HandleBuffer
);
if (!EFI_ERROR (Status)) {
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
Status = CoreProtocolsPerHandle (
HandleBuffer[HandleIndex],
&ProtocolGuidArray,
&ArrayCount
);
if (!EFI_ERROR (Status)) {
for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
Status = CoreOpenProtocolInformation (
HandleBuffer[HandleIndex],
ProtocolGuidArray[ProtocolIndex],
&OpenInfo,
&OpenInfoCount
);
if (!EFI_ERROR (Status)) {
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
Status = CoreCloseProtocol (
HandleBuffer[HandleIndex],
ProtocolGuidArray[ProtocolIndex],
Image->Handle,
OpenInfo[OpenInfoIndex].ControllerHandle
);
}
}
if (OpenInfo != NULL) {
CoreFreePool(OpenInfo);
}
}
}
if (ProtocolGuidArray != NULL) {
CoreFreePool(ProtocolGuidArray);
}
}
}
if (HandleBuffer != NULL) {
CoreFreePool (HandleBuffer);
}
}
CoreRemoveDebugImageInfoEntry (Image->Handle);
Status = CoreUninstallProtocolInterface (
Image->Handle,
&gEfiLoadedImageProtocolGuid,
&Image->Info
);
//
// Uninstall Debug Mask Protocol
//
DEBUG_CODE (
Status = UninstallDebugMaskProtocol(Image->Handle);
ASSERT_EFI_ERROR (Status);
)
}
if (Image->RuntimeData != NULL) {
if (Image->RuntimeData->Link.ForwardLink != NULL) {
//
// Remove the Image from the Runtime Image list as we are about to Free it!
//
RemoveEntryList (&Image->RuntimeData->Link);
}
CoreFreePool (Image->RuntimeData);
}
//
// Free the Image from memory
//
if ((Image->ImageBasePage != 0) && FreePage) {
CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
}
//
// Done with the Image structure
//
if (Image->Info.FilePath != NULL) {
CoreFreePool (Image->Info.FilePath);
}
if (Image->FixupData != NULL) {
CoreFreePool (Image->FixupData);
}
CoreFreePool (Image);
}
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreExit (
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS Status,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
)
/*++
Routine Description:
Terminates the currently loaded EFI image and returns control to boot services.
Arguments:
ImageHandle - Handle that identifies the image. This parameter is passed to the image
on entry.
Status - The image’s exit code.
ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
EFI_SUCCESS.
ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
optionally followed by additional binary data. The string is a
description that the caller may use to further indicate the reason for
the image’s exit.
Returns:
EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
EFI_ACCESS_DENIED - Should never reach there.
EFI_OUT_OF_RESOURCES - Could not allocate pool
--*/
{
LOADED_IMAGE_PRIVATE_DATA *Image;
Image = CoreLoadedImageInfo (ImageHandle);
if (Image == NULL_HANDLE) {
return EFI_INVALID_PARAMETER;
}
if (!Image->Started) {
//
// The image has not been started so just free its resources
//
CoreUnloadAndCloseImage (Image, TRUE);
return EFI_SUCCESS;
}
//
// Image has been started, verify this image can exit
//
if (Image != mCurrentImage) {
DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
return EFI_INVALID_PARAMETER;
}
//
// Set status
//
Image->Status = Status;
//
// If there's ExitData info, move it
//
if (ExitData != NULL) {
Image->ExitDataSize = ExitDataSize;
Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
if (Image->ExitData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EfiCommonLibCopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
}
//
// return to StartImage
//
Status = gEfiPeiTransferControl->LongJump (gEfiPeiTransferControl, Image->JumpContext);
//
// If we return from LongJump, then it is an error
//
ASSERT (FALSE);
return EFI_ACCESS_DENIED;
}
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreUnloadImage (
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Unloads an image.
Arguments:
ImageHandle - Handle that identifies the image to be unloaded.
Returns:
EFI_SUCCESS - The image has been unloaded.
EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
--*/
{
EFI_STATUS Status;
LOADED_IMAGE_PRIVATE_DATA *Image;
Image = CoreLoadedImageInfo (ImageHandle);
if (Image == NULL ) {
//
// The image handle is not valid
//
return EFI_INVALID_PARAMETER;
}
if (Image->Started) {
//
// The image has been started, request it to unload.
//
Status = EFI_UNSUPPORTED;
if (Image->Info.Unload != NULL) {
Status = Image->Info.Unload (ImageHandle);
}
} else {
//
// This Image hasn't been started, thus it can be unloaded
//
Status = EFI_SUCCESS;
}
if (!EFI_ERROR (Status)) {
//
// if the Image was not started or Unloaded O.K. then clean up
//
CoreUnloadAndCloseImage (Image, TRUE);
}
return Status;
}
EFI_STATUS
EFIAPI
CoreUnloadImageEx (
IN EFI_PE32_IMAGE_PROTOCOL *This,
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Unload the specified image.
Arguments:
This - Indicates the calling context.
ImageHandle - The specified image handle.
Returns:
EFI_INVALID_PARAMETER - Image handle is NULL.
EFI_UNSUPPORTED - Attempt to unload an unsupported image.
EFI_SUCCESS - Image successfully unloaded.
--*/
{
return CoreUnloadImage (ImageHandle);
}
//
// This callback function is used by the EBC interpreter driver to flush the
// processor instruction cache after creating thunks. We're simply hiding
// the "this" pointer that must be passed into the real flush function.
//
STATIC
EFI_STATUS
EFIAPI
CoreFlushICache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length
)
/*++
Routine Description:
flush the processor instruction cache.
Arguments:
Start - Start adddress in memory to flush.
Length - Length of memory to flush.
Returns:
--*/
{
return gEfiPeiFlushInstructionCache->Flush (
gEfiPeiFlushInstructionCache,
Start,
Length
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -