搜尋此網誌
2012年10月3日 星期三
BdsLibBootViaBootOption() - Boot up to load drivers
/*You can find the function in EDK1.6 BdsBoot.c*/
EFI_STATUS
BdsLibBootViaBootOption (
IN BDS_COMMON_OPTION * Option,
IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
)
/*++
Routine Description:
Process the boot option follow the EFI 1.1 specification and
special treat the legacy boot option with BBS_DEVICE_PATH.
Arguments:
Option - The boot option need to be processed
DevicePath - The device path which describe where to load
the boot image or the legcy BBS device path
to boot the legacy OS
ExitDataSize - Returned directly from gBS->StartImage ()
ExitData - Returned directly from gBS->StartImage ()
Returns:
EFI_SUCCESS - Status from gBS->StartImage ()
EFI_NOT_FOUND - If the Device Path is not found in the system
--*/
{
EFI_STATUS Status;
EFI_HANDLE Handle;
EFI_HANDLE ImageHandle;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
EFI_EVENT ReadyToBootEvent;
EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;
EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
EFI_LIST_ENTRY TempBootLists;
EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;
//
// Record the performance data for End of BDS
//
PERF_END (0, BDS_TOK, NULL, 0);
*ExitDataSize = 0;
*ExitData = NULL;
//
// Notes: put EFI64 ROM Shadow Solution
//
EFI64_SHADOW_ALL_LEGACY_ROM ();
//
// Notes: this code can be remove after the s3 script table
// hook on the event EFI_EVENT_SIGNAL_READY_TO_BOOT or
// EFI_EVENT_SIGNAL_LEGACY_BOOT
//
Status = gBS->LocateProtocol (&gEfiAcpiS3SaveGuid, NULL, &AcpiS3Save);
if (!EFI_ERROR (Status)) {
AcpiS3Save->S3Save (AcpiS3Save, NULL);
}
//
// If it's Device Path that starts with a hard drive path, append it with the front part to compose a
// full device path
//
WorkingDevicePath = NULL;
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {
WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (
(HARDDRIVE_DEVICE_PATH *)DevicePath
);
if (WorkingDevicePath != NULL) {
DevicePath = WorkingDevicePath;
}
}
//
// Set Boot Current
//
gRT->SetVariable (
L"BootCurrent",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof (UINT16),
&Option->BootCurrent
);
//
// Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event
//
Status = EfiCreateEventReadyToBoot (
EFI_TPL_CALLBACK,
NULL,
NULL,
&ReadyToBootEvent
);
if (!EFI_ERROR (Status)) {
gBS->SignalEvent (ReadyToBootEvent);
gBS->CloseEvent (ReadyToBootEvent);
}
if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
(DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
) {
//
// Check to see if we should legacy BOOT. If yes then do the legacy boot
//
return BdsLibDoLegacyBoot (Option);
}
//
// If the boot option point to Internal FV shell, make sure it is valid
//
Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);
if (!EFI_ERROR(Status)) {
if (Option->DevicePath != NULL) {
EfiLibSafeFreePool(Option->DevicePath);
}
Option->DevicePath = EfiLibAllocateZeroPool (EfiDevicePathSize (DevicePath));
EfiCopyMem (Option->DevicePath, DevicePath, EfiDevicePathSize (DevicePath));
//
// Update the shell boot option
//
InitializeListHead (&TempBootLists);
BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");
//
// free the temporary device path created by BdsLibUpdateFvFileDevicePath()
//
gBS->FreePool (DevicePath);
DevicePath = Option->DevicePath;
}
//
// Measure GPT Table
//
Status = gBS->LocateProtocol (
&gEfiTcgPlatformProtocolGuid,
NULL,
&TcgPlatformProtocol
);
if (!EFI_ERROR (Status)) {
Status = TcgPlatformProtocol->MeasureGptTable (DevicePath);
}
//
// Drop the TPL level from EFI_TPL_DRIVER to EFI_TPL_APPLICATION
//
gBS->RestoreTPL (EFI_TPL_APPLICATION);
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Booting EFI way %S\n", Option->Description));
Status = gBS->LoadImage (
TRUE,
mBdsImageHandle,
DevicePath,
NULL,
0,
&ImageHandle
);
//
// If we didn't find an image directly, we need to try as if it is a removable device boot opotion
// and load the image according to the default boot behavior for removable device.
//
if (EFI_ERROR (Status)) {
//
// check if there is a bootable removable media could be found in this device path ,
// and get the bootable media handle
//
Handle = BdsLibGetBootableHandle(DevicePath);
if (Handle == NULL) {
goto Done;
}
//
// Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media
// machinename is ia32, ia64, x64, ...
//
FilePath = EfiFileDevicePath (Handle, DEFAULT_REMOVABLE_FILE_NAME);
if (FilePath) {
Status = gBS->LoadImage (
TRUE,
mBdsImageHandle,
FilePath,
NULL,
0,
&ImageHandle
);
if (EFI_ERROR (Status)) {
//
// The DevicePath failed, and it's not a valid
// removable media device.
//
goto Done;
}
}
}
if (EFI_ERROR (Status)) {
//
// It there is any error from the Boot attempt exit now.
//
goto Done;
}
//
// Provide the image with it's load options
//
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo);
ASSERT_EFI_ERROR (Status);
if (Option->LoadOptionsSize != 0) {
ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;
ImageInfo->LoadOptions = Option->LoadOptions;
}
//
// Before calling the image, enable the Watchdog Timer for
// the 5 Minute period
//
gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
//
// Write boot to OS performance data for UEFI boot
//
WRITE_BOOT_TO_OS_PERFORMANCE_DATA;
Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Image Return Status = %r\n", Status));
//
// Clear the Watchdog Timer after the image returns
//
gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
Done:
//
// Clear Boot Current
//
gRT->SetVariable (
L"BootCurrent",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
&Option->BootCurrent
);
//
// Raise the TPL level back to EFI_TPL_DRIVER
//
gBS->RaiseTPL (EFI_TPL_DRIVER);
return Status;
}
LoadDriver() - How to load uefi/efi driver in code?
/*You can find the function in Shell load.c*/
STATIC
EFI_STATUS
LoadDriver (
IN EFI_HANDLE ParentImage,
IN SHELL_FILE_ARG *Arg,
IN BOOLEAN Connect
)
{
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *NodePath;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
CHAR16 *LoadOptions;
UINTN LoadOptionsSize;
CHAR16 *Cwd;
EFI_IMAGE_DOS_HEADER DosHeader;
EFI_IMAGE_FILE_HEADER ImageHeader;
EFI_IMAGE_OPTIONAL_HEADER OptionalHeader;
NodePath = FileDevicePath (NULL, Arg->FileName);
FilePath = AppendDevicePath (Arg->ParentDevicePath, NodePath);
if (NodePath) {
FreePool (NodePath);
NodePath = NULL;
}
if (!FilePath) {
return EFI_OUT_OF_RESOURCES;
}
//
// Check whether Image is valid to be loaded.
//
Status = LibGetImageHeader (
FilePath,
&DosHeader,
&ImageHeader,
&OptionalHeader
);
if (!EFI_ERROR (Status) && !EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageHeader.Machine) &&
(OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ||
OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
FreePool (FilePath);
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_TYPE_UNSUPPORTED),
HiiLoadHandle,
LibGetMachineTypeString (ImageHeader.Machine),
LibGetMachineTypeString (EFI_IMAGE_MACHINE_TYPE)
);
return EFI_INVALID_PARAMETER;
}
Status = BS->LoadImage (
FALSE,
ParentImage,
FilePath,
NULL,
0,
&ImageHandle
);
FreePool (FilePath);
if (EFI_ERROR (Status)) {
if (Status == EFI_SECURITY_VIOLATION) {
BS->UnloadImage (ImageHandle);
}
PrintToken (STRING_TOKEN (STR_LOAD_NOT_IMAGE), HiiLoadHandle, Arg->FullName);
return EFI_INVALID_PARAMETER;
}
//
// Verify the image is a driver ?
//
BS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &ImageInfo);
if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
PrintToken (STRING_TOKEN (STR_LOAD_IMAGE_NOT_DRIVER), HiiLoadHandle, Arg->FullName);
BS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
return EFI_INVALID_PARAMETER;
}
//
// Construct a load options buffer containing the command line and
// current working directory.
//
// NOTE: To prevent memory leaks, the protocol is responsible for
// freeing the memory associated with the load options.
//
// One day we'll pass arguments to the protocol....
//
Cwd = ShellCurDir (NULL);
if (NULL == Cwd) {
Cwd = StrDuplicate (L"");
}
LoadOptionsSize = (StrLen (Arg->FullName) + 2 + StrLen (Cwd) + 2) * sizeof (CHAR16);
LoadOptions = AllocatePool (LoadOptionsSize);
ASSERT (LoadOptions);
StrCpy (LoadOptions, Arg->FullName);
StrCpy (&LoadOptions[StrLen (LoadOptions) + 1], Cwd);
FreePool (Cwd);
if (ImageInfo->LoadOptions) {
FreePool (ImageInfo->LoadOptions);
}
ImageInfo->LoadOptionsSize = (UINT32) LoadOptionsSize;
ImageInfo->LoadOptions = LoadOptions;
//
// Start the image
//
Status = BS->StartImage (ImageHandle, NULL, NULL);
if (!EFI_ERROR (Status)) {
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_LOADED),
HiiLoadHandle,
Arg->FullName,
ImageInfo->ImageBase,
Status
);
} else {
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_ERROR),
HiiLoadHandle,
Arg->FullName,
Status
);
}
if (Connect) {
Status = LoadConnectAllDriversToAllControllers ();
}
//
// When any driver starts, turn off the watchdog timer
//
BS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
return Status;
}
STATIC
EFI_STATUS
LoadDriver (
IN EFI_HANDLE ParentImage,
IN SHELL_FILE_ARG *Arg,
IN BOOLEAN Connect
)
{
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *NodePath;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
CHAR16 *LoadOptions;
UINTN LoadOptionsSize;
CHAR16 *Cwd;
EFI_IMAGE_DOS_HEADER DosHeader;
EFI_IMAGE_FILE_HEADER ImageHeader;
EFI_IMAGE_OPTIONAL_HEADER OptionalHeader;
NodePath = FileDevicePath (NULL, Arg->FileName);
FilePath = AppendDevicePath (Arg->ParentDevicePath, NodePath);
if (NodePath) {
FreePool (NodePath);
NodePath = NULL;
}
if (!FilePath) {
return EFI_OUT_OF_RESOURCES;
}
//
// Check whether Image is valid to be loaded.
//
Status = LibGetImageHeader (
FilePath,
&DosHeader,
&ImageHeader,
&OptionalHeader
);
if (!EFI_ERROR (Status) && !EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageHeader.Machine) &&
(OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ||
OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
FreePool (FilePath);
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_TYPE_UNSUPPORTED),
HiiLoadHandle,
LibGetMachineTypeString (ImageHeader.Machine),
LibGetMachineTypeString (EFI_IMAGE_MACHINE_TYPE)
);
return EFI_INVALID_PARAMETER;
}
Status = BS->LoadImage (
FALSE,
ParentImage,
FilePath,
NULL,
0,
&ImageHandle
);
FreePool (FilePath);
if (EFI_ERROR (Status)) {
if (Status == EFI_SECURITY_VIOLATION) {
BS->UnloadImage (ImageHandle);
}
PrintToken (STRING_TOKEN (STR_LOAD_NOT_IMAGE), HiiLoadHandle, Arg->FullName);
return EFI_INVALID_PARAMETER;
}
//
// Verify the image is a driver ?
//
BS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &ImageInfo);
if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
PrintToken (STRING_TOKEN (STR_LOAD_IMAGE_NOT_DRIVER), HiiLoadHandle, Arg->FullName);
BS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
return EFI_INVALID_PARAMETER;
}
//
// Construct a load options buffer containing the command line and
// current working directory.
//
// NOTE: To prevent memory leaks, the protocol is responsible for
// freeing the memory associated with the load options.
//
// One day we'll pass arguments to the protocol....
//
Cwd = ShellCurDir (NULL);
if (NULL == Cwd) {
Cwd = StrDuplicate (L"");
}
LoadOptionsSize = (StrLen (Arg->FullName) + 2 + StrLen (Cwd) + 2) * sizeof (CHAR16);
LoadOptions = AllocatePool (LoadOptionsSize);
ASSERT (LoadOptions);
StrCpy (LoadOptions, Arg->FullName);
StrCpy (&LoadOptions[StrLen (LoadOptions) + 1], Cwd);
FreePool (Cwd);
if (ImageInfo->LoadOptions) {
FreePool (ImageInfo->LoadOptions);
}
ImageInfo->LoadOptionsSize = (UINT32) LoadOptionsSize;
ImageInfo->LoadOptions = LoadOptions;
//
// Start the image
//
Status = BS->StartImage (ImageHandle, NULL, NULL);
if (!EFI_ERROR (Status)) {
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_LOADED),
HiiLoadHandle,
Arg->FullName,
ImageInfo->ImageBase,
Status
);
} else {
PrintToken (
STRING_TOKEN (STR_LOAD_IMAGE_ERROR),
HiiLoadHandle,
Arg->FullName,
Status
);
}
if (Connect) {
Status = LoadConnectAllDriversToAllControllers ();
}
//
// When any driver starts, turn off the watchdog timer
//
BS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
return Status;
}
2012年10月2日 星期二
LoadEfiDriversFromRomImage() - How to load uefi/efi PCI ROM Image in code?
/*You can find the function in Shell LoadPciRom.c*/
EFI_STATUS
LoadEfiDriversFromRomImage (
VOID *RomBar,
UINTN RomSize,
CHAR16 *FileName
)
/*++
Routine Description:
Command entry point.
Arguments:
RomBar - Rom
RomSize - Rom size
FileName - The file name
Returns:
EFI_SUCCESS - The command completed successfully
EFI_INVALID_PARAMETER - Command usage error
EFI_UNSUPPORTED - Protocols unsupported
EFI_OUT_OF_RESOURCES - Out of memory
Other value - Unknown error
--*/
{
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
PCI_DATA_STRUCTURE *Pcir;
UINTN ImageIndex;
UINTN RomBarOffset;
UINT32 ImageSize;
UINT16 ImageOffset;
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_STATUS retStatus;
CHAR16 RomFileName[280];
EFI_DEVICE_PATH_PROTOCOL *FilePath;
BOOLEAN SkipImage;
UINT32 DestinationSize;
UINT32 ScratchSize;
UINT8 *Scratch;
VOID *ImageBuffer;
VOID *DecompressedImageBuffer;
UINT32 ImageLength;
EFI_DECOMPRESS_PROTOCOL *Decompress;
ImageIndex = 0;
retStatus = EFI_NOT_FOUND;
RomBarOffset = (UINTN) RomBar;
do {
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
if (EfiRomHeader->Signature != 0xaa55) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);
return retStatus;
}
Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
ImageSize = Pcir->ImageLength * 512;
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)
) {
if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
) {
ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
ImageSize = EfiRomHeader->InitializationSize * 512;
ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
ImageLength = ImageSize - ImageOffset;
DecompressedImageBuffer = NULL;
//
// decompress here if needed
//
SkipImage = FALSE;
if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
SkipImage = TRUE;
}
if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
Status = BS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, &Decompress);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_DECOMP_NOT_FOUND), HiiHandle);
SkipImage = TRUE;
} else {
SkipImage = TRUE;
Status = Decompress->GetInfo (
Decompress,
ImageBuffer,
ImageLength,
&DestinationSize,
&ScratchSize
);
if (!EFI_ERROR (Status)) {
DecompressedImageBuffer = AllocatePool (DestinationSize);
if (ImageBuffer != NULL) {
Scratch = AllocatePool (ScratchSize);
if (Scratch != NULL) {
Status = Decompress->Decompress (
Decompress,
ImageBuffer,
ImageLength,
DecompressedImageBuffer,
DestinationSize,
Scratch,
ScratchSize
);
if (!EFI_ERROR (Status)) {
ImageBuffer = DecompressedImageBuffer;
ImageLength = DestinationSize;
SkipImage = FALSE;
}
FreePool (Scratch);
}
}
}
}
}
if (SkipImage == FALSE) {
//
// load image and start image
//
SPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
FilePath = FileDevicePath (NULL, RomFileName);
Status = BS->LoadImage (
TRUE,
gMyImageHandle,
FilePath,
ImageBuffer,
ImageLength,
&ImageHandle
);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);
} else {
Status = BS->StartImage (ImageHandle, NULL, NULL);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);
} else {
retStatus = Status;
}
}
}
if (DecompressedImageBuffer != NULL) {
FreePool (DecompressedImageBuffer);
}
}
}
RomBarOffset = RomBarOffset + ImageSize;
ImageIndex++;
} while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
return retStatus;
}
EFI_STATUS
LoadEfiDriversFromRomImage (
VOID *RomBar,
UINTN RomSize,
CHAR16 *FileName
)
/*++
Routine Description:
Command entry point.
Arguments:
RomBar - Rom
RomSize - Rom size
FileName - The file name
Returns:
EFI_SUCCESS - The command completed successfully
EFI_INVALID_PARAMETER - Command usage error
EFI_UNSUPPORTED - Protocols unsupported
EFI_OUT_OF_RESOURCES - Out of memory
Other value - Unknown error
--*/
{
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
PCI_DATA_STRUCTURE *Pcir;
UINTN ImageIndex;
UINTN RomBarOffset;
UINT32 ImageSize;
UINT16 ImageOffset;
EFI_HANDLE ImageHandle;
EFI_STATUS Status;
EFI_STATUS retStatus;
CHAR16 RomFileName[280];
EFI_DEVICE_PATH_PROTOCOL *FilePath;
BOOLEAN SkipImage;
UINT32 DestinationSize;
UINT32 ScratchSize;
UINT8 *Scratch;
VOID *ImageBuffer;
VOID *DecompressedImageBuffer;
UINT32 ImageLength;
EFI_DECOMPRESS_PROTOCOL *Decompress;
ImageIndex = 0;
retStatus = EFI_NOT_FOUND;
RomBarOffset = (UINTN) RomBar;
do {
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
if (EfiRomHeader->Signature != 0xaa55) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);
return retStatus;
}
Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
ImageSize = Pcir->ImageLength * 512;
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)
) {
if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
) {
ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
ImageSize = EfiRomHeader->InitializationSize * 512;
ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
ImageLength = ImageSize - ImageOffset;
DecompressedImageBuffer = NULL;
//
// decompress here if needed
//
SkipImage = FALSE;
if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
SkipImage = TRUE;
}
if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
Status = BS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, &Decompress);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_DECOMP_NOT_FOUND), HiiHandle);
SkipImage = TRUE;
} else {
SkipImage = TRUE;
Status = Decompress->GetInfo (
Decompress,
ImageBuffer,
ImageLength,
&DestinationSize,
&ScratchSize
);
if (!EFI_ERROR (Status)) {
DecompressedImageBuffer = AllocatePool (DestinationSize);
if (ImageBuffer != NULL) {
Scratch = AllocatePool (ScratchSize);
if (Scratch != NULL) {
Status = Decompress->Decompress (
Decompress,
ImageBuffer,
ImageLength,
DecompressedImageBuffer,
DestinationSize,
Scratch,
ScratchSize
);
if (!EFI_ERROR (Status)) {
ImageBuffer = DecompressedImageBuffer;
ImageLength = DestinationSize;
SkipImage = FALSE;
}
FreePool (Scratch);
}
}
}
}
}
if (SkipImage == FALSE) {
//
// load image and start image
//
SPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
FilePath = FileDevicePath (NULL, RomFileName);
Status = BS->LoadImage (
TRUE,
gMyImageHandle,
FilePath,
ImageBuffer,
ImageLength,
&ImageHandle
);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);
} else {
Status = BS->StartImage (ImageHandle, NULL, NULL);
if (EFI_ERROR (Status)) {
PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);
} else {
retStatus = Status;
}
}
}
if (DecompressedImageBuffer != NULL) {
FreePool (DecompressedImageBuffer);
}
}
}
RomBarOffset = RomBarOffset + ImageSize;
ImageIndex++;
} while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
return retStatus;
}
訂閱:
文章 (Atom)