搜尋此網誌
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;
}
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言