-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BdsBoot.c
-
-Abstract:
-
- BDS Lib functions which relate with create or process the boot
- option.
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-BOOLEAN mEnumBootDevice = FALSE;
-
-//
-// This GUID is used for an EFI Variable that stores the front device pathes
-// for a partial device path that starts with the HD node.
-//
-EFI_GUID mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };
-
-
-
-/**
- Boot the legacy system with the boot option
-
- @param Option The legacy boot option which have BBS device path
-
- @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support
- legacy boot.
- @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot ().
-
-**/
-EFI_STATUS
-BdsLibDoLegacyBoot (
- IN BDS_COMMON_OPTION *Option
- )
-{
- EFI_STATUS Status;
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
-
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
- if (EFI_ERROR (Status)) {
- //
- // If no LegacyBios protocol we do not support legacy boot
- //
- return EFI_UNSUPPORTED;
- }
- //
- // Notes: if we seperate the int 19, then we don't need to refresh BBS
- //
- BdsRefreshBbsTableForBoot (Option);
-
- //
- // Write boot to OS performance data to a file
- //
- PERF_CODE (
- WriteBootToOsPerformanceData ();
- );
-
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));
- return LegacyBios->LegacyBoot (
- LegacyBios,
- (BBS_BBS_DEVICE_PATH *) Option->DevicePath,
- Option->LoadOptionsSize,
- Option->LoadOptions
- );
-}
-
-
-/**
- Process the boot option follow the EFI 1.1 specification and
- special treat the legacy boot option with BBS_DEVICE_PATH.
-
- @param Option The boot option need to be processed
- @param DevicePath The device path which describe where to load the
- boot image or the legcy BBS device path to boot
- the legacy OS
- @param ExitDataSize Returned directly from gBS->StartImage ()
- @param ExitData Returned directly from gBS->StartImage ()
-
- @retval EFI_SUCCESS Status from gBS->StartImage ()
- @retval EFI_NOT_FOUND If the Device Path is not found in the system
-
-**/
-EFI_STATUS
-BdsLibBootViaBootOption (
- IN BDS_COMMON_OPTION * Option,
- IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,
- OUT UINTN *ExitDataSize,
- OUT CHAR16 **ExitData OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_HANDLE ImageHandle;
- EFI_DEVICE_PATH_PROTOCOL *FilePath;
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
- EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;
- EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
- LIST_ENTRY TempBootLists;
-
- //
- // 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 (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &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;
- }
- }
- //
- // Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event
- //
- EfiSignalEventReadyToBoot();
-
-
- //
- // Set Boot Current
- //
- gRT->SetVariable (
- L"BootCurrent",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof (UINT16),
- &Option->BootCurrent
- );
-
- 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) {
- SafeFreePool(Option->DevicePath);
- }
- Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));
- CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
- //
- // Update the shell boot option
- //
- InitializeListHead (&TempBootLists);
- BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");
- }
-
- //
- // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
- //
- gBS->RestoreTPL (TPL_APPLICATION);
-
- DEBUG ((DEBUG_INFO | DEBUG_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 = FileDevicePath (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, (VOID **) &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);
-
- Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);
- DEBUG ((DEBUG_INFO | DEBUG_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 TPL_APPLICATION
- //
- gBS->RaiseTPL (TPL_APPLICATION);
-
- return Status;
-}
-
-
-/**
- Expand a device path that starts with a hard drive media device path node to be a
- full device path that includes the full hardware path to the device. We need
- to do this so it can be booted. As an optimizaiton the front match (the part point
- to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable
- so a connect all is not required on every boot. All successful history device path
- which point to partition node (the front part) will be saved.
-
- @param HardDriveDevicePath EFI Device Path to boot, if it starts with a hard
- drive media device path.
- A Pointer to the full device path.
- @retval NULL Cannot find a valid Hard Drive devic path
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BdsExpandPartitionPartialDevicePathToFull (
- IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
- )
-{
- EFI_STATUS Status;
- UINTN BlockIoHandleCount;
- EFI_HANDLE *BlockIoBuffer;
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- UINTN Index;
- UINTN InstanceNum;
- EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
- UINTN CachedDevicePathSize;
- BOOLEAN DeviceExist;
- BOOLEAN NeedAdjust;
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- UINTN Size;
-
- FullDevicePath = NULL;
- //
- // Check if there is prestore 'HDDP' variable.
- // If exist, search the front path which point to partition node in the variable instants.
- // If fail to find or 'HDDP' not exist, reconnect all and search in all system
- //
- CachedDevicePath = BdsLibGetVariableAndSize (
- L"HDDP",
- &mHdBootVariablePrivateGuid,
- &CachedDevicePathSize
- );
- if (CachedDevicePath != NULL) {
- TempNewDevicePath = CachedDevicePath;
- DeviceExist = FALSE;
- NeedAdjust = FALSE;
- do {
- //
- // Check every instance of the variable
- // First, check wheather the instance contain the partition node, which is needed for distinguishing multi
- // partial partition boot option. Second, check wheather the instance could be connected.
- //
- Instance = GetNextDevicePathInstance (&TempNewDevicePath, &Size);
- if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {
- //
- // Connect the device path instance, the device path point to hard drive media device path node
- // e.g. ACPI() /PCI()/ATA()/Partition()
- //
- Status = BdsLibConnectDevicePath (Instance);
- if (!EFI_ERROR (Status)) {
- DeviceExist = TRUE;
- break;
- }
- }
- //
- // Come here means the first instance is not matched
- //
- NeedAdjust = TRUE;
- SafeFreePool(Instance);
- } while (TempNewDevicePath != NULL);
-
- if (DeviceExist) {
- //
- // Find the matched device path.
- // Append the file path infomration from the boot option and return the fully expanded device path.
- //
- DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
- FullDevicePath = AppendDevicePath (Instance, DevicePath);
-
- //
- // Adjust the 'HDDP' instances sequense if the matched one is not first one.
- //
- if (NeedAdjust) {
- //
- // First delete the matched instance.
- //
- TempNewDevicePath = CachedDevicePath;
- CachedDevicePath = BdsLibDelPartMatchInstance ( CachedDevicePath, Instance );
- SafeFreePool (TempNewDevicePath);
- //
- // Second, append the remaining parth after the matched instance
- //
- TempNewDevicePath = CachedDevicePath;
- CachedDevicePath = AppendDevicePathInstance ( Instance, CachedDevicePath );
- SafeFreePool (TempNewDevicePath);
- //
- // Save the matching Device Path so we don't need to do a connect all next time
- //
- Status = gRT->SetVariable (
- L"HDDP",
- &mHdBootVariablePrivateGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- GetDevicePathSize (CachedDevicePath),
- CachedDevicePath
- );
- }
- SafeFreePool(Instance);
- gBS->FreePool (CachedDevicePath);
- return FullDevicePath;
- }
- }
-
- //
- // If we get here we fail to find or 'HDDP' not exist, and now we need
- // to seach all devices in the system for a matched partition
- //
- BdsLibConnectAllDriversToAllControllers ();
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
- if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {
- //
- // If there was an error or there are no device handles that support
- // the BLOCK_IO Protocol, then return.
- //
- return NULL;
- }
- //
- // Loop through all the device handles that support the BLOCK_IO Protocol
- //
- for (Index = 0; Index < BlockIoHandleCount; Index++) {
-
- Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);
- if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {
- continue;
- }
-
- if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {
- //
- // Find the matched partition device path
- //
- DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
- FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);
-
- //
- // Save the matched patition device path in 'HDDP' variable
- //
- if (CachedDevicePath != NULL) {
- //
- // Save the matched patition device path as first instance of 'HDDP' variable
- //
- if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {
- TempNewDevicePath = CachedDevicePath;
- CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);
- SafeFreePool(TempNewDevicePath);
-
- TempNewDevicePath = CachedDevicePath;
- CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
- SafeFreePool(TempNewDevicePath);
- } else {
- TempNewDevicePath = CachedDevicePath;
- CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);
- SafeFreePool(TempNewDevicePath);
- }
- //
- // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller
- // If the user try to boot many OS in different HDs or partitions, in theary, the 'HDDP' variable maybe become larger and larger.
- //
- InstanceNum = 0;
- TempNewDevicePath = CachedDevicePath;
- while (!IsDevicePathEnd (TempNewDevicePath)) {
- TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
- //
- // Parse one instance
- //
- while (!IsDevicePathEndType (TempNewDevicePath)) {
- TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);
- }
- InstanceNum++;
- //
- // If the CachedDevicePath variable contain too much instance, only remain 12 instances.
- //
- if (InstanceNum >= 12) {
- SetDevicePathEndNode (TempNewDevicePath);
- break;
- }
- }
- } else {
- CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);
- }
-
- //
- // Save the matching Device Path so we don't need to do a connect all next time
- //
- Status = gRT->SetVariable (
- L"HDDP",
- &mHdBootVariablePrivateGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- GetDevicePathSize (CachedDevicePath),
- CachedDevicePath
- );
-
- break;
- }
- }
- gBS->FreePool (CachedDevicePath);
- gBS->FreePool (BlockIoBuffer);
- return FullDevicePath;
-}
-
-
-/**
- Check whether there is a instance in BlockIoDevicePath, which contain multi device path
- instances, has the same partition node with HardDriveDevicePath device path
-
- @param BlockIoDevicePath Multi device path instances which need to check
- @param HardDriveDevicePath A device path which starts with a hard drive media
- device path.
-
- @retval TRUE There is a matched device path instance FALSE
- -There is no matched device path instance
-
-**/
-BOOLEAN
-MatchPartitionDevicePathNode (
- IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
- IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
- )
-{
- HARDDRIVE_DEVICE_PATH *TmpHdPath;
- HARDDRIVE_DEVICE_PATH *TempPath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- BOOLEAN Match;
- EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePathNode;
-
- if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
- return FALSE;
- }
- //
- // Make PreviousDevicePath == the device path node before the end node
- //
- DevicePath = BlockIoDevicePath;
- BlockIoHdDevicePathNode = NULL;
-
- //
- // find the partition device path node
- //
- while (!IsDevicePathEnd (DevicePath)) {
- if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)
- ) {
- BlockIoHdDevicePathNode = DevicePath;
- break;
- }
-
- DevicePath = NextDevicePathNode (DevicePath);
- }
-
- if (BlockIoHdDevicePathNode == NULL) {
- return FALSE;
- }
- //
- // See if the harddrive device path in blockio matches the orig Hard Drive Node
- //
- TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;
- TempPath = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
- Match = FALSE;
- //
- // Check for the match
- //
- if ((TmpHdPath->MBRType == TempPath->MBRType) &&
- (TmpHdPath->SignatureType == TempPath->SignatureType)) {
- switch (TmpHdPath->SignatureType) {
- case SIGNATURE_TYPE_GUID:
- Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)TempPath->Signature);
- break;
- case SIGNATURE_TYPE_MBR:
- Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == *(UINT32 *)(&(TempPath->Signature[0])));
- break;
- default:
- Match = FALSE;
- break;
- }
- }
-
- return Match;
-}
-
-
-/**
- Delete the boot option associated with the handle passed in
-
- @param Handle The handle which present the device path to create
- boot option
-
- @retval EFI_SUCCESS Delete the boot option success
- @retval EFI_NOT_FOUND If the Device Path is not found in the system
- @retval EFI_OUT_OF_RESOURCES Lack of memory resource
- @retval Other Error return value from SetVariable()
-
-**/
-EFI_STATUS
-BdsLibDeleteOptionFromHandle (
- IN EFI_HANDLE Handle
- )
-{
- UINT16 *BootOrder;
- UINT8 *BootOptionVar;
- UINTN BootOrderSize;
- UINTN BootOptionSize;
- EFI_STATUS Status;
- UINTN Index;
- UINT16 BootOption[BOOT_OPTION_MAX_CHAR];
- UINTN DevicePathSize;
- UINTN OptionDevicePathSize;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
- UINT8 *TempPtr;
-
- Status = EFI_SUCCESS;
- BootOrder = NULL;
- BootOrderSize = 0;
-
- BootOrder = BdsLibGetVariableAndSize (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- &BootOrderSize
- );
- if (NULL == BootOrder) {
- return EFI_NOT_FOUND;
- }
-
- DevicePath = DevicePathFromHandle (Handle);
- if (DevicePath == NULL) {
- return EFI_NOT_FOUND;
- }
- DevicePathSize = GetDevicePathSize (DevicePath);
-
- Index = 0;
- while (Index < BootOrderSize / sizeof (UINT16)) {
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
- BootOptionVar = BdsLibGetVariableAndSize (
- BootOption,
- &gEfiGlobalVariableGuid,
- &BootOptionSize
- );
- if (NULL == BootOptionVar) {
- gBS->FreePool (BootOrder);
- return EFI_OUT_OF_RESOURCES;
- }
-
- TempPtr = BootOptionVar;
- TempPtr += sizeof (UINT32) + sizeof (UINT16);
- TempPtr += StrSize ((CHAR16 *) TempPtr);
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
- OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);
-
- //
- // Check whether the device path match
- //
- if ((OptionDevicePathSize == DevicePathSize) &&
- (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {
- BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);
- gBS->FreePool (BootOptionVar);
- break;
- }
-
- gBS->FreePool (BootOptionVar);
- Index++;
- }
-
- Status = gRT->SetVariable (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- BootOrderSize,
- BootOrder
- );
-
- gBS->FreePool (BootOrder);
-
- return Status;
-}
-
-
-/**
- Delete all invalid EFI boot options. The probable invalid boot option could
- be Removable media or Network boot device.
-
- VOID
-
- @retval EFI_SUCCESS Delete all invalid boot option success
- @retval EFI_NOT_FOUND Variable "BootOrder" is not found
- @retval EFI_OUT_OF_RESOURCES Lack of memory resource
- @retval Other Error return value from SetVariable()
-
-**/
-EFI_STATUS
-BdsDeleteAllInvalidEfiBootOption (
- VOID
- )
-{
- UINT16 *BootOrder;
- UINT8 *BootOptionVar;
- UINTN BootOrderSize;
- UINTN BootOptionSize;
- EFI_STATUS Status;
- UINTN Index;
- UINTN Index2;
- UINT16 BootOption[BOOT_OPTION_MAX_CHAR];
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
- UINT8 *TempPtr;
-
- Status = EFI_SUCCESS;
- BootOrder = NULL;
- BootOrderSize = 0;
-
- BootOrder = BdsLibGetVariableAndSize (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- &BootOrderSize
- );
- if (NULL == BootOrder) {
- return EFI_NOT_FOUND;
- }
-
- Index = 0;
- while (Index < BootOrderSize / sizeof (UINT16)) {
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
- BootOptionVar = BdsLibGetVariableAndSize (
- BootOption,
- &gEfiGlobalVariableGuid,
- &BootOptionSize
- );
- if (NULL == BootOptionVar) {
- gBS->FreePool (BootOrder);
- return EFI_OUT_OF_RESOURCES;
- }
-
- TempPtr = BootOptionVar;
- TempPtr += sizeof (UINT32) + sizeof (UINT16);
- TempPtr += StrSize ((CHAR16 *) TempPtr);
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
-
- //
- // Skip legacy boot option (BBS boot device)
- //
- if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&
- (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {
- gBS->FreePool (BootOptionVar);
- Index++;
- continue;
- }
-
- if (!BdsLibIsValidEFIBootOptDevicePath (OptionDevicePath, FALSE)) {
- //
- // Delete this invalid boot option "Boot####"
- //
- Status = gRT->SetVariable (
- BootOption,
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- 0,
- NULL
- );
- //
- // Mark this boot option in boot order as deleted
- //
- BootOrder[Index] = 0xffff;
- }
-
- gBS->FreePool (BootOptionVar);
- Index++;
- }
-
- //
- // Adjust boot order array
- //
- Index2 = 0;
- for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
- if (BootOrder[Index] != 0xffff) {
- BootOrder[Index2] = BootOrder[Index];
- Index2 ++;
- }
- }
- Status = gRT->SetVariable (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- Index2 * sizeof (UINT16),
- BootOrder
- );
-
- gBS->FreePool (BootOrder);
-
- return Status;
-}
-
-
-/**
- This function will enumerate all possible boot device in the system,
- it will only excute once of every boot.
-
- @param BdsBootOptionList The header of the link list which indexed all
- current boot options
-
- @retval EFI_SUCCESS Finished all the boot device enumerate and create
- the boot option base on that boot device
-
-**/
-EFI_STATUS
-BdsLibEnumerateAllBootOption (
- IN OUT LIST_ENTRY *BdsBootOptionList
- )
-{
- EFI_STATUS Status;
- UINT16 FloppyNumber;
- UINT16 CdromNumber;
- UINT16 UsbNumber;
- UINT16 MiscNumber;
- UINT16 NonBlockNumber;
- UINTN NumberBlockIoHandles;
- EFI_HANDLE *BlockIoHandles;
- EFI_BLOCK_IO_PROTOCOL *BlkIo;
- UINTN Index;
- UINTN NumberSimpleNetworkHandles;
- EFI_HANDLE *SimpleNetworkHandles;
- UINTN FvHandleCount;
- EFI_HANDLE *FvHandleBuffer;
- EFI_FV_FILETYPE Type;
- UINTN Size;
- EFI_FV_FILE_ATTRIBUTES Attributes;
- UINT32 AuthenticationStatus;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- UINTN DevicePathType;
- CHAR16 Buffer[40];
- EFI_HANDLE *FileSystemHandles;
- UINTN NumberFileSystemHandles;
- BOOLEAN NeedDelete;
- EFI_IMAGE_DOS_HEADER DosHeader;
- EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
-
- FloppyNumber = 0;
- CdromNumber = 0;
- UsbNumber = 0;
- MiscNumber = 0;
- ZeroMem (Buffer, sizeof (Buffer));
- //
- // If the boot device enumerate happened, just get the boot
- // device from the boot order variable
- //
- if (mEnumBootDevice) {
- BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
- return EFI_SUCCESS;
- }
- //
- // Notes: this dirty code is to get the legacy boot option from the
- // BBS table and create to variable as the EFI boot option, it should
- // be removed after the CSM can provide legacy boot option directly
- //
- REFRESH_LEGACY_BOOT_OPTIONS;
-
- //
- // Delete invalid boot option
- //
- BdsDeleteAllInvalidEfiBootOption ();
- //
- // Parse removable media
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &NumberBlockIoHandles,
- &BlockIoHandles
- );
- for (Index = 0; Index < NumberBlockIoHandles; Index++) {
- Status = gBS->HandleProtocol (
- BlockIoHandles[Index],
- &gEfiBlockIoProtocolGuid,
- (VOID **) &BlkIo
- );
- if (!EFI_ERROR (Status)) {
- if (!BlkIo->Media->RemovableMedia) {
- //
- // skip the non-removable block devices
- //
- continue;
- }
- }
- DevicePath = DevicePathFromHandle (BlockIoHandles[Index]);
- DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);
-
- switch (DevicePathType) {
- case BDS_EFI_ACPI_FLOPPY_BOOT:
- if (FloppyNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy %d", FloppyNumber);
- }
- BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
- FloppyNumber++;
- break;
-
- case BDS_EFI_MESSAGE_ATAPI_BOOT:
- if (CdromNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM %d", CdromNumber);
- }
- BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
- CdromNumber++;
- break;
-
- case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:
- if (UsbNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device %d", UsbNumber);
- }
- BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
- UsbNumber++;
- break;
-
- case BDS_EFI_MESSAGE_SCSI_BOOT:
- if (UsbNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device %d", UsbNumber);
- }
- BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
- UsbNumber++;
- break;
-
- case BDS_EFI_MESSAGE_MISC_BOOT:
- if (MiscNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device %d", MiscNumber);
- }
- BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
- MiscNumber++;
- break;
-
- default:
- break;
- }
- }
-
- if (NumberBlockIoHandles) {
- gBS->FreePool (BlockIoHandles);
- }
-
- //
- // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.
- //
- NonBlockNumber = 0;
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &NumberFileSystemHandles,
- &FileSystemHandles
- );
- for (Index = 0; Index < NumberFileSystemHandles; Index++) {
- Status = gBS->HandleProtocol (
- FileSystemHandles[Index],
- &gEfiBlockIoProtocolGuid,
- (VOID **) &BlkIo
- );
- if (!EFI_ERROR (Status)) {
- //
- // Skip if the file system handle supports a BlkIo protocol,
- //
- continue;
- }
-
- //
- // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
- // machinename is ia32, ia64, x64, ...
- //
- Hdr.Union = &HdrData;
- NeedDelete = TRUE;
- Status = BdsLibGetImageHeader (
- FileSystemHandles[Index],
- DEFAULT_REMOVABLE_FILE_NAME,
- &DosHeader,
- Hdr
- );
- if (!EFI_ERROR (Status) &&
- EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
- Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
- NeedDelete = FALSE;
- }
-
- if (NeedDelete) {
- //
- // No such file or the file is not a EFI application, delete this boot option
- //
- BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
- } else {
- if (NonBlockNumber == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);
- }
- BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);
- NonBlockNumber++;
- }
- }
-
- if (NumberFileSystemHandles) {
- gBS->FreePool (FileSystemHandles);
- }
-
- //
- // Parse Network Boot Device
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleNetworkProtocolGuid,
- NULL,
- &NumberSimpleNetworkHandles,
- &SimpleNetworkHandles
- );
- for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {
- if (Index == 0) {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network");
- } else {
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network %d", Index);
- }
- BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);
- }
-
- if (NumberSimpleNetworkHandles) {
- gBS->FreePool (SimpleNetworkHandles);
- }
-
- //
- // Check if we have on flash shell
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- &FvHandleCount,
- &FvHandleBuffer
- );
- for (Index = 0; Index < FvHandleCount; Index++) {
- //
- // Only care the dispatched FV. If no dispatch protocol on the FV, it is not dispatched, then skip it.
- //
- Status = gBS->HandleProtocol (
- FvHandleBuffer[Index],
- &gEfiFirmwareVolumeDispatchProtocolGuid,
- (VOID **) &Fv
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- gBS->HandleProtocol (
- FvHandleBuffer[Index],
- &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **) &Fv
- );
-
- Status = Fv->ReadFile (
- Fv,
- &gEfiShellFileGuid,
- NULL,
- &Size,
- &Type,
- &Attributes,
- &AuthenticationStatus
- );
- if (EFI_ERROR (Status)) {
- //
- // Skip if no shell file in the FV
- //
- continue;
- }
- //
- // Build the shell boot option
- //
- BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
- }
-
- if (FvHandleCount) {
- gBS->FreePool (FvHandleBuffer);
- }
- //
- // Make sure every boot only have one time
- // boot device enumerate
- //
- BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
- mEnumBootDevice = TRUE;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Build the boot option with the handle parsed in
-
- @param Handle The handle which present the device path to create
- boot option
- @param BdsBootOptionList The header of the link list which indexed all
- current boot options
-
- @return VOID
-
-**/
-VOID
-BdsLibBuildOptionFromHandle (
- IN EFI_HANDLE Handle,
- IN LIST_ENTRY *BdsBootOptionList,
- IN CHAR16 *String
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- DevicePath = DevicePathFromHandle (Handle);
-
- //
- // Create and register new boot option
- //
- BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");
-}
-
-
-/**
- Build the on flash shell boot option with the handle parsed in
-
- @param Handle The handle which present the device path to create
- on flash shell boot option
- @param BdsBootOptionList The header of the link list which indexed all
- current boot options
-
- @return None
-
-**/
-VOID
-BdsLibBuildOptionFromShell (
- IN EFI_HANDLE Handle,
- IN OUT LIST_ENTRY *BdsBootOptionList
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;
-
- DevicePath = DevicePathFromHandle (Handle);
-
- //
- // Build the shell device path
- //
- EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);
- //
- //ShellNode.Header.Type = MEDIA_DEVICE_PATH;
- //ShellNode.Header.SubType = MEDIA_FV_FILEPATH_DP;
- //SetDevicePathNodeLength (&ShellNode.Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
- //CopyMem (&ShellNode.NameGuid, &gEfiShellFileGuid, sizeof (EFI_GUID));
- //
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);
-
- //
- // Create and register the shell boot option
- //
- BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");
-
-}
-
-
-/**
- Boot from the EFI1.1 spec defined "BootNext" variable
-
- None
-
- @return None
-
-**/
-VOID
-BdsLibBootNext (
- VOID
- )
-{
- UINT16 *BootNext;
- UINTN BootNextSize;
- CHAR16 Buffer[20];
- BDS_COMMON_OPTION *BootOption;
- LIST_ENTRY TempList;
- UINTN ExitDataSize;
- CHAR16 *ExitData;
-
- //
- // Init the boot option name buffer and temp link list
- //
- InitializeListHead (&TempList);
- ZeroMem (Buffer, sizeof (Buffer));
-
- BootNext = BdsLibGetVariableAndSize (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- &BootNextSize
- );
-
- //
- // Clear the boot next variable first
- //
- if (BootNext != NULL) {
- gRT->SetVariable (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- 0,
- BootNext
- );
-
- //
- // Start to build the boot option and try to boot
- //
- UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);
- BootOption = BdsLibVariableToOption (&TempList, Buffer);
- BdsLibConnectDevicePath (BootOption->DevicePath);
- BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
- }
-
-}
-
-
-
-/**
- Return the bootable media handle.
- First, check the device is connected
- Second, check whether the device path point to a device which support SimpleFileSystemProtocol,
- Third, detect the the default boot file in the Media, and return the removable Media handle.
-
- @param DevicePath Device Path to a bootable device
-
- @retval NULL The device path points to an EFI bootable Media
- @retval NULL The media on the DevicePath is not bootable
-
-**/
-EFI_HANDLE
-BdsLibGetBootableHandle (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
- EFI_HANDLE Handle;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- VOID *Buffer;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- UINTN Size;
- UINTN TempSize;
- EFI_HANDLE ReturnHandle;
- EFI_HANDLE *SimpleFileSystemHandles;
-
- UINTN NumberSimpleFileSystemHandles;
- UINTN Index;
- EFI_IMAGE_DOS_HEADER DosHeader;
- EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
-
- UpdatedDevicePath = DevicePath;
- //
- // Check whether the device is connected
- //
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);
- if (EFI_ERROR (Status)) {
- //
- // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,
- //
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);
- if (EFI_ERROR (Status)) {
- //
- // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly
- //
- UpdatedDevicePath = DevicePath;
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);
- gBS->ConnectController (Handle, NULL, NULL, TRUE);
- }
- } else {
- //
- // Get BlockIo protocal and check removable attribute
- //
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
- //
- // Issue a dummy read to the device to check for media change.
- // When the removable media is changed, any Block IO read/write will
- // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
- // returned. After the Block IO protocol is reinstalled, subsequent
- // Block IO read/write will success.
- //
- Buffer = AllocatePool (BlockIo->Media->BlockSize);
- if (Buffer != NULL) {
- BlockIo->ReadBlocks (
- BlockIo,
- BlockIo->Media->MediaId,
- 0,
- BlockIo->Media->BlockSize,
- Buffer
- );
- gBS->FreePool (Buffer);
- }
- }
-
- //
- // Detect the the default boot file from removable Media
- //
-
- //
- // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus
- // Try to locate the USB node device path first, if fail then use its previour PCI node to search
- //
- DupDevicePath = DuplicateDevicePath (DevicePath);
- UpdatedDevicePath = DupDevicePath;
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);
- //
- // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node
- // Acpi()/Pci()/Usb() --> Acpi()/Pci()
- //
- if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {
- //
- // Remove the usb node, let the device path only point to PCI node
- //
- SetDevicePathEndNode (UpdatedDevicePath);
- UpdatedDevicePath = DupDevicePath;
- } else {
- UpdatedDevicePath = DevicePath;
- }
-
- //
- // Get the device path size of boot option
- //
- Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node
- ReturnHandle = NULL;
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &NumberSimpleFileSystemHandles,
- &SimpleFileSystemHandles
- );
- for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
- //
- // Get the device path size of SimpleFileSystem handle
- //
- TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
- TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node
- //
- // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
- //
- if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {
- //
- // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media
- // machinename is ia32, ia64, x64, ...
- //
- Hdr.Union = &HdrData;
- Status = BdsLibGetImageHeader (
- SimpleFileSystemHandles[Index],
- DEFAULT_REMOVABLE_FILE_NAME,
- &DosHeader,
- Hdr
- );
- if (!EFI_ERROR (Status) &&
- EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
- Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
- ReturnHandle = SimpleFileSystemHandles[Index];
- break;
- }
- }
- }
-
- if (DupDevicePath != NULL) {
- SafeFreePool(DupDevicePath);
- }
- if (SimpleFileSystemHandles !=NULL ) {
- gBS->FreePool (SimpleFileSystemHandles);
- }
-
- return ReturnHandle;
-}
-
-
-
-
-/**
- Check to see if the network cable is plugged in. If the DevicePath is not
- connected it will be connected.
-
- @param DevicePath Device Path to check
-
- @retval TRUE DevicePath points to an Network that is connected
- @retval FALSE DevicePath does not point to a bootable network
-
-**/
-BOOLEAN
-BdsLibNetworkBootWithMediaPresent (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;
- EFI_HANDLE Handle;
- EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
- BOOLEAN MediaPresent;
-
- MediaPresent = FALSE;
-
- UpdatedDevicePath = DevicePath;
- Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);
- if (EFI_ERROR (Status)) {
- //
- // Device not present so see if we need to connect it
- //
- Status = BdsLibConnectDevicePath (DevicePath);
- if (!EFI_ERROR (Status)) {
- //
- // This one should work after we did the connect
- //
- Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);
- }
- }
-
- if (!EFI_ERROR (Status)) {
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);
- if (!EFI_ERROR (Status)) {
- if (Snp->Mode->MediaPresentSupported) {
- if (Snp->Mode->State == EfiSimpleNetworkInitialized) {
- //
- // In case some one else is using the SNP check to see if it's connected
- //
- MediaPresent = Snp->Mode->MediaPresent;
- } else {
- //
- // No one is using SNP so we need to Start and Initialize so
- // MediaPresent will be valid.
- //
- Status = Snp->Start (Snp);
- if (!EFI_ERROR (Status)) {
- Status = Snp->Initialize (Snp, 0, 0);
- if (!EFI_ERROR (Status)) {
- MediaPresent = Snp->Mode->MediaPresent;
- Snp->Shutdown (Snp);
- }
- Snp->Stop (Snp);
- }
- }
- } else {
- MediaPresent = TRUE;
- }
- }
- }
-
- return MediaPresent;
-}
-
-
-
-/**
- For a bootable Device path, return its boot type
-
- @param DevicePath The bootable device Path to check
-
- @return UINT32 Boot type :
- @return //
- @return // If the device path contains any media deviec path node, it is media boot type
- @return // For the floppy node, handle it as media node
- @return //
- @return BDS_EFI_MEDIA_HD_BOOT
- @return BDS_EFI_MEDIA_CDROM_BOOT
- @return BDS_EFI_ACPI_FLOPPY_BOOT
- @return //
- @return // If the device path not contains any media deviec path node, and
- @return // its last device path node point to a message device path node, it is
- @return // a message boot type
- @return //
- @return BDS_EFI_MESSAGE_ATAPI_BOOT
- @return BDS_EFI_MESSAGE_SCSI_BOOT
- @return BDS_EFI_MESSAGE_USB_DEVICE_BOOT
- @return BDS_EFI_MESSAGE_MISC_BOOT
- @return //
- @return // Legacy boot type
- @return //
- @return BDS_LEGACY_BBS_BOOT
- @return //
- @return // If a EFI Removable BlockIO device path not point to a media and message devie,
- @return // it is unsupported
- @return //
- @return BDS_EFI_UNSUPPORT
-
-**/
-UINT32
-BdsGetBootTypeFromDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- ACPI_HID_DEVICE_PATH *Acpi;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
-
-
- if (NULL == DevicePath) {
- return BDS_EFI_UNSUPPORT;
- }
-
- TempDevicePath = DevicePath;
-
- while (!IsDevicePathEndType (TempDevicePath)) {
- switch (DevicePathType (TempDevicePath)) {
- case BBS_DEVICE_PATH:
- return BDS_LEGACY_BBS_BOOT;
- case MEDIA_DEVICE_PATH:
- if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {
- return BDS_EFI_MEDIA_HD_BOOT;
- } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {
- return BDS_EFI_MEDIA_CDROM_BOOT;
- }
- break;
- case ACPI_DEVICE_PATH:
- Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;
- if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
- return BDS_EFI_ACPI_FLOPPY_BOOT;
- }
- break;
- case MESSAGING_DEVICE_PATH:
- //
- // if the device path not only point to driver device, it is not a messaging device path.
- //
- LastDeviceNode = NextDevicePathNode (TempDevicePath);
- if (!IsDevicePathEndType (LastDeviceNode)) {
- break;
- }
-
- if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {
- return BDS_EFI_MESSAGE_ATAPI_BOOT;
- } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {
- return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;
- } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {
- return BDS_EFI_MESSAGE_SCSI_BOOT;
- }
- return BDS_EFI_MESSAGE_MISC_BOOT;
- default:
- break;
- }
- TempDevicePath = NextDevicePathNode (TempDevicePath);
- }
-
- return BDS_EFI_UNSUPPORT;
-}
-
-
-/**
- Check whether the Device path in a boot option point to a valide bootable device,
- And if CheckMedia is true, check the device is ready to boot now.
-
- DevPath -- the Device path in a boot option
- CheckMedia -- if true, check the device is ready to boot now.
-
- @return TRUE -- the Device path is valide
- @return FALSE -- the Device path is invalide .
-
-**/
-BOOLEAN
-BdsLibIsValidEFIBootOptDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath,
- IN BOOLEAN CheckMedia
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
-
- TempDevicePath = DevPath;
- LastDeviceNode = DevPath;
- //
- // Check if it's a valid boot option for network boot device
- // Only check if there is SimpleNetworkProtocol installed. If yes, that means
- // there is the network card there.
- //
- Status = gBS->LocateDevicePath (
- &gEfiSimpleNetworkProtocolGuid,
- &TempDevicePath,
- &Handle
- );
- if (EFI_ERROR (Status)) {
- //
- // Device not present so see if we need to connect it
- //
- TempDevicePath = DevPath;
- BdsLibConnectDevicePath (TempDevicePath);
- Status = gBS->LocateDevicePath (
- &gEfiSimpleNetworkProtocolGuid,
- &TempDevicePath,
- &Handle
- );
- }
- if (!EFI_ERROR (Status)) {
- if (CheckMedia) {
- //
- // Test if it is ready to boot now
- //
- if (BdsLibNetworkBootWithMediaPresent(DevPath)) {
- return TRUE;
- }
- } else {
- return TRUE;
- }
- }
-
- //
- // If the boot option point to a file, it is a valid EFI boot option,
- // and assume it is ready to boot now
- //
- while (!EfiIsDevicePathEnd (TempDevicePath)) {
- LastDeviceNode = TempDevicePath;
- TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
- }
- if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {
- return TRUE;
- }
-
- //
- // If the boot option point to a internal Shell, it is a valid EFI boot option,
- // and assume it is ready to boot now
- //
- if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {
- return TRUE;
- }
-
- //
- // If the boot option point to a blockIO device, no matter whether or not it is a removeable device, it is a valid EFI boot option
- //
- TempDevicePath = DevPath;
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
- if (EFI_ERROR (Status)) {
- //
- // Device not present so see if we need to connect it
- //
- Status = BdsLibConnectDevicePath (DevPath);
- if (!EFI_ERROR (Status)) {
- //
- // Try again to get the Block Io protocol after we did the connect
- //
- TempDevicePath = DevPath;
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
- }
- }
- if (!EFI_ERROR (Status)) {
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
- if (!EFI_ERROR (Status)) {
- if (CheckMedia) {
- //
- // Test if it is ready to boot now
- //
- if (BdsLibGetBootableHandle (DevPath) != NULL) {
- return TRUE;
- }
- } else {
- return TRUE;
- }
- }
- } else {
- //
- // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,
- //
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);
- if (!EFI_ERROR (Status)) {
- if (CheckMedia) {
- //
- // Test if it is ready to boot now
- //
- if (BdsLibGetBootableHandle (DevPath) != NULL) {
- return TRUE;
- }
- } else {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-
-/**
- According to a file guild, check a Fv file device path is valid. If it is invalid,
- try to return the valid device path.
- FV address maybe changes for memory layout adjust from time to time, use this funciton
- could promise the Fv file device path is right.
-
- @param DevicePath on input, the Fv file device path need to check on
- output, the updated valid Fv file device path
- @param FileGuid the Fv file guild
-
- @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
- parameter
- @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file
- guild at all
- @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it is
- valid
- @retval EFI_SUCCESS has successfully updated the invalid DevicePath,
- and return the updated device path in DevicePath
-
-**/
-EFI_STATUS
-EFIAPI
-BdsLibUpdateFvFileDevicePath (
- IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,
- IN EFI_GUID *FileGuid
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
- EFI_STATUS Status;
- EFI_GUID *GuidPoint;
- UINTN Index;
- UINTN FvHandleCount;
- EFI_HANDLE *FvHandleBuffer;
- EFI_FV_FILETYPE Type;
- UINTN Size;
- EFI_FV_FILE_ATTRIBUTES Attributes;
- UINT32 AuthenticationStatus;
- BOOLEAN FindFvFile;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;
- EFI_HANDLE FoundFvHandle;
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
-
- if ((DevicePath == NULL) || (*DevicePath == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if (FileGuid == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check whether the device path point to the default the input Fv file
- //
- TempDevicePath = *DevicePath;
- LastDeviceNode = TempDevicePath;
- while (!EfiIsDevicePathEnd (TempDevicePath)) {
- LastDeviceNode = TempDevicePath;
- TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
- }
- GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
- (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
- );
- if (GuidPoint == NULL) {
- //
- // if this option does not points to a Fv file, just return EFI_UNSUPPORTED
- //
- return EFI_UNSUPPORTED;
- }
- if (!CompareGuid (GuidPoint, FileGuid)) {
- //
- // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED
- //
- return EFI_UNSUPPORTED;
- }
-
- //
- // Check whether the input Fv file device path is valid
- //
- TempDevicePath = *DevicePath;
- FoundFvHandle = NULL;
- Status = gBS->LocateDevicePath (
- &gEfiFirmwareVolume2ProtocolGuid,
- &TempDevicePath,
- &FoundFvHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->HandleProtocol (
- FoundFvHandle,
- &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **) &Fv
- );
- if (!EFI_ERROR (Status)) {
- //
- // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
- //
- Status = Fv->ReadFile (
- Fv,
- FileGuid,
- NULL,
- &Size,
- &Type,
- &Attributes,
- &AuthenticationStatus
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
- }
- }
-
- //
- // Look for the input wanted FV file in current FV
- // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV
- //
- FindFvFile = FALSE;
- FoundFvHandle = NULL;
- Status = gBS->HandleProtocol (
- mBdsImageHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **) &LoadedImage
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->HandleProtocol (
- LoadedImage->DeviceHandle,
- &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **) &Fv
- );
- if (!EFI_ERROR (Status)) {
- Status = Fv->ReadFile (
- Fv,
- FileGuid,
- NULL,
- &Size,
- &Type,
- &Attributes,
- &AuthenticationStatus
- );
- if (!EFI_ERROR (Status)) {
- FindFvFile = TRUE;
- FoundFvHandle = LoadedImage->DeviceHandle;
- }
- }
- }
- //
- // Second, if fail to find, try to enumerate all FV
- //
- if (!FindFvFile) {
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- &FvHandleCount,
- &FvHandleBuffer
- );
- for (Index = 0; Index < FvHandleCount; Index++) {
- gBS->HandleProtocol (
- FvHandleBuffer[Index],
- &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **) &Fv
- );
-
- Status = Fv->ReadFile (
- Fv,
- FileGuid,
- NULL,
- &Size,
- &Type,
- &Attributes,
- &AuthenticationStatus
- );
- if (EFI_ERROR (Status)) {
- //
- // Skip if input Fv file not in the FV
- //
- continue;
- }
- FindFvFile = TRUE;
- FoundFvHandle = FvHandleBuffer[Index];
- break;
- }
- }
-
- if (FindFvFile) {
- //
- // Build the shell device path
- //
- NewDevicePath = DevicePathFromHandle (FoundFvHandle);
- EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);
- NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);
- *DevicePath = NewDevicePath;
- return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
-}
+/** @file\r
+ BDS Lib functions which relate with create or process the boot\r
+ option.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+BOOLEAN mEnumBootDevice = FALSE;\r
+\r
+//\r
+// This GUID is used for an EFI Variable that stores the front device pathes\r
+// for a partial device path that starts with the HD node.\r
+//\r
+EFI_GUID mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
+\r
+\r
+\r
+/**\r
+ Boot the legacy system with the boot option\r
+\r
+ @param Option The legacy boot option which have BBS device path\r
+\r
+ @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support\r
+ legacy boot.\r
+ @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot ().\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDoLegacyBoot (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no LegacyBios protocol we do not support legacy boot\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Notes: if we seperate the int 19, then we don't need to refresh BBS\r
+ //\r
+ BdsRefreshBbsTableForBoot (Option);\r
+\r
+ //\r
+ // Write boot to OS performance data to a file\r
+ //\r
+ PERF_CODE (\r
+ WriteBootToOsPerformanceData ();\r
+ );\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));\r
+ return LegacyBios->LegacyBoot (\r
+ LegacyBios,\r
+ (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
+ Option->LoadOptionsSize,\r
+ Option->LoadOptions\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Process the boot option follow the EFI 1.1 specification and\r
+ special treat the legacy boot option with BBS_DEVICE_PATH.\r
+\r
+ @param Option The boot option need to be processed\r
+ @param DevicePath The device path which describe where to load the\r
+ boot image or the legcy BBS device path to boot\r
+ the legacy OS\r
+ @param ExitDataSize Returned directly from gBS->StartImage ()\r
+ @param ExitData Returned directly from gBS->StartImage ()\r
+\r
+ @retval EFI_SUCCESS Status from gBS->StartImage ()\r
+ @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBootViaBootOption (\r
+ IN BDS_COMMON_OPTION * Option,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,\r
+ OUT UINTN *ExitDataSize,\r
+ OUT CHAR16 **ExitData OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+ EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;\r
+ EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
+ LIST_ENTRY TempBootLists;\r
+\r
+ //\r
+ // Record the performance data for End of BDS\r
+ //\r
+ PERF_END (0, BDS_TOK, NULL, 0);\r
+\r
+ *ExitDataSize = 0;\r
+ *ExitData = NULL;\r
+\r
+ //\r
+ // Notes: put EFI64 ROM Shadow Solution\r
+ //\r
+ EFI64_SHADOW_ALL_LEGACY_ROM ();\r
+\r
+ //\r
+ // Notes: this code can be remove after the s3 script table\r
+ // hook on the event EFI_EVENT_SIGNAL_READY_TO_BOOT or\r
+ // EFI_EVENT_SIGNAL_LEGACY_BOOT\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save);\r
+ if (!EFI_ERROR (Status)) {\r
+ AcpiS3Save->S3Save (AcpiS3Save, NULL);\r
+ }\r
+ //\r
+ // If it's Device Path that starts with a hard drive path, append it with the front part to compose a\r
+ // full device path\r
+ //\r
+ WorkingDevicePath = NULL;\r
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {\r
+ WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (\r
+ (HARDDRIVE_DEVICE_PATH *)DevicePath\r
+ );\r
+ if (WorkingDevicePath != NULL) {\r
+ DevicePath = WorkingDevicePath;\r
+ }\r
+ }\r
+ //\r
+ // Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event\r
+ //\r
+ EfiSignalEventReadyToBoot();\r
+ \r
+ \r
+ //\r
+ // Set Boot Current\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootCurrent",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (UINT16),\r
+ &Option->BootCurrent\r
+ );\r
+\r
+ if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
+ ) {\r
+ //\r
+ // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
+ //\r
+ return BdsLibDoLegacyBoot (Option);\r
+ }\r
+\r
+ //\r
+ // If the boot option point to Internal FV shell, make sure it is valid\r
+ //\r
+ Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);\r
+ if (!EFI_ERROR(Status)) {\r
+ if (Option->DevicePath != NULL) {\r
+ SafeFreePool(Option->DevicePath);\r
+ }\r
+ Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+ CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+ //\r
+ // Update the shell boot option\r
+ //\r
+ InitializeListHead (&TempBootLists);\r
+ BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+ }\r
+\r
+ //\r
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting EFI way %S\n", Option->Description));\r
+\r
+ Status = gBS->LoadImage (\r
+ TRUE,\r
+ mBdsImageHandle,\r
+ DevicePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+\r
+ //\r
+ // If we didn't find an image directly, we need to try as if it is a removable device boot opotion\r
+ // and load the image according to the default boot behavior for removable device.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // check if there is a bootable removable media could be found in this device path ,\r
+ // and get the bootable media handle\r
+ //\r
+ Handle = BdsLibGetBootableHandle(DevicePath);\r
+ if (Handle == NULL) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ FilePath = FileDevicePath (Handle, DEFAULT_REMOVABLE_FILE_NAME);\r
+ if (FilePath) {\r
+ Status = gBS->LoadImage (\r
+ TRUE,\r
+ mBdsImageHandle,\r
+ FilePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The DevicePath failed, and it's not a valid\r
+ // removable media device.\r
+ //\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // It there is any error from the Boot attempt exit now.\r
+ //\r
+ goto Done;\r
+ }\r
+ //\r
+ // Provide the image with it's load options\r
+ //\r
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (Option->LoadOptionsSize != 0) {\r
+ ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
+ ImageInfo->LoadOptions = Option->LoadOptions;\r
+ }\r
+ //\r
+ // Before calling the image, enable the Watchdog Timer for\r
+ // the 5 Minute period\r
+ //\r
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+ Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
+\r
+ //\r
+ // Clear the Watchdog Timer after the image returns\r
+ //\r
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+\r
+Done:\r
+ //\r
+ // Clear Boot Current\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootCurrent",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ 0,\r
+ &Option->BootCurrent\r
+ );\r
+\r
+ //\r
+ // Raise the TPL level back to TPL_APPLICATION\r
+ //\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Expand a device path that starts with a hard drive media device path node to be a\r
+ full device path that includes the full hardware path to the device. We need\r
+ to do this so it can be booted. As an optimizaiton the front match (the part point\r
+ to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable\r
+ so a connect all is not required on every boot. All successful history device path\r
+ which point to partition node (the front part) will be saved.\r
+\r
+ @param HardDriveDevicePath EFI Device Path to boot, if it starts with a hard\r
+ drive media device path.\r
+ @return A Pointer to the full device path or NULL if a valid Hard Drive devic path\r
+ cannot be found.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsExpandPartitionPartialDevicePathToFull (\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BlockIoHandleCount;\r
+ EFI_HANDLE *BlockIoBuffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN Index;\r
+ UINTN InstanceNum;\r
+ EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINTN CachedDevicePathSize;\r
+ BOOLEAN DeviceExist;\r
+ BOOLEAN NeedAdjust;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ UINTN Size;\r
+\r
+ FullDevicePath = NULL;\r
+ //\r
+ // Check if there is prestore 'HDDP' variable.\r
+ // If exist, search the front path which point to partition node in the variable instants.\r
+ // If fail to find or 'HDDP' not exist, reconnect all and search in all system\r
+ //\r
+ CachedDevicePath = BdsLibGetVariableAndSize (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ &CachedDevicePathSize\r
+ );\r
+ if (CachedDevicePath != NULL) {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ DeviceExist = FALSE;\r
+ NeedAdjust = FALSE;\r
+ do {\r
+ //\r
+ // Check every instance of the variable\r
+ // First, check wheather the instance contain the partition node, which is needed for distinguishing multi\r
+ // partial partition boot option. Second, check wheather the instance could be connected.\r
+ //\r
+ Instance = GetNextDevicePathInstance (&TempNewDevicePath, &Size);\r
+ if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {\r
+ //\r
+ // Connect the device path instance, the device path point to hard drive media device path node\r
+ // e.g. ACPI() /PCI()/ATA()/Partition()\r
+ //\r
+ Status = BdsLibConnectDevicePath (Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Come here means the first instance is not matched\r
+ //\r
+ NeedAdjust = TRUE;\r
+ SafeFreePool(Instance);\r
+ } while (TempNewDevicePath != NULL);\r
+\r
+ if (DeviceExist) {\r
+ //\r
+ // Find the matched device path.\r
+ // Append the file path infomration from the boot option and return the fully expanded device path.\r
+ //\r
+ DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+ FullDevicePath = AppendDevicePath (Instance, DevicePath);\r
+\r
+ //\r
+ // Adjust the 'HDDP' instances sequense if the matched one is not first one.\r
+ //\r
+ if (NeedAdjust) {\r
+ //\r
+ // First delete the matched instance.\r
+ //\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = BdsLibDelPartMatchInstance ( CachedDevicePath, Instance );\r
+ SafeFreePool (TempNewDevicePath);\r
+ //\r
+ // Second, append the remaining parth after the matched instance\r
+ //\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance ( Instance, CachedDevicePath );\r
+ SafeFreePool (TempNewDevicePath);\r
+ //\r
+ // Save the matching Device Path so we don't need to do a connect all next time\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ GetDevicePathSize (CachedDevicePath),\r
+ CachedDevicePath\r
+ );\r
+ }\r
+ SafeFreePool(Instance);\r
+ gBS->FreePool (CachedDevicePath);\r
+ return FullDevicePath;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If we get here we fail to find or 'HDDP' not exist, and now we need\r
+ // to seach all devices in the system for a matched partition\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+ if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {\r
+ //\r
+ // If there was an error or there are no device handles that support\r
+ // the BLOCK_IO Protocol, then return.\r
+ //\r
+ return NULL;\r
+ }\r
+ //\r
+ // Loop through all the device handles that support the BLOCK_IO Protocol\r
+ //\r
+ for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
+\r
+ Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
+ if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
+ continue;\r
+ }\r
+\r
+ if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {\r
+ //\r
+ // Find the matched partition device path\r
+ //\r
+ DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+ FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
+\r
+ //\r
+ // Save the matched patition device path in 'HDDP' variable\r
+ //\r
+ if (CachedDevicePath != NULL) {\r
+ //\r
+ // Save the matched patition device path as first instance of 'HDDP' variable\r
+ //\r
+ if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);\r
+ SafeFreePool(TempNewDevicePath);\r
+\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+ SafeFreePool(TempNewDevicePath);\r
+ } else {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+ SafeFreePool(TempNewDevicePath);\r
+ }\r
+ //\r
+ // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
+ // If the user try to boot many OS in different HDs or partitions, in theary, the 'HDDP' variable maybe become larger and larger.\r
+ //\r
+ InstanceNum = 0;\r
+ TempNewDevicePath = CachedDevicePath;\r
+ while (!IsDevicePathEnd (TempNewDevicePath)) {\r
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+ //\r
+ // Parse one instance\r
+ //\r
+ while (!IsDevicePathEndType (TempNewDevicePath)) {\r
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+ }\r
+ InstanceNum++;\r
+ //\r
+ // If the CachedDevicePath variable contain too much instance, only remain 12 instances.\r
+ //\r
+ if (InstanceNum >= 12) {\r
+ SetDevicePathEndNode (TempNewDevicePath);\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
+ }\r
+\r
+ //\r
+ // Save the matching Device Path so we don't need to do a connect all next time\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ GetDevicePathSize (CachedDevicePath),\r
+ CachedDevicePath\r
+ );\r
+\r
+ break;\r
+ }\r
+ }\r
+ gBS->FreePool (CachedDevicePath);\r
+ gBS->FreePool (BlockIoBuffer);\r
+ return FullDevicePath;\r
+}\r
+\r
+\r
+/**\r
+ Check whether there is a instance in BlockIoDevicePath, which contain multi device path\r
+ instances, has the same partition node with HardDriveDevicePath device path\r
+\r
+ @param BlockIoDevicePath Multi device path instances which need to check\r
+ @param HardDriveDevicePath A device path which starts with a hard drive media\r
+ device path.\r
+\r
+ @retval TRUE There is a matched device path instance FALSE\r
+ -There is no matched device path instance\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+MatchPartitionDevicePathNode (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ )\r
+{\r
+ HARDDRIVE_DEVICE_PATH *TmpHdPath;\r
+ HARDDRIVE_DEVICE_PATH *TempPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN Match;\r
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePathNode;\r
+\r
+ if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Make PreviousDevicePath == the device path node before the end node\r
+ //\r
+ DevicePath = BlockIoDevicePath;\r
+ BlockIoHdDevicePathNode = NULL;\r
+\r
+ //\r
+ // find the partition device path node\r
+ //\r
+ while (!IsDevicePathEnd (DevicePath)) {\r
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
+ ) {\r
+ BlockIoHdDevicePathNode = DevicePath;\r
+ break;\r
+ }\r
+\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ }\r
+\r
+ if (BlockIoHdDevicePathNode == NULL) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
+ //\r
+ TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;\r
+ TempPath = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+ Match = FALSE;\r
+ //\r
+ // Check for the match\r
+ //\r
+ if ((TmpHdPath->MBRType == TempPath->MBRType) &&\r
+ (TmpHdPath->SignatureType == TempPath->SignatureType)) {\r
+ switch (TmpHdPath->SignatureType) {\r
+ case SIGNATURE_TYPE_GUID:\r
+ Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)TempPath->Signature);\r
+ break;\r
+ case SIGNATURE_TYPE_MBR:\r
+ Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == *(UINT32 *)(&(TempPath->Signature[0])));\r
+ break;\r
+ default:\r
+ Match = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Match;\r
+}\r
+\r
+\r
+/**\r
+ Delete the boot option associated with the handle passed in\r
+\r
+ @param Handle The handle which present the device path to create\r
+ boot option\r
+\r
+ @retval EFI_SUCCESS Delete the boot option success\r
+ @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
+ @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
+ @retval Other Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDeleteOptionFromHandle (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
+ UINTN DevicePathSize;\r
+ UINTN OptionDevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ UINT8 *TempPtr;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+ if (DevicePath == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ gBS->FreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = BootOptionVar;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+ OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
+\r
+ //\r
+ // Check whether the device path match\r
+ //\r
+ if ((OptionDevicePathSize == DevicePathSize) &&\r
+ (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {\r
+ BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
+ gBS->FreePool (BootOptionVar);\r
+ break;\r
+ }\r
+\r
+ gBS->FreePool (BootOptionVar);\r
+ Index++;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+\r
+ gBS->FreePool (BootOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Delete all invalid EFI boot options. The probable invalid boot option could\r
+ be Removable media or Network boot device.\r
+\r
+ VOID\r
+\r
+ @retval EFI_SUCCESS Delete all invalid boot option success\r
+ @retval EFI_NOT_FOUND Variable "BootOrder" is not found\r
+ @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
+ @retval Other Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidEfiBootOption (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ UINT8 *TempPtr;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ gBS->FreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = BootOptionVar;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+ //\r
+ // Skip legacy boot option (BBS boot device)\r
+ //\r
+ if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {\r
+ gBS->FreePool (BootOptionVar);\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ if (!BdsLibIsValidEFIBootOptDevicePath (OptionDevicePath, FALSE)) {\r
+ //\r
+ // Delete this invalid boot option "Boot####"\r
+ //\r
+ Status = gRT->SetVariable (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ NULL\r
+ );\r
+ //\r
+ // Mark this boot option in boot order as deleted\r
+ //\r
+ BootOrder[Index] = 0xffff;\r
+ }\r
+\r
+ gBS->FreePool (BootOptionVar);\r
+ Index++;\r
+ }\r
+\r
+ //\r
+ // Adjust boot order array\r
+ //\r
+ Index2 = 0;\r
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BootOrder[Index] != 0xffff) {\r
+ BootOrder[Index2] = BootOrder[Index];\r
+ Index2 ++;\r
+ }\r
+ }\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ Index2 * sizeof (UINT16),\r
+ BootOrder\r
+ );\r
+\r
+ gBS->FreePool (BootOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function will enumerate all possible boot device in the system,\r
+ it will only excute once of every boot.\r
+\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+ @retval EFI_SUCCESS Finished all the boot device enumerate and create\r
+ the boot option base on that boot device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibEnumerateAllBootOption (\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 FloppyNumber;\r
+ UINT16 CdromNumber;\r
+ UINT16 UsbNumber;\r
+ UINT16 MiscNumber;\r
+ UINT16 NonBlockNumber;\r
+ UINTN NumberBlockIoHandles;\r
+ EFI_HANDLE *BlockIoHandles;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ UINTN Index;\r
+ UINTN NumberSimpleNetworkHandles;\r
+ EFI_HANDLE *SimpleNetworkHandles;\r
+ UINTN FvHandleCount;\r
+ EFI_HANDLE *FvHandleBuffer;\r
+ EFI_FV_FILETYPE Type;\r
+ UINTN Size;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN DevicePathType;\r
+ CHAR16 Buffer[40];\r
+ EFI_HANDLE *FileSystemHandles;\r
+ UINTN NumberFileSystemHandles;\r
+ BOOLEAN NeedDelete;\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+\r
+ FloppyNumber = 0;\r
+ CdromNumber = 0;\r
+ UsbNumber = 0;\r
+ MiscNumber = 0;\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+ //\r
+ // If the boot device enumerate happened, just get the boot\r
+ // device from the boot order variable\r
+ //\r
+ if (mEnumBootDevice) {\r
+ BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Notes: this dirty code is to get the legacy boot option from the\r
+ // BBS table and create to variable as the EFI boot option, it should\r
+ // be removed after the CSM can provide legacy boot option directly\r
+ //\r
+ REFRESH_LEGACY_BOOT_OPTIONS;\r
+\r
+ //\r
+ // Delete invalid boot option\r
+ //\r
+ BdsDeleteAllInvalidEfiBootOption ();\r
+ //\r
+ // Parse removable media\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &NumberBlockIoHandles,\r
+ &BlockIoHandles\r
+ );\r
+ for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ BlockIoHandles[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (!BlkIo->Media->RemovableMedia) {\r
+ //\r
+ // skip the non-removable block devices\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+ DevicePath = DevicePathFromHandle (BlockIoHandles[Index]);\r
+ DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
+\r
+ switch (DevicePathType) {\r
+ case BDS_EFI_ACPI_FLOPPY_BOOT:\r
+ if (FloppyNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy %d", FloppyNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ FloppyNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
+ if (CdromNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM %d", CdromNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ CdromNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
+ if (UsbNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device %d", UsbNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ UsbNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_SCSI_BOOT:\r
+ if (UsbNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device %d", UsbNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ UsbNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_MISC_BOOT:\r
+ if (MiscNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device %d", MiscNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ MiscNumber++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (NumberBlockIoHandles) {\r
+ gBS->FreePool (BlockIoHandles);\r
+ }\r
+\r
+ //\r
+ // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.\r
+ //\r
+ NonBlockNumber = 0;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NumberFileSystemHandles,\r
+ &FileSystemHandles\r
+ );\r
+ for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ FileSystemHandles[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if the file system handle supports a BlkIo protocol,\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ Hdr.Union = &HdrData;\r
+ NeedDelete = TRUE;\r
+ Status = BdsLibGetImageHeader (\r
+ FileSystemHandles[Index],\r
+ DEFAULT_REMOVABLE_FILE_NAME,\r
+ &DosHeader,\r
+ Hdr\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+ Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ NeedDelete = FALSE;\r
+ }\r
+\r
+ if (NeedDelete) {\r
+ //\r
+ // No such file or the file is not a EFI application, delete this boot option\r
+ //\r
+ BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
+ } else {\r
+ if (NonBlockNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
+ NonBlockNumber++;\r
+ }\r
+ }\r
+\r
+ if (NumberFileSystemHandles) {\r
+ gBS->FreePool (FileSystemHandles);\r
+ }\r
+\r
+ //\r
+ // Parse Network Boot Device\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ NULL,\r
+ &NumberSimpleNetworkHandles,\r
+ &SimpleNetworkHandles\r
+ );\r
+ for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {\r
+ if (Index == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network %d", Index);\r
+ }\r
+ BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);\r
+ }\r
+\r
+ if (NumberSimpleNetworkHandles) {\r
+ gBS->FreePool (SimpleNetworkHandles);\r
+ }\r
+\r
+ //\r
+ // Check if we have on flash shell\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &FvHandleCount,\r
+ &FvHandleBuffer\r
+ );\r
+ for (Index = 0; Index < FvHandleCount; Index++) {\r
+ //\r
+ // Only care the dispatched FV. If no dispatch protocol on the FV, it is not dispatched, then skip it.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolumeDispatchProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ \r
+ gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ &gEfiShellFileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if no shell file in the FV\r
+ //\r
+ continue;\r
+ }\r
+ //\r
+ // Build the shell boot option\r
+ //\r
+ BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
+ }\r
+\r
+ if (FvHandleCount) {\r
+ gBS->FreePool (FvHandleBuffer);\r
+ }\r
+ //\r
+ // Make sure every boot only have one time\r
+ // boot device enumerate\r
+ //\r
+ BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ mEnumBootDevice = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Build the boot option with the handle parsed in\r
+\r
+ @param Handle The handle which present the device path to create\r
+ boot option\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+ @return VOID\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromHandle (\r
+ IN EFI_HANDLE Handle,\r
+ IN LIST_ENTRY *BdsBootOptionList,\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+\r
+ //\r
+ // Create and register new boot option\r
+ //\r
+ BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");\r
+}\r
+\r
+\r
+/**\r
+ Build the on flash shell boot option with the handle parsed in\r
+\r
+ @param Handle The handle which present the device path to create\r
+ on flash shell boot option\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromShell (\r
+ IN EFI_HANDLE Handle,\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
+\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+\r
+ //\r
+ // Build the shell device path\r
+ //\r
+ EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
+ //\r
+ //ShellNode.Header.Type = MEDIA_DEVICE_PATH;\r
+ //ShellNode.Header.SubType = MEDIA_FV_FILEPATH_DP;\r
+ //SetDevicePathNodeLength (&ShellNode.Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));\r
+ //CopyMem (&ShellNode.NameGuid, &gEfiShellFileGuid, sizeof (EFI_GUID));\r
+ //\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
+\r
+ //\r
+ // Create and register the shell boot option\r
+ //\r
+ BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+\r
+}\r
+\r
+\r
+/**\r
+ Boot from the EFI1.1 spec defined "BootNext" variable\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBootNext (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootNext;\r
+ UINTN BootNextSize;\r
+ CHAR16 Buffer[20];\r
+ BDS_COMMON_OPTION *BootOption;\r
+ LIST_ENTRY TempList;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+\r
+ //\r
+ // Init the boot option name buffer and temp link list\r
+ //\r
+ InitializeListHead (&TempList);\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+ BootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ //\r
+ // Clear the boot next variable first\r
+ //\r
+ if (BootNext != NULL) {\r
+ gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ BootNext\r
+ );\r
+\r
+ //\r
+ // Start to build the boot option and try to boot\r
+ //\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
+ BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+ BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+/**\r
+ Return the bootable media handle.\r
+ First, check the device is connected\r
+ Second, check whether the device path point to a device which support SimpleFileSystemProtocol,\r
+ Third, detect the the default boot file in the Media, and return the removable Media handle.\r
+\r
+ @param DevicePath Device Path to a bootable device\r
+\r
+ @retval NULL The device path points to an EFI bootable Media\r
+ @retval NULL The media on the DevicePath is not bootable\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+BdsLibGetBootableHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
+ EFI_HANDLE Handle;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ VOID *Buffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ UINTN Size;\r
+ UINTN TempSize;\r
+ EFI_HANDLE ReturnHandle;\r
+ EFI_HANDLE *SimpleFileSystemHandles;\r
+\r
+ UINTN NumberSimpleFileSystemHandles;\r
+ UINTN Index;\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+\r
+ UpdatedDevicePath = DevicePath;\r
+ //\r
+ // Check whether the device is connected\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly\r
+ //\r
+ UpdatedDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+ }\r
+ } else {\r
+ //\r
+ // Get BlockIo protocal and check removable attribute\r
+ //\r
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+ //\r
+ // Issue a dummy read to the device to check for media change.\r
+ // When the removable media is changed, any Block IO read/write will\r
+ // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
+ // returned. After the Block IO protocol is reinstalled, subsequent\r
+ // Block IO read/write will success.\r
+ //\r
+ Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
+ if (Buffer != NULL) {\r
+ BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ BlockIo->Media->MediaId,\r
+ 0,\r
+ BlockIo->Media->BlockSize,\r
+ Buffer\r
+ );\r
+ gBS->FreePool (Buffer);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Detect the the default boot file from removable Media\r
+ //\r
+\r
+ //\r
+ // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus\r
+ // Try to locate the USB node device path first, if fail then use its previour PCI node to search\r
+ //\r
+ DupDevicePath = DuplicateDevicePath (DevicePath);\r
+ UpdatedDevicePath = DupDevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ //\r
+ // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node\r
+ // Acpi()/Pci()/Usb() --> Acpi()/Pci()\r
+ //\r
+ if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&\r
+ (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {\r
+ //\r
+ // Remove the usb node, let the device path only point to PCI node\r
+ //\r
+ SetDevicePathEndNode (UpdatedDevicePath);\r
+ UpdatedDevicePath = DupDevicePath;\r
+ } else {\r
+ UpdatedDevicePath = DevicePath;\r
+ }\r
+\r
+ //\r
+ // Get the device path size of boot option\r
+ //\r
+ Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+ ReturnHandle = NULL;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NumberSimpleFileSystemHandles,\r
+ &SimpleFileSystemHandles\r
+ );\r
+ for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
+ //\r
+ // Get the device path size of SimpleFileSystem handle\r
+ //\r
+ TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
+ TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+ //\r
+ // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path\r
+ //\r
+ if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {\r
+ //\r
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ Hdr.Union = &HdrData;\r
+ Status = BdsLibGetImageHeader (\r
+ SimpleFileSystemHandles[Index],\r
+ DEFAULT_REMOVABLE_FILE_NAME,\r
+ &DosHeader,\r
+ Hdr\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+ Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ ReturnHandle = SimpleFileSystemHandles[Index];\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (DupDevicePath != NULL) {\r
+ SafeFreePool(DupDevicePath);\r
+ }\r
+ if (SimpleFileSystemHandles !=NULL ) {\r
+ gBS->FreePool (SimpleFileSystemHandles);\r
+ }\r
+\r
+ return ReturnHandle;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Check to see if the network cable is plugged in. If the DevicePath is not\r
+ connected it will be connected.\r
+\r
+ @param DevicePath Device Path to check\r
+\r
+ @retval TRUE DevicePath points to an Network that is connected\r
+ @retval FALSE DevicePath does not point to a bootable network\r
+\r
+**/\r
+BOOLEAN\r
+BdsLibNetworkBootWithMediaPresent (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
+ EFI_HANDLE Handle;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+ BOOLEAN MediaPresent;\r
+\r
+ MediaPresent = FALSE;\r
+\r
+ UpdatedDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ Status = BdsLibConnectDevicePath (DevicePath);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // This one should work after we did the connect\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Snp->Mode->MediaPresentSupported) {\r
+ if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
+ //\r
+ // In case some one else is using the SNP check to see if it's connected\r
+ //\r
+ MediaPresent = Snp->Mode->MediaPresent;\r
+ } else {\r
+ //\r
+ // No one is using SNP so we need to Start and Initialize so\r
+ // MediaPresent will be valid.\r
+ //\r
+ Status = Snp->Start (Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Snp->Initialize (Snp, 0, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ MediaPresent = Snp->Mode->MediaPresent;\r
+ Snp->Shutdown (Snp);\r
+ }\r
+ Snp->Stop (Snp);\r
+ }\r
+ }\r
+ } else {\r
+ MediaPresent = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return MediaPresent;\r
+}\r
+\r
+\r
+\r
+/**\r
+ For a bootable Device path, return its boot type\r
+\r
+ @param DevicePath The bootable device Path to check\r
+\r
+ @retval BDS_EFI_MEDIA_HD_BOOT If the device path contains any media deviec path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_MEDIA_CDROM_BOOT If the device path contains any media deviec path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_ACPI_FLOPPY_BOOT If the device path contains any media deviec path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_MESSAGE_ATAPI_BOOT If the device path not contains any media deviec path node, and\r
+ its last device path node point to a message device path node, it is\r
+ \r
+ @retval BDS_EFI_MESSAGE_SCSI_BOOT If the device path not contains any media deviec path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_EFI_MESSAGE_USB_DEVICE_BOOT If the device path not contains any media deviec path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_EFI_MESSAGE_MISC_BOOT If the device path not contains any media deviec path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_LEGACY_BBS_BOOT Legacy boot type\r
+ @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path not point to a media and message devie, \r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+BdsGetBootTypeFromDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+\r
+\r
+ if (NULL == DevicePath) {\r
+ return BDS_EFI_UNSUPPORT;\r
+ }\r
+\r
+ TempDevicePath = DevicePath;\r
+\r
+ while (!IsDevicePathEndType (TempDevicePath)) {\r
+ switch (DevicePathType (TempDevicePath)) {\r
+ case BBS_DEVICE_PATH:\r
+ return BDS_LEGACY_BBS_BOOT;\r
+ case MEDIA_DEVICE_PATH:\r
+ if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {\r
+ return BDS_EFI_MEDIA_HD_BOOT;\r
+ } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {\r
+ return BDS_EFI_MEDIA_CDROM_BOOT;\r
+ }\r
+ break;\r
+ case ACPI_DEVICE_PATH:\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;\r
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {\r
+ return BDS_EFI_ACPI_FLOPPY_BOOT;\r
+ }\r
+ break;\r
+ case MESSAGING_DEVICE_PATH:\r
+ //\r
+ // if the device path not only point to driver device, it is not a messaging device path.\r
+ //\r
+ LastDeviceNode = NextDevicePathNode (TempDevicePath);\r
+ if (!IsDevicePathEndType (LastDeviceNode)) {\r
+ break;\r
+ }\r
+\r
+ if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {\r
+ return BDS_EFI_MESSAGE_ATAPI_BOOT;\r
+ } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {\r
+ return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
+ } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {\r
+ return BDS_EFI_MESSAGE_SCSI_BOOT;\r
+ }\r
+ return BDS_EFI_MESSAGE_MISC_BOOT;\r
+ default:\r
+ break;\r
+ }\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+\r
+ return BDS_EFI_UNSUPPORT;\r
+}\r
+\r
+\r
+/**\r
+ Check whether the Device path in a boot option point to a valide bootable device,\r
+ And if CheckMedia is true, check the device is ready to boot now.\r
+\r
+ DevPath -- the Device path in a boot option\r
+ CheckMedia -- if true, check the device is ready to boot now.\r
+\r
+ @return TRUE -- the Device path is valide\r
+ @return FALSE -- the Device path is invalide .\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibIsValidEFIBootOptDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath,\r
+ IN BOOLEAN CheckMedia\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ TempDevicePath = DevPath;\r
+ LastDeviceNode = DevPath;\r
+ //\r
+ // Check if it's a valid boot option for network boot device\r
+ // Only check if there is SimpleNetworkProtocol installed. If yes, that means\r
+ // there is the network card there.\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &TempDevicePath,\r
+ &Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ TempDevicePath = DevPath;\r
+ BdsLibConnectDevicePath (TempDevicePath);\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &TempDevicePath,\r
+ &Handle\r
+ );\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If the boot option point to a file, it is a valid EFI boot option,\r
+ // and assume it is ready to boot now\r
+ //\r
+ while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
+ LastDeviceNode = TempDevicePath;\r
+ TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
+ }\r
+ if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // If the boot option point to a internal Shell, it is a valid EFI boot option,\r
+ // and assume it is ready to boot now\r
+ //\r
+ if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // If the boot option point to a blockIO device, no matter whether or not it is a removeable device, it is a valid EFI boot option\r
+ //\r
+ TempDevicePath = DevPath;\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ Status = BdsLibConnectDevicePath (DevPath);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Try again to get the Block Io protocol after we did the connect\r
+ //\r
+ TempDevicePath = DevPath;\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+ }\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ According to a file guild, check a Fv file device path is valid. If it is invalid,\r
+ try to return the valid device path.\r
+ FV address maybe changes for memory layout adjust from time to time, use this funciton\r
+ could promise the Fv file device path is right.\r
+\r
+ @param DevicePath on input, the Fv file device path need to check on\r
+ output, the updated valid Fv file device path\r
+ @param FileGuid the Fv file guild\r
+\r
+ @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid\r
+ parameter\r
+ @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file\r
+ guild at all\r
+ @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it is\r
+ valid\r
+ @retval EFI_SUCCESS has successfully updated the invalid DevicePath,\r
+ and return the updated device path in DevicePath\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateFvFileDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,\r
+ IN EFI_GUID *FileGuid\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+ EFI_STATUS Status;\r
+ EFI_GUID *GuidPoint;\r
+ UINTN Index;\r
+ UINTN FvHandleCount;\r
+ EFI_HANDLE *FvHandleBuffer;\r
+ EFI_FV_FILETYPE Type;\r
+ UINTN Size;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINT32 AuthenticationStatus;\r
+ BOOLEAN FindFvFile;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
+ EFI_HANDLE FoundFvHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+\r
+ if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (FileGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check whether the device path point to the default the input Fv file\r
+ //\r
+ TempDevicePath = *DevicePath;\r
+ LastDeviceNode = TempDevicePath;\r
+ while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
+ LastDeviceNode = TempDevicePath;\r
+ TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
+ }\r
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (\r
+ (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode\r
+ );\r
+ if (GuidPoint == NULL) {\r
+ //\r
+ // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ if (!CompareGuid (GuidPoint, FileGuid)) {\r
+ //\r
+ // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check whether the input Fv file device path is valid\r
+ //\r
+ TempDevicePath = *DevicePath;\r
+ FoundFvHandle = NULL;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ &TempDevicePath,\r
+ &FoundFvHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (\r
+ FoundFvHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
+ //\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Look for the input wanted FV file in current FV\r
+ // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV\r
+ //\r
+ FindFvFile = FALSE;\r
+ FoundFvHandle = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ mBdsImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImage\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (\r
+ LoadedImage->DeviceHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ FindFvFile = TRUE;\r
+ FoundFvHandle = LoadedImage->DeviceHandle;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Second, if fail to find, try to enumerate all FV\r
+ //\r
+ if (!FindFvFile) {\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &FvHandleCount,\r
+ &FvHandleBuffer\r
+ );\r
+ for (Index = 0; Index < FvHandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if input Fv file not in the FV\r
+ //\r
+ continue;\r
+ }\r
+ FindFvFile = TRUE;\r
+ FoundFvHandle = FvHandleBuffer[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FindFvFile) {\r
+ //\r
+ // Build the shell device path\r
+ //\r
+ NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
+ EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
+ NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
+ *DevicePath = NewDevicePath;\r
+ return EFI_SUCCESS;\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BdsConnect.c
-
-Abstract:
-
- BDS Lib functions which relate with connect the device
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-
-/**
- This function will connect all the system driver to controller
- first, and then special connect the default console, this make
- sure all the system controller avialbe and the platform default
- console connected.
-
- None
-
- @return None
-
-**/
-VOID
-BdsLibConnectAll (
- VOID
- )
-{
- //
- // Connect the platform console first
- //
- BdsLibConnectAllDefaultConsoles ();
-
- //
- // Generic way to connect all the drivers
- //
- BdsLibConnectAllDriversToAllControllers ();
-
- //
- // Here we have the assumption that we have already had
- // platform default console
- //
- BdsLibConnectAllDefaultConsoles ();
-}
-
-
-/**
- This function will connect all the system drivers to all controllers
- first, and then connect all the console devices the system current
- have. After this we should get all the device work and console avariable
- if the system have console device.
-
- None
-
- @return None
-
-**/
-VOID
-BdsLibGenericConnectAll (
- VOID
- )
-{
- //
- // Most generic way to connect all the drivers
- //
- BdsLibConnectAllDriversToAllControllers ();
- BdsLibConnectAllConsoles ();
-}
-
-
-/**
- This function will create all handles associate with every device
- path node. If the handle associate with one device path node can not
- be created success, then still give one chance to do the dispatch,
- which load the missing drivers if possible.
-
- @param DevicePathToConnect The device path which will be connected, it can be
- a multi-instance device path
-
- @retval EFI_SUCCESS All handles associate with every device path node
- have been created
- @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
- @retval EFI_NOT_FOUND Create the handle associate with one device path
- node failed
-
-**/
-EFI_STATUS
-BdsLibConnectDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *Next;
- EFI_HANDLE Handle;
- EFI_HANDLE PreviousHandle;
- UINTN Size;
-
- if (DevicePathToConnect == NULL) {
- return EFI_SUCCESS;
- }
-
- DevicePath = DuplicateDevicePath (DevicePathToConnect);
- CopyOfDevicePath = DevicePath;
- if (DevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- do {
- //
- // The outer loop handles multi instance device paths.
- // Only console variables contain multiple instance device paths.
- //
- // After this call DevicePath points to the next Instance
- //
- Instance = GetNextDevicePathInstance (&DevicePath, &Size);
- Next = Instance;
- while (!IsDevicePathEndType (Next)) {
- Next = NextDevicePathNode (Next);
- }
-
- SetDevicePathEndNode (Next);
-
- //
- // Start the real work of connect with RemainingDevicePath
- //
- PreviousHandle = NULL;
- do {
- //
- // Find the handle that best matches the Device Path. If it is only a
- // partial match the remaining part of the device path is returned in
- // RemainingDevicePath.
- //
- RemainingDevicePath = Instance;
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
-
- if (!EFI_ERROR (Status)) {
- if (Handle == PreviousHandle) {
- //
- // If no forward progress is made try invoking the Dispatcher.
- // A new FV may have been added to the system an new drivers
- // may now be found.
- // Status == EFI_SUCCESS means a driver was dispatched
- // Status == EFI_NOT_FOUND means no new drivers were dispatched
- //
- Status = gDS->Dispatch ();
- }
-
- if (!EFI_ERROR (Status)) {
- PreviousHandle = Handle;
- //
- // Connect all drivers that apply to Handle and RemainingDevicePath,
- // the Recursive flag is FALSE so only one level will be expanded.
- //
- // Do not check the connect status here, if the connect controller fail,
- // then still give the chance to do dispatch, because partial
- // RemainingDevicepath may be in the new FV
- //
- // 1. If the connect fail, RemainingDevicepath and handle will not
- // change, so next time will do the dispatch, then dispatch's status
- // will take effect
- // 2. If the connect success, the RemainingDevicepath and handle will
- // change, then avoid the dispatch, we have chance to continue the
- // next connection
- //
- gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
- }
- }
- //
- // Loop until RemainingDevicePath is an empty device path
- //
- } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
-
- } while (DevicePath != NULL);
-
- if (CopyOfDevicePath != NULL) {
- gBS->FreePool (CopyOfDevicePath);
- }
- //
- // All handle with DevicePath exists in the handle database
- //
- return Status;
-}
-
-
-/**
- This function will connect all current system handles recursively. The
- connection will finish until every handle's child handle created if it have.
-
- None
-
- @retval EFI_SUCCESS All handles and it's child handle have been
- connected
- @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
-
-**/
-EFI_STATUS
-BdsLibConnectAllEfi (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
-
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
- }
-
- gBS->FreePool (HandleBuffer);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- This function will disconnect all current system handles. The disconnection
- will finish until every handle have been disconnected.
-
- None
-
- @retval EFI_SUCCESS All handles have been disconnected
- @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
-
-**/
-EFI_STATUS
-BdsLibDisconnectAllEfi (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
-
- //
- // Disconnect all
- //
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
- }
-
- gBS->FreePool (HandleBuffer);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Connects all drivers to all controllers.
- This function make sure all the current system driver will manage
- the correspoinding controllers if have. And at the same time, make
- sure all the system controllers have driver to manage it if have.
-
- None
-
- @return None
-
-**/
-VOID
-BdsLibConnectAllDriversToAllControllers (
- VOID
- )
-{
- EFI_STATUS Status;
-
- do {
- //
- // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
- //
- BdsLibConnectAllEfi ();
-
- //
- // Check to see if it's possible to dispatch an more DXE drivers.
- // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
- // If anything is Dispatched Status == EFI_SUCCESS and we will try
- // the connect again.
- //
- Status = gDS->Dispatch ();
-
- } while (!EFI_ERROR (Status));
-
-}
-
-
-/**
- Connect the specific Usb device which match the short form device path,
- and whose bus is determined by Host Controller (Uhci or Ehci)
-
- @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci
- (0xFF)
- @param RemainingDevicePath a short-form device path that starts with the first
- element being a USB WWID or a USB Class device
- path
-
- @return EFI_INVALID_PARAMETER
- @return EFI_SUCCESS
- @return EFI_NOT_FOUND
-
-**/
-EFI_STATUS
-BdsLibConnectUsbDevByShortFormDP(
- IN UINT8 HostControllerPI,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleArray;
- UINTN HandleArrayCount;
- UINTN Index;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT8 Class[3];
- BOOLEAN AtLeastOneConnected;
-
- //
- // Check the passed in parameters
- //
- if (RemainingDevicePath == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||
- ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)
- && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)
- )) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (HostControllerPI != 0xFF &&
- HostControllerPI != 0x00 &&
- HostControllerPI != 0x20) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Find the usb host controller firstly, then connect with the remaining device path
- //
- AtLeastOneConnected = FALSE;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiPciIoProtocolGuid,
- NULL,
- &HandleArrayCount,
- &HandleArray
- );
- if (!EFI_ERROR (Status)) {
- for (Index = 0; Index < HandleArrayCount; Index++) {
- Status = gBS->HandleProtocol (
- HandleArray[Index],
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (!EFI_ERROR (Status)) {
- //
- // Check whether the Pci device is the wanted usb host controller
- //
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
- if (!EFI_ERROR (Status)) {
- if ((PCI_CLASS_SERIAL == Class[2]) &&
- (PCI_CLASS_SERIAL_USB == Class[1])) {
- if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {
- Status = gBS->ConnectController (
- HandleArray[Index],
- NULL,
- RemainingDevicePath,
- FALSE
- );
- if (!EFI_ERROR(Status)) {
- AtLeastOneConnected = TRUE;
- }
- }
- }
- }
- }
- }
-
- if (AtLeastOneConnected) {
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
+/** @file\r
+ BDS Lib functions which relate with connect the device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+/**\r
+ This function will connect all the system driver to controller\r
+ first, and then special connect the default console, this make\r
+ sure all the system controller avialbe and the platform default\r
+ console connected.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAll (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Connect the platform console first\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+\r
+ //\r
+ // Generic way to connect all the drivers\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+\r
+ //\r
+ // Here we have the assumption that we have already had\r
+ // platform default console\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+ This function will connect all the system drivers to all controllers\r
+ first, and then connect all the console devices the system current\r
+ have. After this we should get all the device work and console avariable\r
+ if the system have console device.\r
+\r
+ None\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+BdsLibGenericConnectAll (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Most generic way to connect all the drivers\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ BdsLibConnectAllConsoles ();\r
+}\r
+\r
+\r
+/**\r
+ This function will create all handles associate with every device\r
+ path node. If the handle associate with one device path node can not\r
+ be created success, then still give one chance to do the dispatch,\r
+ which load the missing drivers if possible.\r
+\r
+ @param DevicePathToConnect The device path which will be connected, it can be\r
+ a multi-instance device path\r
+\r
+ @retval EFI_SUCCESS All handles associate with every device path node\r
+ have been created\r
+ @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles\r
+ @retval EFI_NOT_FOUND Create the handle associate with one device path\r
+ node failed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE PreviousHandle;\r
+ UINTN Size;\r
+\r
+ if (DevicePathToConnect == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ DevicePath = DuplicateDevicePath (DevicePathToConnect);\r
+ CopyOfDevicePath = DevicePath;\r
+ if (DevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ do {\r
+ //\r
+ // The outer loop handles multi instance device paths.\r
+ // Only console variables contain multiple instance device paths.\r
+ //\r
+ // After this call DevicePath points to the next Instance\r
+ //\r
+ Instance = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ Next = Instance;\r
+ while (!IsDevicePathEndType (Next)) {\r
+ Next = NextDevicePathNode (Next);\r
+ }\r
+\r
+ SetDevicePathEndNode (Next);\r
+\r
+ //\r
+ // Start the real work of connect with RemainingDevicePath\r
+ //\r
+ PreviousHandle = NULL;\r
+ do {\r
+ //\r
+ // Find the handle that best matches the Device Path. If it is only a\r
+ // partial match the remaining part of the device path is returned in\r
+ // RemainingDevicePath.\r
+ //\r
+ RemainingDevicePath = Instance;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Handle == PreviousHandle) {\r
+ //\r
+ // If no forward progress is made try invoking the Dispatcher.\r
+ // A new FV may have been added to the system an new drivers\r
+ // may now be found.\r
+ // Status == EFI_SUCCESS means a driver was dispatched\r
+ // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+ //\r
+ Status = gDS->Dispatch ();\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ PreviousHandle = Handle;\r
+ //\r
+ // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+ // the Recursive flag is FALSE so only one level will be expanded.\r
+ //\r
+ // Do not check the connect status here, if the connect controller fail,\r
+ // then still give the chance to do dispatch, because partial\r
+ // RemainingDevicepath may be in the new FV\r
+ //\r
+ // 1. If the connect fail, RemainingDevicepath and handle will not\r
+ // change, so next time will do the dispatch, then dispatch's status\r
+ // will take effect\r
+ // 2. If the connect success, the RemainingDevicepath and handle will\r
+ // change, then avoid the dispatch, we have chance to continue the\r
+ // next connection\r
+ //\r
+ gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+ }\r
+ }\r
+ //\r
+ // Loop until RemainingDevicePath is an empty device path\r
+ //\r
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+ } while (DevicePath != NULL);\r
+\r
+ if (CopyOfDevicePath != NULL) {\r
+ gBS->FreePool (CopyOfDevicePath);\r
+ }\r
+ //\r
+ // All handle with DevicePath exists in the handle database\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function will connect all current system handles recursively. The\r
+ connection will finish until every handle's child handle created if it have.\r
+\r
+ @retval EFI_SUCCESS All handles and it's child handle have been\r
+ connected\r
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllEfi (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+ }\r
+\r
+ gBS->FreePool (HandleBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will disconnect all current system handles. The disconnection\r
+ will finish until every handle have been disconnected.\r
+\r
+ @retval EFI_SUCCESS All handles have been disconnected\r
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibDisconnectAllEfi (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Disconnect all\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+ }\r
+\r
+ gBS->FreePool (HandleBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Connects all drivers to all controllers.\r
+ This function make sure all the current system driver will manage\r
+ the correspoinding controllers if have. And at the same time, make\r
+ sure all the system controllers have driver to manage it if have.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllDriversToAllControllers (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ do {\r
+ //\r
+ // Connect All EFI 1.10 drivers following EFI 1.10 algorithm\r
+ //\r
+ BdsLibConnectAllEfi ();\r
+\r
+ //\r
+ // Check to see if it's possible to dispatch an more DXE drivers.\r
+ // The BdsLibConnectAllEfi () may have made new DXE drivers show up.\r
+ // If anything is Dispatched Status == EFI_SUCCESS and we will try\r
+ // the connect again.\r
+ //\r
+ Status = gDS->Dispatch ();\r
+\r
+ } while (!EFI_ERROR (Status));\r
+\r
+}\r
+\r
+\r
+/**\r
+ Connect the specific Usb device which match the short form device path,\r
+ and whose bus is determined by Host Controller (Uhci or Ehci)\r
+\r
+ @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci\r
+ (0xFF)\r
+ @param RemainingDevicePath a short-form device path that starts with the first\r
+ element being a USB WWID or a USB Class device\r
+ path\r
+\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_SUCCESS\r
+ @return EFI_NOT_FOUND\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectUsbDevByShortFormDP(\r
+ IN UINT8 HostControllerPI,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleArray;\r
+ UINTN HandleArrayCount;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Class[3];\r
+ BOOLEAN AtLeastOneConnected;\r
+\r
+ //\r
+ // Check the passed in parameters\r
+ //\r
+ if (RemainingDevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||\r
+ ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)\r
+ && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)\r
+ )) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (HostControllerPI != 0xFF &&\r
+ HostControllerPI != 0x00 &&\r
+ HostControllerPI != 0x20) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Find the usb host controller firstly, then connect with the remaining device path\r
+ //\r
+ AtLeastOneConnected = FALSE;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleArrayCount,\r
+ &HandleArray\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < HandleArrayCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleArray[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **)&PciIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Check whether the Pci device is the wanted usb host controller\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((PCI_CLASS_SERIAL == Class[2]) &&\r
+ (PCI_CLASS_SERIAL_USB == Class[1])) {\r
+ if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {\r
+ Status = gBS->ConnectController (\r
+ HandleArray[Index],\r
+ NULL,\r
+ RemainingDevicePath,\r
+ FALSE\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ AtLeastOneConnected = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (AtLeastOneConnected) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BdsConsole.c
-
-Abstract:
-
- BDS Lib functions which contain all the code to connect console device
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-BOOLEAN
-IsNvNeed (
- IN CHAR16 *ConVarName
- )
-{
- CHAR16 *Ptr;
-
- Ptr = ConVarName;
-
- //
- // If the variable includes "Dev" at last, we consider
- // it does not support NV attribute.
- //
- while (*Ptr) {
- Ptr++;
- }
-
- if ((*(Ptr-3) == 'D') && (*(Ptr-2) == 'e') && (*(Ptr-1) == 'v')) {
- return FALSE;
- } else {
- return TRUE;
- }
-}
-
-
-/**
- This function update console variable based on ConVarName, it can
- add or remove one specific console device path from the variable
-
- @param ConVarName Console related variable name, ConIn, ConOut,
- ErrOut.
- @param CustomizedConDevicePath The console device path which will be added to
- the console variable ConVarName, this parameter
- can not be multi-instance.
- @param ExclusiveDevicePath The console device path which will be removed
- from the console variable ConVarName, this
- parameter can not be multi-instance.
-
- @retval EFI_UNSUPPORTED Add or remove the same device path.
- @retval EFI_SUCCESS Success add or remove the device path from the
- console variable.
-
-**/
-EFI_STATUS
-BdsLibUpdateConsoleVariable (
- IN CHAR16 *ConVarName,
- IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
- IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *VarConsole;
- UINTN DevicePathSize;
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
- UINT32 Attributes;
-
- VarConsole = NULL;
- DevicePathSize = 0;
-
- //
- // Notes: check the device path point, here should check
- // with compare memory
- //
- if (CustomizedConDevicePath == ExclusiveDevicePath) {
- return EFI_UNSUPPORTED;
- }
- //
- // Delete the ExclusiveDevicePath from current default console
- //
- VarConsole = BdsLibGetVariableAndSize (
- ConVarName,
- &gEfiGlobalVariableGuid,
- &DevicePathSize
- );
-
- //
- // Initialize NewDevicePath
- //
- NewDevicePath = VarConsole;
-
- //
- // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
- // In the end, NewDevicePath is the final device path.
- //
- if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
- NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
- }
- //
- // Try to append customized device path to NewDevicePath.
- //
- if (CustomizedConDevicePath != NULL) {
- if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
- //
- // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
- //
- NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
- //
- // In the first check, the default console variable will be _ModuleEntryPoint,
- // just append current customized device path
- //
- TempNewDevicePath = NewDevicePath;
- NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
- SafeFreePool(TempNewDevicePath);
- }
- }
-
- //
- // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.
- //
- if (IsNvNeed(ConVarName)) {
- //
- // ConVarName has NV attribute.
- //
- Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
- } else {
- //
- // ConVarName does not have NV attribute.
- //
- Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
- }
-
- //
- // Finally, Update the variable of the default console by NewDevicePath
- //
- gRT->SetVariable (
- ConVarName,
- &gEfiGlobalVariableGuid,
- Attributes,
- GetDevicePathSize (NewDevicePath),
- NewDevicePath
- );
-
- if (VarConsole == NewDevicePath) {
- SafeFreePool(VarConsole);
- } else {
- SafeFreePool(VarConsole);
- SafeFreePool(NewDevicePath);
- }
-
- return EFI_SUCCESS;
-
-}
-
-
-/**
- Connect the console device base on the variable ConVarName, if
- device path of the ConVarName is multi-instance device path, if
- anyone of the instances is connected success, then this function
- will return success.
-
- @param ConVarName Console related variable name, ConIn, ConOut,
- ErrOut.
-
- @retval EFI_NOT_FOUND There is not any console devices connected
- success
- @retval EFI_SUCCESS Success connect any one instance of the console
- device path base on the variable ConVarName.
-
-**/
-EFI_STATUS
-BdsLibConnectConsoleVariable (
- IN CHAR16 *ConVarName
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
- UINTN VariableSize;
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- EFI_DEVICE_PATH_PROTOCOL *Next;
- EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
- UINTN Size;
- BOOLEAN DeviceExist;
-
- Status = EFI_SUCCESS;
- DeviceExist = FALSE;
-
- //
- // Check if the console variable exist
- //
- StartDevicePath = BdsLibGetVariableAndSize (
- ConVarName,
- &gEfiGlobalVariableGuid,
- &VariableSize
- );
- if (StartDevicePath == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- CopyOfDevicePath = StartDevicePath;
- do {
- //
- // Check every instance of the console variable
- //
- Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
- Next = Instance;
- while (!IsDevicePathEndType (Next)) {
- Next = NextDevicePathNode (Next);
- }
-
- SetDevicePathEndNode (Next);
- //
- // Check USB1.1 console
- //
- if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
- ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)
- || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)
- )) {
- //
- // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus
- //
- Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);
- if (!EFI_ERROR (Status)) {
- DeviceExist = TRUE;
- }
-
- Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);
- if (!EFI_ERROR (Status)) {
- DeviceExist = TRUE;
- }
- } else {
- //
- // Connect the instance device path
- //
- Status = BdsLibConnectDevicePath (Instance);
- if (EFI_ERROR (Status)) {
- //
- // Delete the instance from the console varialbe
- //
- BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);
- } else {
- DeviceExist = TRUE;
- }
- }
- SafeFreePool(Instance);
- } while (CopyOfDevicePath != NULL);
-
- gBS->FreePool (StartDevicePath);
-
- if (DeviceExist == FALSE) {
- return EFI_NOT_FOUND;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- This function will search every simpletxt devive in current system,
- and make every simpletxt device as pertantial console device.
-
- None
-
- @return None
-
-**/
-VOID
-BdsLibConnectAllConsoles (
- VOID
- )
-{
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
-
- Index = 0;
- HandleCount = 0;
- HandleBuffer = NULL;
- ConDevicePath = NULL;
-
- //
- // Update all the console varables
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleTextInProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
-
- for (Index = 0; Index < HandleCount; Index++) {
- gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ConDevicePath
- );
- BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);
- }
-
- SafeFreePool(HandleBuffer);
-
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimpleTextOutProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- for (Index = 0; Index < HandleCount; Index++) {
- gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ConDevicePath
- );
- BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);
- BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);
- }
-
- SafeFreePool(HandleBuffer);
-
- //
- // Connect all console variables
- //
- BdsLibConnectAllDefaultConsoles ();
-
-}
-
-
-/**
- This function will connect console device base on the console
- device variable ConIn, ConOut and ErrOut.
-
- None
-
- @retval EFI_SUCCESS At least one of the ConIn and ConOut device have
- been connected success.
- @retval EFI_STATUS Return the status of
- BdsLibConnectConsoleVariable ().
-
-**/
-EFI_STATUS
-BdsLibConnectAllDefaultConsoles (
- VOID
- )
-{
- EFI_STATUS Status;
-
- //
- // Connect all default console variables
- //
-
- //
- // It seems impossible not to have any ConOut device on platform,
- // so we check the status here.
- //
- Status = BdsLibConnectConsoleVariable (L"ConOut");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Insert the performance probe for Console Out
- //
- PERF_START (NULL, "ConOut", "BDS", 1);
- PERF_END (NULL, "ConOut", "BDS", 0);
-
- //
- // Because possibly the platform is legacy free, in such case,
- // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,
- // so we need not check the status.
- //
- BdsLibConnectConsoleVariable (L"ConIn");
-
- //
- // The _ModuleEntryPoint err out var is legal.
- //
- BdsLibConnectConsoleVariable (L"ErrOut");
-
- return EFI_SUCCESS;
-
-}
+/** @file\r
+ BDS Lib functions which contain all the code to connect console device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+BOOLEAN\r
+IsNvNeed (\r
+ IN CHAR16 *ConVarName\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+\r
+ Ptr = ConVarName;\r
+\r
+ //\r
+ // If the variable includes "Dev" at last, we consider\r
+ // it does not support NV attribute.\r
+ //\r
+ while (*Ptr) {\r
+ Ptr++;\r
+ }\r
+\r
+ if ((*(Ptr-3) == 'D') && (*(Ptr-2) == 'e') && (*(Ptr-1) == 'v')) {\r
+ return FALSE;\r
+ } else {\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ This function update console variable based on ConVarName, it can\r
+ add or remove one specific console device path from the variable\r
+\r
+ @param ConVarName Console related variable name, ConIn, ConOut,\r
+ ErrOut.\r
+ @param CustomizedConDevicePath The console device path which will be added to\r
+ the console variable ConVarName, this parameter\r
+ can not be multi-instance.\r
+ @param ExclusiveDevicePath The console device path which will be removed\r
+ from the console variable ConVarName, this\r
+ parameter can not be multi-instance.\r
+\r
+ @retval EFI_UNSUPPORTED Add or remove the same device path.\r
+ @retval EFI_SUCCESS Success add or remove the device path from the\r
+ console variable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateConsoleVariable (\r
+ IN CHAR16 *ConVarName,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
+ UINTN DevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINT32 Attributes;\r
+\r
+ VarConsole = NULL;\r
+ DevicePathSize = 0;\r
+\r
+ //\r
+ // Notes: check the device path point, here should check\r
+ // with compare memory\r
+ //\r
+ if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Delete the ExclusiveDevicePath from current default console\r
+ //\r
+ VarConsole = BdsLibGetVariableAndSize (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &DevicePathSize\r
+ );\r
+\r
+ //\r
+ // Initialize NewDevicePath\r
+ //\r
+ NewDevicePath = VarConsole;\r
+\r
+ //\r
+ // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
+ // In the end, NewDevicePath is the final device path.\r
+ //\r
+ if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
+ NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
+ }\r
+ //\r
+ // Try to append customized device path to NewDevicePath.\r
+ //\r
+ if (CustomizedConDevicePath != NULL) {\r
+ if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
+ //\r
+ // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
+ //\r
+ NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
+ //\r
+ // In the first check, the default console variable will be _ModuleEntryPoint,\r
+ // just append current customized device path\r
+ //\r
+ TempNewDevicePath = NewDevicePath;\r
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
+ SafeFreePool(TempNewDevicePath);\r
+ }\r
+ }\r
+\r
+ //\r
+ // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
+ //\r
+ if (IsNvNeed(ConVarName)) {\r
+ //\r
+ // ConVarName has NV attribute.\r
+ //\r
+ Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+ } else {\r
+ //\r
+ // ConVarName does not have NV attribute.\r
+ //\r
+ Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
+ }\r
+\r
+ //\r
+ // Finally, Update the variable of the default console by NewDevicePath\r
+ //\r
+ gRT->SetVariable (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ Attributes,\r
+ GetDevicePathSize (NewDevicePath),\r
+ NewDevicePath\r
+ );\r
+\r
+ if (VarConsole == NewDevicePath) {\r
+ SafeFreePool(VarConsole);\r
+ } else {\r
+ SafeFreePool(VarConsole);\r
+ SafeFreePool(NewDevicePath);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Connect the console device base on the variable ConVarName, if\r
+ device path of the ConVarName is multi-instance device path, if\r
+ anyone of the instances is connected success, then this function\r
+ will return success.\r
+\r
+ @param ConVarName Console related variable name, ConIn, ConOut,\r
+ ErrOut.\r
+\r
+ @retval EFI_NOT_FOUND There is not any console devices connected\r
+ success\r
+ @retval EFI_SUCCESS Success connect any one instance of the console\r
+ device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectConsoleVariable (\r
+ IN CHAR16 *ConVarName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
+ UINTN VariableSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
+ UINTN Size;\r
+ BOOLEAN DeviceExist;\r
+\r
+ Status = EFI_SUCCESS;\r
+ DeviceExist = FALSE;\r
+\r
+ //\r
+ // Check if the console variable exist\r
+ //\r
+ StartDevicePath = BdsLibGetVariableAndSize (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &VariableSize\r
+ );\r
+ if (StartDevicePath == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CopyOfDevicePath = StartDevicePath;\r
+ do {\r
+ //\r
+ // Check every instance of the console variable\r
+ //\r
+ Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
+ Next = Instance;\r
+ while (!IsDevicePathEndType (Next)) {\r
+ Next = NextDevicePathNode (Next);\r
+ }\r
+\r
+ SetDevicePathEndNode (Next);\r
+ //\r
+ // Check USB1.1 console\r
+ //\r
+ if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
+ || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
+ )) {\r
+ //\r
+ // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus\r
+ //\r
+ Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ }\r
+\r
+ Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // Connect the instance device path\r
+ //\r
+ Status = BdsLibConnectDevicePath (Instance);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Delete the instance from the console varialbe\r
+ //\r
+ BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
+ } else {\r
+ DeviceExist = TRUE;\r
+ }\r
+ }\r
+ SafeFreePool(Instance);\r
+ } while (CopyOfDevicePath != NULL);\r
+\r
+ gBS->FreePool (StartDevicePath);\r
+\r
+ if (DeviceExist == FALSE) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will search every simpletxt devive in current system,\r
+ and make every simpletxt device as pertantial console device.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllConsoles (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+\r
+ Index = 0;\r
+ HandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ ConDevicePath = NULL;\r
+\r
+ //\r
+ // Update all the console varables\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ \r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
+ }\r
+\r
+ SafeFreePool(HandleBuffer);\r
+\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
+ }\r
+\r
+ SafeFreePool(HandleBuffer);\r
+\r
+ //\r
+ // Connect all console variables\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function will connect console device base on the console\r
+ device variable ConIn, ConOut and ErrOut.\r
+\r
+ @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
+ been connected success.\r
+ @retval EFI_STATUS Return the status of\r
+ BdsLibConnectConsoleVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllDefaultConsoles (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Connect all default console variables\r
+ //\r
+\r
+ //\r
+ // It seems impossible not to have any ConOut device on platform,\r
+ // so we check the status here.\r
+ //\r
+ Status = BdsLibConnectConsoleVariable (L"ConOut");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Insert the performance probe for Console Out\r
+ //\r
+ PERF_START (NULL, "ConOut", "BDS", 1);\r
+ PERF_END (NULL, "ConOut", "BDS", 0);\r
+\r
+ //\r
+ // Because possibly the platform is legacy free, in such case,\r
+ // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
+ // so we need not check the status.\r
+ //\r
+ BdsLibConnectConsoleVariable (L"ConIn");\r
+\r
+ //\r
+ // The _ModuleEntryPoint err out var is legal.\r
+ //\r
+ BdsLibConnectConsoleVariable (L"ErrOut");\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BdsMisc.c
-
-Abstract:
-
- Misc BDS library function
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-
-#define MAX_STRING_LEN 200
-
-static BOOLEAN mFeaturerSwitch = TRUE;
-static BOOLEAN mResetRequired = FALSE;
-
-extern UINT16 gPlatformBootTimeOutDefault;
-
-
-/**
- Return the default value for system Timeout variable.
-
- None
-
- @return Timeout value.
-
-**/
-UINT16
-BdsLibGetTimeout (
- VOID
- )
-{
- UINT16 Timeout;
- UINTN Size;
- EFI_STATUS Status;
-
- //
- // Return Timeout variable or 0xffff if no valid
- // Timeout variable exists.
- //
- Size = sizeof (UINT16);
- Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
- if (!EFI_ERROR (Status)) {
- return Timeout;
- }
- //
- // To make the current EFI Automatic-Test activity possible, just add
- // following code to make AutoBoot enabled when this variable is not
- // present.
- // This code should be removed later.
- //
- Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);
-
- //
- // Notes: Platform should set default variable if non exists on all error cases!!!
- //
- Status = gRT->SetVariable (
- L"Timeout",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- sizeof (UINT16),
- &Timeout
- );
- return Timeout;
-}
-
-
-/**
- The function will go through the driver optoin link list, load and start
- every driver the driver optoin device path point to.
-
- @param BdsDriverLists The header of the current driver option link list
-
- @return None
-
-**/
-VOID
-BdsLibLoadDrivers (
- IN LIST_ENTRY *BdsDriverLists
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- BDS_COMMON_OPTION *Option;
- EFI_HANDLE ImageHandle;
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
- UINTN ExitDataSize;
- CHAR16 *ExitData;
- BOOLEAN ReconnectAll;
-
- ReconnectAll = FALSE;
-
- //
- // Process the driver option
- //
- for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {
- Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
- //
- // If a load option is not marked as LOAD_OPTION_ACTIVE,
- // the boot manager will not automatically load the option.
- //
- if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {
- continue;
- }
- //
- // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
- // then all of the EFI drivers in the system will be disconnected and
- // reconnected after the last driver load option is processed.
- //
- if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {
- ReconnectAll = TRUE;
- }
- //
- // Make sure the driver path is connected.
- //
- BdsLibConnectDevicePath (Option->DevicePath);
-
- //
- // Load and start the image that Driver#### describes
- //
- Status = gBS->LoadImage (
- FALSE,
- mBdsImageHandle,
- Option->DevicePath,
- NULL,
- 0,
- &ImageHandle
- );
-
- if (!EFI_ERROR (Status)) {
- gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
-
- //
- // Verify whether this image is a driver, if not,
- // exit it and continue to parse next load option
- //
- if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
- gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
- continue;
- }
-
- 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);
-
- Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));
-
- //
- // Clear the Watchdog Timer after the image returns
- //
- gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
- }
- }
- //
- // Process the LOAD_OPTION_FORCE_RECONNECT driver option
- //
- if (ReconnectAll) {
- BdsLibDisconnectAllEfi ();
- BdsLibConnectAll ();
- }
-
-}
-
-
-/**
- Get the Option Number that does not used
- Try to locate the specific option variable one by one untile find a free number
-
- @param VariableName Indicate if the boot#### or driver#### option
-
- @return The Minimal Free Option Number
-
-**/
-UINT16
-BdsLibGetFreeOptionNumber (
- IN CHAR16 *VariableName
- )
-{
- UINT16 Number;
- UINTN Index;
- CHAR16 StrTemp[10];
- UINT16 *OptionBuffer;
- UINTN OptionSize;
-
- //
- // Try to find the minimum free number from 0, 1, 2, 3....
- //
- Index = 0;
- do {
- if (*VariableName == 'B') {
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
- } else {
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);
- }
- //
- // try if the option number is used
- //
- OptionBuffer = BdsLibGetVariableAndSize (
- StrTemp,
- &gEfiGlobalVariableGuid,
- &OptionSize
- );
- if (OptionBuffer == NULL) {
- break;
- }
- Index++;
- } while (1);
-
- Number = (UINT16) Index;
- return Number;
-}
-
-
-/**
- This function will register the new boot#### or driver#### option base on
- the VariableName. The new registered boot#### or driver#### will be linked
- to BdsOptionList and also update to the VariableName. After the boot#### or
- driver#### updated, the BootOrder or DriverOrder will also be updated.
-
- @param BdsOptionList The header of the boot#### or driver#### link list
- @param DevicePath The device path which the boot#### or driver####
- option present
- @param String The description of the boot#### or driver####
- @param VariableName Indicate if the boot#### or driver#### option
-
- @retval EFI_SUCCESS The boot#### or driver#### have been success
- registered
- @retval EFI_STATUS Return the status of gRT->SetVariable ().
-
-**/
-EFI_STATUS
-BdsLibRegisterNewOption (
- IN LIST_ENTRY *BdsOptionList,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CHAR16 *String,
- IN CHAR16 *VariableName
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- UINT16 RegisterOptionNumber;
- UINT16 *TempOptionPtr;
- UINTN TempOptionSize;
- UINT16 *OptionOrderPtr;
- VOID *OptionPtr;
- UINTN OptionSize;
- UINT8 *TempPtr;
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
- CHAR16 *Description;
- CHAR16 OptionName[10];
- BOOLEAN UpdateDescription;
- UINT16 BootOrderEntry;
- UINTN OrderItemNum;
-
-
- OptionPtr = NULL;
- OptionSize = 0;
- TempPtr = NULL;
- OptionDevicePath = NULL;
- Description = NULL;
- OptionOrderPtr = NULL;
- UpdateDescription = FALSE;
- ZeroMem (OptionName, sizeof (OptionName));
-
- TempOptionSize = 0;
- TempOptionPtr = BdsLibGetVariableAndSize (
- VariableName,
- &gEfiGlobalVariableGuid,
- &TempOptionSize
- );
-
- //
- // Compare with current option variable
- //
- for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {
-
- if (*VariableName == 'B') {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);
- } else {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);
- }
-
- OptionPtr = BdsLibGetVariableAndSize (
- OptionName,
- &gEfiGlobalVariableGuid,
- &OptionSize
- );
- if (OptionPtr == NULL) {
- continue;
- }
- TempPtr = OptionPtr;
- TempPtr += sizeof (UINT32) + sizeof (UINT16);
- Description = (CHAR16 *) TempPtr;
- TempPtr += StrSize ((CHAR16 *) TempPtr);
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
-
- //
- // Notes: the description may will change base on the GetStringToken
- //
- if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {
- if (CompareMem (Description, String, StrSize (Description)) == 0) {
- //
- // Got the option, so just return
- //
- gBS->FreePool (OptionPtr);
- gBS->FreePool (TempOptionPtr);
- return EFI_SUCCESS;
- } else {
- //
- // Option description changed, need update.
- //
- UpdateDescription = TRUE;
- gBS->FreePool (OptionPtr);
- break;
- }
- }
-
- gBS->FreePool (OptionPtr);
- }
-
- OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);
- OptionSize += GetDevicePathSize (DevicePath);
- OptionPtr = AllocateZeroPool (OptionSize);
- TempPtr = OptionPtr;
- *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;
- TempPtr += sizeof (UINT32);
- *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);
- TempPtr += sizeof (UINT16);
- CopyMem (TempPtr, String, StrSize (String));
- TempPtr += StrSize (String);
- CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));
-
- if (UpdateDescription) {
- //
- // The number in option#### to be updated
- //
- RegisterOptionNumber = TempOptionPtr[Index];
- } else {
- //
- // The new option#### number
- //
- RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);
- }
-
- if (*VariableName == 'B') {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);
- } else {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);
- }
-
- Status = gRT->SetVariable (
- OptionName,
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- OptionSize,
- OptionPtr
- );
- //
- // Return if only need to update a changed description or fail to set option.
- //
- if (EFI_ERROR (Status) || UpdateDescription) {
- gBS->FreePool (OptionPtr);
- gBS->FreePool (TempOptionPtr);
- return Status;
- }
-
- gBS->FreePool (OptionPtr);
-
- //
- // Update the option order variable
- //
-
- //
- // If no option order
- //
- if (TempOptionSize == 0) {
- BootOrderEntry = 0;
- Status = gRT->SetVariable (
- VariableName,
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- sizeof (UINT16),
- &BootOrderEntry
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePool (TempOptionPtr);
- return Status;
- }
- return EFI_SUCCESS;
- }
-
- //
- // Append the new option number to the original option order
- //
- OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;
- OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));
- CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));
-
- OptionOrderPtr[Index] = RegisterOptionNumber;
-
- Status = gRT->SetVariable (
- VariableName,
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- OrderItemNum * sizeof (UINT16),
- OptionOrderPtr
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePool (TempOptionPtr);
- gBS->FreePool (OptionOrderPtr);
- return Status;
- }
-
- gBS->FreePool (TempOptionPtr);
- gBS->FreePool (OptionOrderPtr);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Build the boot#### or driver#### option from the VariableName, the
- build boot#### or driver#### will also be linked to BdsCommonOptionList
-
- @param BdsCommonOptionList The header of the boot#### or driver#### option
- link list
- @param VariableName EFI Variable name indicate if it is boot#### or
- driver####
-
- @retval BDS_COMMON_OPTION Get the option just been created
- @retval NULL Failed to get the new option
-
-**/
-BDS_COMMON_OPTION *
-BdsLibVariableToOption (
- IN OUT LIST_ENTRY *BdsCommonOptionList,
- IN CHAR16 *VariableName
- )
-{
- UINT32 Attribute;
- UINT16 FilePathSize;
- UINT8 *Variable;
- UINT8 *TempPtr;
- UINTN VariableSize;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- BDS_COMMON_OPTION *Option;
- VOID *LoadOptions;
- UINT32 LoadOptionsSize;
- CHAR16 *Description;
- UINT8 NumOff;
- //
- // Read the variable. We will never free this data.
- //
- Variable = BdsLibGetVariableAndSize (
- VariableName,
- &gEfiGlobalVariableGuid,
- &VariableSize
- );
- if (Variable == NULL) {
- return NULL;
- }
- //
- // Notes: careful defined the variable of Boot#### or
- // Driver####, consider use some macro to abstract the code
- //
- //
- // Get the option attribute
- //
- TempPtr = Variable;
- Attribute = *(UINT32 *) Variable;
- TempPtr += sizeof (UINT32);
-
- //
- // Get the option's device path size
- //
- FilePathSize = *(UINT16 *) TempPtr;
- TempPtr += sizeof (UINT16);
-
- //
- // Get the option's description string
- //
- Description = (CHAR16 *) TempPtr;
-
- //
- // Get the option's description string size
- //
- TempPtr += StrSize ((CHAR16 *) TempPtr);
-
- //
- // Get the option's device path
- //
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
- TempPtr += FilePathSize;
-
- LoadOptions = TempPtr;
- LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
-
- //
- // The Console variables may have multiple device paths, so make
- // an Entry for each one.
- //
- Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));
- if (Option == NULL) {
- return NULL;
- }
-
- Option->Signature = BDS_LOAD_OPTION_SIGNATURE;
- Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));
- CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));
- Option->Attribute = Attribute;
- Option->Description = AllocateZeroPool (StrSize (Description));
- CopyMem (Option->Description, Description, StrSize (Description));
- Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);
- CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);
- Option->LoadOptionsSize = LoadOptionsSize;
-
- //
- // Get the value from VariableName Unicode string
- // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
- // Unicode stream to ASCII without any loss in meaning.
- //
- if (*VariableName == 'B') {
- NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;
- Option->BootCurrent = (UINT16) ((VariableName[NumOff] -'0') * 0x1000);
- Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));
- Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+2]-'0') * 0x10));
- Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));
- }
- //
- // Insert active entry to BdsDeviceList
- //
- if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {
- InsertTailList (BdsCommonOptionList, &Option->Link);
- gBS->FreePool (Variable);
- return Option;
- }
-
- gBS->FreePool (Variable);
- gBS->FreePool (Option);
- return NULL;
-
-}
-
-
-/**
- Process BootOrder, or DriverOrder variables, by calling
- BdsLibVariableToOption () for each UINT16 in the variables.
-
- @param BdsCommonOptionList The header of the option list base on variable
- VariableName
- @param VariableName EFI Variable name indicate the BootOrder or
- DriverOrder
-
- @retval EFI_SUCCESS Success create the boot option or driver option
- list
- @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or driver option list
-
-**/
-EFI_STATUS
-BdsLibBuildOptionFromVar (
- IN LIST_ENTRY *BdsCommonOptionList,
- IN CHAR16 *VariableName
- )
-{
- UINT16 *OptionOrder;
- UINTN OptionOrderSize;
- UINTN Index;
- BDS_COMMON_OPTION *Option;
- CHAR16 OptionName[20];
-
- //
- // Zero Buffer in order to get all BOOT#### variables
- //
- ZeroMem (OptionName, sizeof (OptionName));
-
- //
- // Read the BootOrder, or DriverOrder variable.
- //
- OptionOrder = BdsLibGetVariableAndSize (
- VariableName,
- &gEfiGlobalVariableGuid,
- &OptionOrderSize
- );
- if (OptionOrder == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
- if (*VariableName == 'B') {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);
- } else {
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);
- }
-
- Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);
- Option->BootCurrent = OptionOrder[Index];
-
- }
-
- gBS->FreePool (OptionOrder);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Get boot mode by looking up configuration table and parsing HOB list
-
- @param BootMode Boot mode from PEI handoff HOB.
-
- @retval EFI_SUCCESS Successfully get boot mode
- @retval EFI_NOT_FOUND Can not find the current system boot mode
-
-**/
-EFI_STATUS
-BdsLibGetBootMode (
- OUT EFI_BOOT_MODE *BootMode
- )
-{
- VOID *HobList;
- EFI_STATUS Status;
-
- //
- // Get Hob list
- //
- Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Hob list not found\n"));
- *BootMode = 0;
- return EFI_NOT_FOUND;
- }
-
- Status = R8_GetHobBootMode (HobList, BootMode);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
- buffer, and the size of the buffer. If failure return NULL.
-
- @param Name String part of EFI variable name
- @param VendorGuid GUID part of EFI variable name
- @param VariableSize Returns the size of the EFI variable that was read
-
- @return Dynamically allocated memory that contains a copy of the EFI variable.
- @return Caller is responsible freeing the buffer.
- @retval NULL Variable was not read
-
-**/
-VOID *
-BdsLibGetVariableAndSize (
- IN CHAR16 *Name,
- IN EFI_GUID *VendorGuid,
- OUT UINTN *VariableSize
- )
-{
- EFI_STATUS Status;
- UINTN BufferSize;
- VOID *Buffer;
-
- Buffer = NULL;
-
- //
- // Pass in a zero size buffer to find the required buffer size.
- //
- BufferSize = 0;
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- //
- // Allocate the buffer to return
- //
- Buffer = AllocateZeroPool (BufferSize);
- if (Buffer == NULL) {
- return NULL;
- }
- //
- // Read variable into the allocated buffer.
- //
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
- if (EFI_ERROR (Status)) {
- BufferSize = 0;
- }
- }
-
- *VariableSize = BufferSize;
- return Buffer;
-}
-
-
-/**
- Delete the instance in Multi which matches partly with Single instance
-
- @param Multi A pointer to a multi-instance device path data
- structure.
- @param Single A pointer to a single-instance device path data
- structure.
-
- @return This function will remove the device path instances in Multi which partly
- @return match with the Single, and return the result device path. If there is no
- @return remaining device path as a result, this function will return NULL.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BdsLibDelPartMatchInstance (
- IN EFI_DEVICE_PATH_PROTOCOL *Multi,
- IN EFI_DEVICE_PATH_PROTOCOL *Single
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *Instance;
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
- UINTN InstanceSize;
- UINTN SingleDpSize;
- UINTN Size;
-
- NewDevicePath = NULL;
- TempNewDevicePath = NULL;
-
- if (Multi == NULL || Single == NULL) {
- return Multi;
- }
-
- Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
- SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
- InstanceSize -= END_DEVICE_PATH_LENGTH;
-
- while (Instance != NULL) {
-
- Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;
-
- if ((CompareMem (Instance, Single, Size) != 0)) {
- //
- // Append the device path instance which does not match with Single
- //
- TempNewDevicePath = NewDevicePath;
- NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
- SafeFreePool(TempNewDevicePath);
- }
- SafeFreePool(Instance);
- Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
- InstanceSize -= END_DEVICE_PATH_LENGTH;
- }
-
- return NewDevicePath;
-}
-
-
-/**
- Function compares a device path data structure to that of all the nodes of a
- second device path instance.
-
- @param Multi A pointer to a multi-instance device path data
- structure.
- @param Single A pointer to a single-instance device path data
- structure.
-
- @retval TRUE If the Single is contained within Multi
- @retval FALSE The Single is not match within Multi
-
-**/
-BOOLEAN
-BdsLibMatchDevicePaths (
- IN EFI_DEVICE_PATH_PROTOCOL *Multi,
- IN EFI_DEVICE_PATH_PROTOCOL *Single
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
- UINTN Size;
-
- if (!Multi || !Single) {
- return FALSE;
- }
-
- DevicePath = Multi;
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
-
- //
- // Search for the match of 'Single' in 'Multi'
- //
- while (DevicePathInst != NULL) {
- //
- // If the single device path is found in multiple device paths,
- // return success
- //
- if (CompareMem (Single, DevicePathInst, Size) == 0) {
- gBS->FreePool (DevicePathInst);
- return TRUE;
- }
-
- gBS->FreePool (DevicePathInst);
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
- }
-
- return FALSE;
-}
-
-
-/**
- This function prints a series of strings.
-
- @param ConOut Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
- @param ... A variable argument list containing series of
- strings, the last string must be NULL.
-
- @retval EFI_SUCCESS Success print out the string using ConOut.
- @retval EFI_STATUS Return the status of the ConOut->OutputString ().
-
-**/
-EFI_STATUS
-BdsLibOutputStrings (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,
- ...
- )
-{
- VA_LIST args;
- EFI_STATUS Status;
- CHAR16 *String;
-
- Status = EFI_SUCCESS;
- VA_START (args, ConOut);
-
- while (!EFI_ERROR (Status)) {
- //
- // If String is NULL, then it's the end of the list
- //
- String = VA_ARG (args, CHAR16 *);
- if (!String) {
- break;
- }
-
- Status = ConOut->OutputString (ConOut, String);
-
- if (EFI_ERROR (Status)) {
- break;
- }
- }
-
- return Status;
-}
-
-//
-// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.
-// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if
-// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.
-//
-
-
-/**
- Enable the setup browser reset reminder feature.
- This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.
-
- VOID
-
- @return VOID
-
-**/
-VOID
-EnableResetReminderFeature (
- VOID
- )
-{
- mFeaturerSwitch = TRUE;
-}
-
-
-/**
- Disable the setup browser reset reminder feature.
- This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.
-
- VOID
-
- @return VOID
-
-**/
-VOID
-DisableResetReminderFeature (
- VOID
- )
-{
- mFeaturerSwitch = FALSE;
-}
-
-
-/**
- Record the info that a reset is required.
- A module boolean variable is used to record whether a reset is required.
-
- VOID
-
- @return VOID
-
-**/
-VOID
-EnableResetRequired (
- VOID
- )
-{
- mResetRequired = TRUE;
-}
-
-
-/**
- Record the info that no reset is required.
- A module boolean variable is used to record whether a reset is required.
-
- VOID
-
- @return VOID
-
-**/
-VOID
-DisableResetRequired (
- VOID
- )
-{
- mResetRequired = FALSE;
-}
-
-
-/**
- Check whether platform policy enable the reset reminder feature. The default is enabled.
-
- VOID
-
- @return VOID
-
-**/
-BOOLEAN
-IsResetReminderFeatureEnable (
- VOID
- )
-{
- return mFeaturerSwitch;
-}
-
-
-/**
- Check if user changed any option setting which needs a system reset to be effective.
-
- VOID
-
- @return VOID
-
-**/
-BOOLEAN
-IsResetRequired (
- VOID
- )
-{
- return mResetRequired;
-}
-
-
-/**
- Check whether a reset is needed, and finish the reset reminder feature.
- If a reset is needed, Popup a menu to notice user, and finish the feature
- according to the user selection.
-
- VOID
-
- @return VOID
-
-**/
-VOID
-SetupResetReminder (
- VOID
- )
-{
- EFI_INPUT_KEY Key;
- CHAR16 *StringBuffer1;
- CHAR16 *StringBuffer2;
-
-
- //
- //check any reset required change is applied? if yes, reset system
- //
- if (IsResetReminderFeatureEnable ()) {
- if (IsResetRequired ()) {
-
- StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
- ASSERT (StringBuffer1 != NULL);
- StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
- ASSERT (StringBuffer2 != NULL);
- StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");
- StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)");
- //
- // Popup a menu to notice user
- //
- do {
- IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);
- } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
-
- gBS->FreePool (StringBuffer1);
- gBS->FreePool (StringBuffer2);
- //
- // If the user hits the YES Response key, reset
- //
- if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
- gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
- }
- gST->ConOut->ClearScreen (gST->ConOut);
- }
- }
-}
-
-
-/**
- Get the headers (dos, image, optional header) from an image
-
- @param Device SimpleFileSystem device handle
- @param FileName File name for the image
- @param DosHeader Pointer to dos header
- @param ImageHeader Pointer to image header
- @param OptionalHeader Pointer to optional header
-
- @retval EFI_SUCCESS Successfully get the machine type.
- @retval EFI_NOT_FOUND The file is not found.
- @retval EFI_LOAD_ERROR File is not a valid image file.
-
-**/
-EFI_STATUS
-BdsLibGetImageHeader (
- IN EFI_HANDLE Device,
- IN CHAR16 *FileName,
- OUT EFI_IMAGE_DOS_HEADER *DosHeader,
- OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
- )
-{
- EFI_STATUS Status;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
- EFI_FILE_HANDLE Root;
- EFI_FILE_HANDLE ThisFile;
- UINTN BufferSize;
- UINT64 FileSize;
- EFI_FILE_INFO *Info;
-
- Root = NULL;
- ThisFile = NULL;
- //
- // Handle the file system interface to the device
- //
- Status = gBS->HandleProtocol (
- Device,
- &gEfiSimpleFileSystemProtocolGuid,
- (VOID *) &Volume
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = Volume->OpenVolume (
- Volume,
- &Root
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Get file size
- //
- BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
- do {
- Info = NULL;
- Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Status = ThisFile->GetInfo (
- ThisFile,
- &gEfiFileInfoGuid,
- &BufferSize,
- Info
- );
- if (!EFI_ERROR (Status)) {
- break;
- }
- if (Status != EFI_BUFFER_TOO_SMALL) {
- goto Done;
- }
- gBS->FreePool (Info);
- } while (TRUE);
-
- FileSize = Info->FileSize;
- gBS->FreePool (Info);
-
- //
- // Read dos header
- //
- BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
- Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
- if (EFI_ERROR (Status) ||
- BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
- FileSize <= DosHeader->e_lfanew ||
- DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
- Status = EFI_LOAD_ERROR;
- goto Done;
- }
-
- //
- // Move to PE signature
- //
- Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
- if (EFI_ERROR (Status)) {
- Status = EFI_LOAD_ERROR;
- goto Done;
- }
-
- //
- // Read and check PE signature
- //
- BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
- Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
- if (EFI_ERROR (Status) ||
- BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
- Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
- Status = EFI_LOAD_ERROR;
- goto Done;
- }
-
- //
- // Check PE32 or PE32+ magic
- //
- if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
- Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- Status = EFI_LOAD_ERROR;
- goto Done;
- }
-
- Done:
- if (ThisFile != NULL) {
- ThisFile->Close (ThisFile);
- }
- if (Root != NULL) {
- Root->Close (Root);
- }
- return Status;
-}
-
-VOID
-EFIAPI
-BdsSetMemoryTypeInformationVariable (
- EFI_EVENT Event,
- VOID *Context
- )
-/*++
-
-Routine Description:
-
- This routine is a notification function for legayc boot or exit boot
- service event. It will adjust the memory information for different
- memory type and save them into the variables for next boot
-
-Arguments:
-
- Event - The event that triggered this notification function
- Context - Pointer to the notification functions context
-
-Returns:
-
- None.
-
---*/
-{
- EFI_STATUS Status;
- EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;
- EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
- UINTN VariableSize;
- BOOLEAN UpdateRequired;
- UINTN Index;
- UINTN Index1;
- UINT32 Previous;
- UINT32 Current;
- UINT32 Next;
- VOID *HobList;
-
- UpdateRequired = FALSE;
-
- //
- // Retrieve the current memory usage statistics. If they are not found, then
- // no adjustments can be made to the Memory Type Information variable.
- //
- Status = EfiGetSystemConfigurationTable (
- &gEfiMemoryTypeInformationGuid,
- (VOID **) &CurrentMemoryTypeInformation
- );
- if (EFI_ERROR (Status)) {
- return;
- }
-
- //
- // Get the Memory Type Information settings from Hob if they exist,
- // PEI is responsible for getting them from variable and build a Hob to save them.
- // If the previous Memory Type Information is not available, then set defaults
- //
- EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
- Status = R8_GetNextGuidHob (&HobList, &gEfiMemoryTypeInformationGuid, (VOID **) &PreviousMemoryTypeInformation, &VariableSize);
- if (EFI_ERROR (Status) || PreviousMemoryTypeInformation == NULL) {
- //
- // If Platform has not built Memory Type Info into the Hob, just return.
- //
- return;
- }
-
- //
- // Use a heuristic to adjust the Memory Type Information for the next boot
- //
- for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
-
- Current = 0;
- for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
- if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
- Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
- break;
- }
- }
-
- if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
- continue;
- }
-
- Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
-
- //
- // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail
- //
- if (Current > Previous) {
- Next = Current + (Current >> 2);
- } else {
- Next = Previous;
- }
- if (Next > 0 && Next < 4) {
- Next = 4;
- }
-
- if (Next != Previous) {
- PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
- UpdateRequired = TRUE;
- }
-
- }
-
- //
- // If any changes were made to the Memory Type Information settings, then set the new variable value
- //
- if (UpdateRequired) {
- Status = gRT->SetVariable (
- EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
- &gEfiMemoryTypeInformationGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- VariableSize,
- PreviousMemoryTypeInformation
- );
- }
-
- return;
-}
-
-
-/**
- This routine register a function to adjust the different type memory page number just before booting
- and save the updated info into the variable for next boot to use
-
- None
-
- @return None.
-
-**/
-VOID
-EFIAPI
-BdsLibSaveMemoryTypeInformation (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_EVENT ReadyToBootEvent;
-
- Status = EfiCreateEventReadyToBootEx (
- TPL_CALLBACK,
- BdsSetMemoryTypeInformationVariable,
- NULL,
- &ReadyToBootEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));
- }
-
-}
-
-
-/**
- return the current TPL, copied from the EDKII glue lib.
-
- VOID
-
- @return Current TPL
-
-**/
-EFI_TPL
-BdsLibGetCurrentTpl (
- VOID
- )
-{
- EFI_TPL Tpl;
-
- Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- gBS->RestoreTPL (Tpl);
-
- return Tpl;
-}
+/** @file\r
+ Misc BDS library function\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+#define MAX_STRING_LEN 200\r
+\r
+static BOOLEAN mFeaturerSwitch = TRUE;\r
+static BOOLEAN mResetRequired = FALSE;\r
+\r
+extern UINT16 gPlatformBootTimeOutDefault;\r
+\r
+\r
+/**\r
+ Return the default value for system Timeout variable.\r
+\r
+ @return Timeout value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+BdsLibGetTimeout (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 Timeout;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Return Timeout variable or 0xffff if no valid\r
+ // Timeout variable exists.\r
+ //\r
+ Size = sizeof (UINT16);\r
+ Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Timeout;\r
+ }\r
+ //\r
+ // To make the current EFI Automatic-Test activity possible, just add\r
+ // following code to make AutoBoot enabled when this variable is not\r
+ // present.\r
+ // This code should be removed later.\r
+ //\r
+ Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);\r
+\r
+ //\r
+ // Notes: Platform should set default variable if non exists on all error cases!!!\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"Timeout",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT16),\r
+ &Timeout\r
+ );\r
+ return Timeout;\r
+}\r
+\r
+\r
+/**\r
+ The function will go through the driver optoin link list, load and start\r
+ every driver the driver optoin device path point to.\r
+\r
+ @param BdsDriverLists The header of the current driver option link list\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibLoadDrivers (\r
+ IN LIST_ENTRY *BdsDriverLists\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_COMMON_OPTION *Option;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ BOOLEAN ReconnectAll;\r
+\r
+ ReconnectAll = FALSE;\r
+\r
+ //\r
+ // Process the driver option\r
+ //\r
+ for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+ //\r
+ // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
+ // the boot manager will not automatically load the option.\r
+ //\r
+ if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
+ continue;\r
+ }\r
+ //\r
+ // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
+ // then all of the EFI drivers in the system will be disconnected and\r
+ // reconnected after the last driver load option is processed.\r
+ //\r
+ if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
+ ReconnectAll = TRUE;\r
+ }\r
+ //\r
+ // Make sure the driver path is connected.\r
+ //\r
+ BdsLibConnectDevicePath (Option->DevicePath);\r
+\r
+ //\r
+ // Load and start the image that Driver#### describes\r
+ //\r
+ Status = gBS->LoadImage (\r
+ FALSE,\r
+ mBdsImageHandle,\r
+ Option->DevicePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+\r
+ //\r
+ // Verify whether this image is a driver, if not,\r
+ // exit it and continue to parse next load option\r
+ //\r
+ if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
+ gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
+ continue;\r
+ }\r
+\r
+ if (Option->LoadOptionsSize != 0) {\r
+ ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
+ ImageInfo->LoadOptions = Option->LoadOptions;\r
+ }\r
+ //\r
+ // Before calling the image, enable the Watchdog Timer for\r
+ // the 5 Minute period\r
+ //\r
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+ Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));\r
+\r
+ //\r
+ // Clear the Watchdog Timer after the image returns\r
+ //\r
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+ }\r
+ }\r
+ //\r
+ // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
+ //\r
+ if (ReconnectAll) {\r
+ BdsLibDisconnectAllEfi ();\r
+ BdsLibConnectAll ();\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ Get the Option Number that does not used\r
+ Try to locate the specific option variable one by one untile find a free number\r
+\r
+ @param VariableName Indicate if the boot#### or driver#### option\r
+\r
+ @return The Minimal Free Option Number\r
+\r
+**/\r
+UINT16\r
+BdsLibGetFreeOptionNumber (\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINT16 Number;\r
+ UINTN Index;\r
+ CHAR16 StrTemp[10];\r
+ UINT16 *OptionBuffer;\r
+ UINTN OptionSize;\r
+\r
+ //\r
+ // Try to find the minimum free number from 0, 1, 2, 3....\r
+ //\r
+ Index = 0;\r
+ do {\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);\r
+ } else {\r
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);\r
+ }\r
+ //\r
+ // try if the option number is used\r
+ //\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (OptionBuffer == NULL) {\r
+ break;\r
+ }\r
+ Index++;\r
+ } while (1);\r
+\r
+ Number = (UINT16) Index;\r
+ return Number;\r
+}\r
+\r
+\r
+/**\r
+ This function will register the new boot#### or driver#### option base on\r
+ the VariableName. The new registered boot#### or driver#### will be linked\r
+ to BdsOptionList and also update to the VariableName. After the boot#### or\r
+ driver#### updated, the BootOrder or DriverOrder will also be updated.\r
+\r
+ @param BdsOptionList The header of the boot#### or driver#### link list\r
+ @param DevicePath The device path which the boot#### or driver####\r
+ option present\r
+ @param String The description of the boot#### or driver####\r
+ @param VariableName Indicate if the boot#### or driver#### option\r
+\r
+ @retval EFI_SUCCESS The boot#### or driver#### have been success\r
+ registered\r
+ @retval EFI_STATUS Return the status of gRT->SetVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibRegisterNewOption (\r
+ IN LIST_ENTRY *BdsOptionList,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN CHAR16 *String,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINT16 RegisterOptionNumber;\r
+ UINT16 *TempOptionPtr;\r
+ UINTN TempOptionSize;\r
+ UINT16 *OptionOrderPtr;\r
+ VOID *OptionPtr;\r
+ UINTN OptionSize;\r
+ UINT8 *TempPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ CHAR16 *Description;\r
+ CHAR16 OptionName[10];\r
+ BOOLEAN UpdateDescription;\r
+ UINT16 BootOrderEntry;\r
+ UINTN OrderItemNum;\r
+\r
+\r
+ OptionPtr = NULL;\r
+ OptionSize = 0;\r
+ TempPtr = NULL;\r
+ OptionDevicePath = NULL;\r
+ Description = NULL;\r
+ OptionOrderPtr = NULL;\r
+ UpdateDescription = FALSE;\r
+ ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+ TempOptionSize = 0;\r
+ TempOptionPtr = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &TempOptionSize\r
+ );\r
+\r
+ //\r
+ // Compare with current option variable\r
+ //\r
+ for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
+\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
+ }\r
+\r
+ OptionPtr = BdsLibGetVariableAndSize (\r
+ OptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (OptionPtr == NULL) {\r
+ continue;\r
+ }\r
+ TempPtr = OptionPtr;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ Description = (CHAR16 *) TempPtr;\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+ //\r
+ // Notes: the description may will change base on the GetStringToken\r
+ //\r
+ if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
+ if (CompareMem (Description, String, StrSize (Description)) == 0) { \r
+ //\r
+ // Got the option, so just return\r
+ //\r
+ gBS->FreePool (OptionPtr);\r
+ gBS->FreePool (TempOptionPtr);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Option description changed, need update.\r
+ //\r
+ UpdateDescription = TRUE;\r
+ gBS->FreePool (OptionPtr);\r
+ break;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OptionPtr);\r
+ }\r
+\r
+ OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);\r
+ OptionSize += GetDevicePathSize (DevicePath);\r
+ OptionPtr = AllocateZeroPool (OptionSize);\r
+ TempPtr = OptionPtr;\r
+ *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
+ TempPtr += sizeof (UINT32);\r
+ *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
+ TempPtr += sizeof (UINT16);\r
+ CopyMem (TempPtr, String, StrSize (String));\r
+ TempPtr += StrSize (String);\r
+ CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
+\r
+ if (UpdateDescription) {\r
+ //\r
+ // The number in option#### to be updated\r
+ //\r
+ RegisterOptionNumber = TempOptionPtr[Index];\r
+ } else {\r
+ //\r
+ // The new option#### number\r
+ //\r
+ RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);\r
+ }\r
+\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ OptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ OptionSize,\r
+ OptionPtr\r
+ );\r
+ //\r
+ // Return if only need to update a changed description or fail to set option.\r
+ //\r
+ if (EFI_ERROR (Status) || UpdateDescription) {\r
+ gBS->FreePool (OptionPtr);\r
+ gBS->FreePool (TempOptionPtr);\r
+ return Status;\r
+ }\r
+\r
+ gBS->FreePool (OptionPtr);\r
+\r
+ //\r
+ // Update the option order variable\r
+ //\r
+\r
+ //\r
+ // If no option order\r
+ //\r
+ if (TempOptionSize == 0) {\r
+ BootOrderEntry = 0;\r
+ Status = gRT->SetVariable (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT16),\r
+ &BootOrderEntry\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (TempOptionPtr);\r
+ return Status;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Append the new option number to the original option order\r
+ //\r
+ OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;\r
+ OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));\r
+ CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));\r
+\r
+ OptionOrderPtr[Index] = RegisterOptionNumber;\r
+\r
+ Status = gRT->SetVariable (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ OrderItemNum * sizeof (UINT16),\r
+ OptionOrderPtr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (TempOptionPtr);\r
+ gBS->FreePool (OptionOrderPtr);\r
+ return Status;\r
+ }\r
+\r
+ gBS->FreePool (TempOptionPtr);\r
+ gBS->FreePool (OptionOrderPtr);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Build the boot#### or driver#### option from the VariableName, the\r
+ build boot#### or driver#### will also be linked to BdsCommonOptionList\r
+\r
+ @param BdsCommonOptionList The header of the boot#### or driver#### option\r
+ link list\r
+ @param VariableName EFI Variable name indicate if it is boot#### or\r
+ driver####\r
+\r
+ @retval BDS_COMMON_OPTION Get the option just been created\r
+ @retval NULL Failed to get the new option\r
+\r
+**/\r
+BDS_COMMON_OPTION *\r
+EFIAPI\r
+BdsLibVariableToOption (\r
+ IN OUT LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+ UINT16 FilePathSize;\r
+ UINT8 *Variable;\r
+ UINT8 *TempPtr;\r
+ UINTN VariableSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BDS_COMMON_OPTION *Option;\r
+ VOID *LoadOptions;\r
+ UINT32 LoadOptionsSize;\r
+ CHAR16 *Description;\r
+ UINT8 NumOff;\r
+ //\r
+ // Read the variable. We will never free this data.\r
+ //\r
+ Variable = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &VariableSize\r
+ );\r
+ if (Variable == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // Notes: careful defined the variable of Boot#### or\r
+ // Driver####, consider use some macro to abstract the code\r
+ //\r
+ //\r
+ // Get the option attribute\r
+ //\r
+ TempPtr = Variable;\r
+ Attribute = *(UINT32 *) Variable;\r
+ TempPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // Get the option's device path size\r
+ //\r
+ FilePathSize = *(UINT16 *) TempPtr;\r
+ TempPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Get the option's description string\r
+ //\r
+ Description = (CHAR16 *) TempPtr;\r
+\r
+ //\r
+ // Get the option's description string size\r
+ //\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+\r
+ //\r
+ // Get the option's device path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+ TempPtr += FilePathSize;\r
+\r
+ LoadOptions = TempPtr;\r
+ LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));\r
+\r
+ //\r
+ // The Console variables may have multiple device paths, so make\r
+ // an Entry for each one.\r
+ //\r
+ Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
+ if (Option == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Option->Signature = BDS_LOAD_OPTION_SIGNATURE;\r
+ Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+ CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+ Option->Attribute = Attribute;\r
+ Option->Description = AllocateZeroPool (StrSize (Description));\r
+ CopyMem (Option->Description, Description, StrSize (Description));\r
+ Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
+ CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
+ Option->LoadOptionsSize = LoadOptionsSize;\r
+\r
+ //\r
+ // Get the value from VariableName Unicode string\r
+ // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this\r
+ // Unicode stream to ASCII without any loss in meaning.\r
+ //\r
+ if (*VariableName == 'B') {\r
+ NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;\r
+ Option->BootCurrent = (UINT16) ((VariableName[NumOff] -'0') * 0x1000);\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+2]-'0') * 0x10));\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));\r
+ }\r
+ //\r
+ // Insert active entry to BdsDeviceList\r
+ //\r
+ if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
+ InsertTailList (BdsCommonOptionList, &Option->Link);\r
+ gBS->FreePool (Variable);\r
+ return Option;\r
+ }\r
+\r
+ gBS->FreePool (Variable);\r
+ gBS->FreePool (Option);\r
+ return NULL;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Process BootOrder, or DriverOrder variables, by calling\r
+ BdsLibVariableToOption () for each UINT16 in the variables.\r
+\r
+ @param BdsCommonOptionList The header of the option list base on variable\r
+ VariableName\r
+ @param VariableName EFI Variable name indicate the BootOrder or\r
+ DriverOrder\r
+\r
+ @retval EFI_SUCCESS Success create the boot option or driver option\r
+ list\r
+ @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or driver option list\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBuildOptionFromVar (\r
+ IN LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINT16 *OptionOrder;\r
+ UINTN OptionOrderSize;\r
+ UINTN Index;\r
+ BDS_COMMON_OPTION *Option;\r
+ CHAR16 OptionName[20];\r
+\r
+ //\r
+ // Zero Buffer in order to get all BOOT#### variables\r
+ //\r
+ ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+ //\r
+ // Read the BootOrder, or DriverOrder variable.\r
+ //\r
+ OptionOrder = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionOrderSize\r
+ );\r
+ if (OptionOrder == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
+ }\r
+\r
+ Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
+ Option->BootCurrent = OptionOrder[Index];\r
+\r
+ }\r
+\r
+ gBS->FreePool (OptionOrder);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Get boot mode by looking up configuration table and parsing HOB list\r
+\r
+ @param BootMode Boot mode from PEI handoff HOB.\r
+\r
+ @retval EFI_SUCCESS Successfully get boot mode\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetBootMode (\r
+ OUT EFI_BOOT_MODE *BootMode\r
+ )\r
+{\r
+ *BootMode = GetBootModeHob ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
+ buffer, and the size of the buffer. If failure return NULL.\r
+\r
+ @param Name String part of EFI variable name\r
+ @param VendorGuid GUID part of EFI variable name\r
+ @param VariableSize Returns the size of the EFI variable that was read\r
+\r
+ @return Dynamically allocated memory that contains a copy of the EFI variable.\r
+ @return Caller is responsible freeing the buffer.\r
+ @retval NULL Variable was not read\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+BdsLibGetVariableAndSize (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VariableSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ VOID *Buffer;\r
+\r
+ Buffer = NULL;\r
+\r
+ //\r
+ // Pass in a zero size buffer to find the required buffer size.\r
+ //\r
+ BufferSize = 0;\r
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // Allocate the buffer to return\r
+ //\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // Read variable into the allocated buffer.\r
+ //\r
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ BufferSize = 0;\r
+ }\r
+ }\r
+\r
+ *VariableSize = BufferSize;\r
+ return Buffer;\r
+}\r
+\r
+\r
+/**\r
+ Delete the instance in Multi which matches partly with Single instance\r
+\r
+ @param Multi A pointer to a multi-instance device path data\r
+ structure.\r
+ @param Single A pointer to a single-instance device path data\r
+ structure.\r
+\r
+ @return This function will remove the device path instances in Multi which partly\r
+ match with the Single, and return the result device path. If there is no\r
+ remaining device path as a result, this function will return NULL.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsLibDelPartMatchInstance (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINTN InstanceSize;\r
+ UINTN SingleDpSize;\r
+ UINTN Size;\r
+\r
+ NewDevicePath = NULL;\r
+ TempNewDevicePath = NULL;\r
+\r
+ if (Multi == NULL || Single == NULL) {\r
+ return Multi;\r
+ }\r
+\r
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+ SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;\r
+ InstanceSize -= END_DEVICE_PATH_LENGTH;\r
+\r
+ while (Instance != NULL) {\r
+\r
+ Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;\r
+\r
+ if ((CompareMem (Instance, Single, Size) != 0)) {\r
+ //\r
+ // Append the device path instance which does not match with Single\r
+ //\r
+ TempNewDevicePath = NewDevicePath;\r
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);\r
+ SafeFreePool(TempNewDevicePath);\r
+ }\r
+ SafeFreePool(Instance);\r
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+ InstanceSize -= END_DEVICE_PATH_LENGTH;\r
+ }\r
+\r
+ return NewDevicePath;\r
+}\r
+\r
+\r
+/**\r
+ Function compares a device path data structure to that of all the nodes of a\r
+ second device path instance.\r
+\r
+ @param Multi A pointer to a multi-instance device path data\r
+ structure.\r
+ @param Single A pointer to a single-instance device path data\r
+ structure.\r
+\r
+ @retval TRUE If the Single is contained within Multi\r
+ @retval FALSE The Single is not match within Multi\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibMatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\r
+\r
+ if (!Multi || !Single) {\r
+ return FALSE;\r
+ }\r
+\r
+ DevicePath = Multi;\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+\r
+ //\r
+ // Search for the match of 'Single' in 'Multi'\r
+ //\r
+ while (DevicePathInst != NULL) {\r
+ //\r
+ // If the single device path is found in multiple device paths,\r
+ // return success\r
+ //\r
+ if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+ gBS->FreePool (DevicePathInst);\r
+ return TRUE;\r
+ }\r
+\r
+ gBS->FreePool (DevicePathInst);\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ This function prints a series of strings.\r
+\r
+ @param ConOut Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+ @param ... A variable argument list containing series of\r
+ strings, the last string must be NULL.\r
+\r
+ @retval EFI_SUCCESS Success print out the string using ConOut.\r
+ @retval EFI_STATUS Return the status of the ConOut->OutputString ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibOutputStrings (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST args;\r
+ EFI_STATUS Status;\r
+ CHAR16 *String;\r
+\r
+ Status = EFI_SUCCESS;\r
+ VA_START (args, ConOut);\r
+\r
+ while (!EFI_ERROR (Status)) {\r
+ //\r
+ // If String is NULL, then it's the end of the list\r
+ //\r
+ String = VA_ARG (args, CHAR16 *);\r
+ if (!String) {\r
+ break;\r
+ }\r
+\r
+ Status = ConOut->OutputString (ConOut, String);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+//\r
+// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.\r
+// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if\r
+// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.\r
+//\r
+\r
+\r
+/**\r
+ Enable the setup browser reset reminder feature.\r
+ This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetReminderFeature (\r
+ VOID\r
+ )\r
+{\r
+ mFeaturerSwitch = TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Disable the setup browser reset reminder feature.\r
+ This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetReminderFeature (\r
+ VOID\r
+ )\r
+{\r
+ mFeaturerSwitch = FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Record the info that a reset is required.\r
+ A module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ mResetRequired = TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Record the info that no reset is required.\r
+ A module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ mResetRequired = FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Check whether platform policy enable the reset reminder feature. The default is enabled.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetReminderFeatureEnable (\r
+ VOID\r
+ )\r
+{\r
+ return mFeaturerSwitch;\r
+}\r
+\r
+\r
+/**\r
+ Check if user changed any option setting which needs a system reset to be effective.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ return mResetRequired;\r
+}\r
+\r
+\r
+/**\r
+ Check whether a reset is needed, and finish the reset reminder feature.\r
+ If a reset is needed, Popup a menu to notice user, and finish the feature\r
+ according to the user selection.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupResetReminder (\r
+ VOID\r
+ )\r
+{\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 *StringBuffer1;\r
+ CHAR16 *StringBuffer2;\r
+\r
+\r
+ //\r
+ //check any reset required change is applied? if yes, reset system\r
+ //\r
+ if (IsResetReminderFeatureEnable ()) {\r
+ if (IsResetRequired ()) {\r
+\r
+ StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+ ASSERT (StringBuffer1 != NULL);\r
+ StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+ ASSERT (StringBuffer2 != NULL);\r
+ StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
+ StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)");\r
+ //\r
+ // Popup a menu to notice user\r
+ //\r
+ do {\r
+ IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ gBS->FreePool (StringBuffer1);\r
+ gBS->FreePool (StringBuffer2);\r
+ //\r
+ // If the user hits the YES Response key, reset\r
+ //\r
+ if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+ }\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Get the headers (dos, image, optional header) from an image\r
+\r
+ @param Device SimpleFileSystem device handle\r
+ @param FileName File name for the image\r
+ @param DosHeader Pointer to dos header\r
+ @param ImageHeader Pointer to image header\r
+ @param OptionalHeader Pointer to optional header\r
+\r
+ @retval EFI_SUCCESS Successfully get the machine type.\r
+ @retval EFI_NOT_FOUND The file is not found.\r
+ @retval EFI_LOAD_ERROR File is not a valid image file.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetImageHeader (\r
+ IN EFI_HANDLE Device,\r
+ IN CHAR16 *FileName,\r
+ OUT EFI_IMAGE_DOS_HEADER *DosHeader,\r
+ OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+ EFI_FILE_HANDLE Root;\r
+ EFI_FILE_HANDLE ThisFile;\r
+ UINTN BufferSize;\r
+ UINT64 FileSize;\r
+ EFI_FILE_INFO *Info;\r
+\r
+ Root = NULL;\r
+ ThisFile = NULL;\r
+ //\r
+ // Handle the file system interface to the device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Device,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID *) &Volume\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = Volume->OpenVolume (\r
+ Volume,\r
+ &Root\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get file size\r
+ //\r
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
+ do {\r
+ Info = NULL;\r
+ Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ Status = ThisFile->GetInfo (\r
+ ThisFile,\r
+ &gEfiFileInfoGuid,\r
+ &BufferSize,\r
+ Info\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ goto Done;\r
+ }\r
+ gBS->FreePool (Info);\r
+ } while (TRUE);\r
+\r
+ FileSize = Info->FileSize;\r
+ gBS->FreePool (Info);\r
+\r
+ //\r
+ // Read dos header\r
+ //\r
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+ Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);\r
+ if (EFI_ERROR (Status) ||\r
+ BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||\r
+ FileSize <= DosHeader->e_lfanew ||\r
+ DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Move to PE signature\r
+ //\r
+ Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Read and check PE signature\r
+ //\r
+ BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+ Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);\r
+ if (EFI_ERROR (Status) ||\r
+ BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||\r
+ Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check PE32 or PE32+ magic\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&\r
+ Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ Done:\r
+ if (ThisFile != NULL) {\r
+ ThisFile->Close (ThisFile);\r
+ }\r
+ if (Root != NULL) {\r
+ Root->Close (Root);\r
+ }\r
+ return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+BdsSetMemoryTypeInformationVariable (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine is a notification function for legayc boot or exit boot\r
+ service event. It will adjust the memory information for different\r
+ memory type and save them into the variables for next boot\r
+\r
+Arguments:\r
+\r
+ Event - The event that triggered this notification function\r
+ Context - Pointer to the notification functions context\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;\r
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;\r
+ UINTN VariableSize;\r
+ BOOLEAN UpdateRequired;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINT32 Previous;\r
+ UINT32 Current;\r
+ UINT32 Next;\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+\r
+ UpdateRequired = FALSE;\r
+\r
+ //\r
+ // Retrieve the current memory usage statistics. If they are not found, then\r
+ // no adjustments can be made to the Memory Type Information variable.\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiMemoryTypeInformationGuid,\r
+ (VOID **) &CurrentMemoryTypeInformation\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get the Memory Type Information settings from Hob if they exist,\r
+ // PEI is responsible for getting them from variable and build a Hob to save them.\r
+ // If the previous Memory Type Information is not available, then set defaults\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
+ if (GuidHob == NULL) {\r
+ //\r
+ // If Platform has not built Memory Type Info into the Hob, just return.\r
+ //\r
+ return;\r
+ }\r
+ PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
+ VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
+\r
+ //\r
+ // Use a heuristic to adjust the Memory Type Information for the next boot\r
+ //\r
+ for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
+\r
+ Current = 0;\r
+ for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {\r
+ if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {\r
+ Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {\r
+ continue;\r
+ }\r
+\r
+ Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;\r
+\r
+ //\r
+ // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail\r
+ //\r
+ if (Current > Previous) {\r
+ Next = Current + (Current >> 2);\r
+ } else {\r
+ Next = Previous;\r
+ }\r
+ if (Next > 0 && Next < 4) {\r
+ Next = 4;\r
+ }\r
+\r
+ if (Next != Previous) {\r
+ PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\r
+ UpdateRequired = TRUE;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // If any changes were made to the Memory Type Information settings, then set the new variable value\r
+ //\r
+ if (UpdateRequired) {\r
+ Status = gRT->SetVariable (\r
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+ &gEfiMemoryTypeInformationGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ VariableSize,\r
+ PreviousMemoryTypeInformation\r
+ );\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+/**\r
+ This routine register a function to adjust the different type memory page number just before booting\r
+ and save the updated info into the variable for next boot to use\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibSaveMemoryTypeInformation (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT ReadyToBootEvent;\r
+\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ BdsSetMemoryTypeInformationVariable,\r
+ NULL,\r
+ &ReadyToBootEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));\r
+ }\r
+\r
+}\r
+\r
+\r
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- DevicePath.c
-
-Abstract:
-
- BDS internal function define the default device path string, it can be
- replaced by platform device path.
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-//
-// Platform Code should implement the Vendor specific Device Path display routine.
-//
-extern
-VOID
-DevPathVendor (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-;
-
-EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL;
-
-EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS;
-
-
-VOID *
-ReallocatePool (
- IN VOID *OldPool,
- IN UINTN OldSize,
- IN UINTN NewSize
- )
-/*++
-
-Routine Description:
-
- Adjusts the size of a previously allocated buffer.
-
-Arguments:
-
- OldPool - A pointer to the buffer whose size is being adjusted.
-
- OldSize - The size of the current buffer.
-
- NewSize - The size of the new buffer.
-
-Returns:
-
- EFI_SUCEESS - The requested number of bytes were allocated.
-
- EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.
-
- EFI_INVALID_PARAMETER - The buffer was invalid.
-
---*/
-{
- VOID *NewPool;
-
- NewPool = NULL;
- if (NewSize) {
- NewPool = AllocateZeroPool (NewSize);
- }
-
- if (OldPool) {
- if (NewPool) {
- CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
- }
-
- gBS->FreePool (OldPool);
- }
-
- return NewPool;
-}
-
-
-/**
- Concatenates a formatted unicode string to allocated pool.
- The caller must free the resulting buffer.
-
- @param Str Tracks the allocated pool, size in use, and amount of pool
- allocated.
- @param fmt The format string
-
- @return Allocated buffer with the formatted string printed in it.
- @return The caller must free the allocated buffer. The buffer
- @return allocation is not packed.
-
-**/
-CHAR16 *
-CatPrint (
- IN OUT POOL_PRINT *Str,
- IN CHAR16 *fmt,
- ...
- )
-{
- UINT16 *AppendStr;
- VA_LIST args;
- UINTN strsize;
-
- AppendStr = AllocateZeroPool (0x1000);
- if (AppendStr == NULL) {
- return Str->str;
- }
-
- VA_START (args, fmt);
- UnicodeVSPrint (AppendStr, 0x1000, fmt, args);
- VA_END (args);
- if (NULL == Str->str) {
- strsize = StrSize (AppendStr);
- Str->str = AllocateZeroPool (strsize);
- ASSERT (Str->str != NULL);
- } else {
- strsize = StrSize (AppendStr);
- strsize += (StrSize (Str->str) - sizeof (UINT16));
-
- Str->str = ReallocatePool (
- Str->str,
- StrSize (Str->str),
- strsize
- );
- ASSERT (Str->str != NULL);
- }
-
- Str->maxlen = MAX_CHAR * sizeof (UINT16);
- if (strsize < Str->maxlen) {
- StrCat (Str->str, AppendStr);
- Str->len = strsize - sizeof (UINT16);
- }
-
- gBS->FreePool (AppendStr);
- return Str->str;
-}
-
-
-/**
- Function unpacks a device path data structure so that all the nodes
- of a device path are naturally aligned.
-
- @param DevPath A pointer to a device path data structure
-
- @return If the memory for the device path is successfully allocated, then a
- @return pointer to the new device path is returned. Otherwise, NULL is returned.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BdsLibUnpackDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *Src;
- EFI_DEVICE_PATH_PROTOCOL *Dest;
- EFI_DEVICE_PATH_PROTOCOL *NewPath;
- UINTN Size;
-
- //
- // Walk device path and round sizes to valid boundries
- //
- Src = DevPath;
- Size = 0;
- for (;;) {
- Size += DevicePathNodeLength (Src);
- Size += ALIGN_SIZE (Size);
-
- if (IsDevicePathEnd (Src)) {
- break;
- }
-
- Src = NextDevicePathNode (Src);
- }
- //
- // Allocate space for the unpacked path
- //
- NewPath = AllocateZeroPool (Size);
- if (NewPath) {
-
- ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
-
- //
- // Copy each node
- //
- Src = DevPath;
- Dest = NewPath;
- for (;;) {
- Size = DevicePathNodeLength (Src);
- CopyMem (Dest, Src, Size);
- Size += ALIGN_SIZE (Size);
- SetDevicePathNodeLength (Dest, Size);
- Dest->Type |= EFI_DP_TYPE_UNPACKED;
- Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
-
- if (IsDevicePathEnd (Src)) {
- break;
- }
-
- Src = NextDevicePathNode (Src);
- }
- }
-
- return NewPath;
-}
-
-VOID
-DevPathPci (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- PCI_DEVICE_PATH *Pci;
-
- Pci = DevPath;
- CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);
-}
-
-VOID
-DevPathPccard (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- PCCARD_DEVICE_PATH *Pccard;
-
- Pccard = DevPath;
- CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);
-}
-
-VOID
-DevPathMemMap (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- MEMMAP_DEVICE_PATH *MemMap;
-
- MemMap = DevPath;
- CatPrint (
- Str,
- L"MemMap(%d:%lx-%lx)",
- MemMap->MemoryType,
- MemMap->StartingAddress,
- MemMap->EndingAddress
- );
-}
-
-VOID
-DevPathController (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- CONTROLLER_DEVICE_PATH *Controller;
-
- Controller = DevPath;
- CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);
-}
-
-
-/**
- Convert Vendor device path to device name
-
- @param Str The buffer store device name
- @param DevPath Pointer to vendor device path
-
- @return When it return, the device name have been stored in *Str.
-
-**/
-VOID
-DevPathVendor (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
- CHAR16 *Type;
- UINTN DataLength;
- UINTN Index;
- UINT32 FlowControlMap;
-
- UINT16 Info;
-
- Vendor = DevPath;
-
- switch (DevicePathType (&Vendor->Header)) {
- case HARDWARE_DEVICE_PATH:
- Type = L"Hw";
-// bugbug: nt 32 specific definition
-#if 0
- //
- // If the device is a winntbus device, we will give it a readable device name.
- //
- if (CompareGuid (&Vendor->Guid, &mEfiWinNtThunkProtocolGuid)) {
- CatPrint (Str, L"%s", L"WinNtBus");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtGopGuid)) {
- CatPrint (Str, L"%s", L"GOP");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtSerialPortGuid)) {
- CatPrint (Str, L"%s", L"Serial");
- return ;
- }
-#endif
- break;
-
- case MESSAGING_DEVICE_PATH:
- Type = L"Msg";
- if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
- CatPrint (Str, L"VenPcAnsi()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
- CatPrint (Str, L"VenVt100()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
- CatPrint (Str, L"VenVt100Plus()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
- CatPrint (Str, L"VenUft8()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) {
- FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
- switch (FlowControlMap & 0x00000003) {
- case 0:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
- break;
-
- case 1:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
- break;
-
- case 2:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
- break;
-
- default:
- break;
- }
-
- return ;
-
- } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) {
- CatPrint (
- Str,
- L"SAS(%lx,%lx,%x,",
- ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
- ((SAS_DEVICE_PATH *) Vendor)->Lun,
- ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
- );
- Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
- if ((Info & 0x0f) == 0) {
- CatPrint (Str, L"NoTopology,0,0,0,");
- } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
- CatPrint (
- Str,
- L"%s,%s,%s,",
- (Info & (0x1 << 4)) ? L"SATA" : L"SAS",
- (Info & (0x1 << 5)) ? L"External" : L"Internal",
- (Info & (0x1 << 6)) ? L"Expanded" : L"Direct"
- );
- if ((Info & 0x0f) == 1) {
- CatPrint (Str, L"0,");
- } else {
- CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));
- }
- } else {
- CatPrint (Str, L"0,0,0,0,");
- }
-
- CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);
- return ;
-
- } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
- CatPrint (Str, L"DebugPort()");
- return ;
- }
- break;
-
- case MEDIA_DEVICE_PATH:
- Type = L"Media";
- break;
-
- default:
- Type = L"?";
- break;
- }
-
- CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
- DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
- if (DataLength > 0) {
- CatPrint (Str, L",");
- for (Index = 0; Index < DataLength; Index++) {
- CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
- }
- }
- CatPrint (Str, L")");
-}
-
-
-VOID
-DevPathAcpi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- ACPI_HID_DEVICE_PATH *Acpi;
-
- Acpi = DevPath;
- if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);
- } else {
- CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);
- }
-}
-
-VOID
-DevPathExtendedAcpi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi;
- //
- // Index for HID, UID and CID strings, 0 for non-exist
- //
- UINT16 HIDSTRIdx;
- UINT16 UIDSTRIdx;
- UINT16 CIDSTRIdx;
- UINT16 Index;
- UINT16 Length;
- UINT16 Anchor;
- CHAR8 *AsChar8Array;
-
- ASSERT (Str != NULL);
- ASSERT (DevPath != NULL);
-
- HIDSTRIdx = 0;
- UIDSTRIdx = 0;
- CIDSTRIdx = 0;
- ExtendedAcpi = DevPath;
- Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);
-
- ASSERT (Length >= 19);
- AsChar8Array = (CHAR8 *) ExtendedAcpi;
-
- //
- // find HIDSTR
- //
- Anchor = 16;
- for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
- ;
- }
- if (Index > Anchor) {
- HIDSTRIdx = Anchor;
- }
- //
- // find UIDSTR
- //
- Anchor = (UINT16) (Index + 1);
- for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
- ;
- }
- if (Index > Anchor) {
- UIDSTRIdx = Anchor;
- }
- //
- // find CIDSTR
- //
- Anchor = (UINT16) (Index + 1);
- for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
- ;
- }
- if (Index > Anchor) {
- CIDSTRIdx = Anchor;
- }
-
- if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {
- CatPrint (Str, L"AcpiExp(");
- if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));
- } else {
- CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
- }
- if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));
- } else {
- CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);
- }
- if (UIDSTRIdx != 0) {
- CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
- } else {
- CatPrint (Str, L"\"\")");
- }
- } else {
- CatPrint (Str, L"AcpiEx(");
- if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));
- } else {
- CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);
- }
- if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));
- } else {
- CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);
- }
- CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);
-
- if (HIDSTRIdx != 0) {
- CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);
- } else {
- CatPrint (Str, L"\"\",");
- }
- if (CIDSTRIdx != 0) {
- CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);
- } else {
- CatPrint (Str, L"\"\",");
- }
- if (UIDSTRIdx != 0) {
- CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
- } else {
- CatPrint (Str, L"\"\")");
- }
- }
-
-}
-
-VOID
-DevPathAdrAcpi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- ACPI_ADR_DEVICE_PATH *AcpiAdr;
- UINT16 Index;
- UINT16 Length;
- UINT16 AdditionalAdrCount;
-
- AcpiAdr = DevPath;
- Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
- AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
-
- CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);
- for (Index = 0; Index < AdditionalAdrCount; Index++) {
- CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
- }
- CatPrint (Str, L")");
-}
-
-VOID
-DevPathAtapi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- ATAPI_DEVICE_PATH *Atapi;
-
- Atapi = DevPath;
- CatPrint (
- Str,
- L"Ata(%s,%s)",
- Atapi->PrimarySecondary ? L"Secondary" : L"Primary",
- Atapi->SlaveMaster ? L"Slave" : L"Master"
- );
-}
-
-VOID
-DevPathScsi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- SCSI_DEVICE_PATH *Scsi;
-
- Scsi = DevPath;
- CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);
-}
-
-VOID
-DevPathFibre (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- FIBRECHANNEL_DEVICE_PATH *Fibre;
-
- Fibre = DevPath;
- CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);
-}
-
-VOID
-DevPath1394 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- F1394_DEVICE_PATH *F1394;
-
- F1394 = DevPath;
- CatPrint (Str, L"1394(%g)", &F1394->Guid);
-}
-
-VOID
-DevPathUsb (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- USB_DEVICE_PATH *Usb;
-
- Usb = DevPath;
- CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);
-}
-
-VOID
-DevPathUsbWWID (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- USB_WWID_DEVICE_PATH *UsbWWId;
-
- UsbWWId = DevPath;
- CatPrint (
- Str,
- L"UsbWwid(%x,%x,%x,\"WWID\")",
- (UINTN) UsbWWId->VendorId,
- (UINTN) UsbWWId->ProductId,
- (UINTN) UsbWWId->InterfaceNumber
- );
-}
-
-VOID
-DevPathLogicalUnit (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
-
- LogicalUnit = DevPath;
- CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);
-}
-
-VOID
-DevPathUsbClass (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- USB_CLASS_DEVICE_PATH *UsbClass;
-
- UsbClass = DevPath;
- CatPrint (
- Str,
- L"Usb Class(%x,%x,%x,%x,%x)",
- (UINTN) UsbClass->VendorId,
- (UINTN) UsbClass->ProductId,
- (UINTN) UsbClass->DeviceClass,
- (UINTN) UsbClass->DeviceSubClass,
- (UINTN) UsbClass->DeviceProtocol
- );
-}
-
-VOID
-DevPathSata (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- SATA_DEVICE_PATH *Sata;
-
- Sata = DevPath;
- CatPrint (
- Str,
- L"Sata(%x,%x,%x)",
- (UINTN) Sata->HBAPortNumber,
- (UINTN) Sata->PortMultiplierPortNumber,
- (UINTN) Sata->Lun
- );
-}
-
-VOID
-DevPathI2O (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- I2O_DEVICE_PATH *I2O;
-
- I2O = DevPath;
- CatPrint (Str, L"I2O(%x)", (UINTN) I2O->Tid);
-}
-
-VOID
-DevPathMacAddr (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- MAC_ADDR_DEVICE_PATH *MAC;
- UINTN HwAddressSize;
- UINTN Index;
-
- MAC = DevPath;
-
- HwAddressSize = sizeof (EFI_MAC_ADDRESS);
- if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {
- HwAddressSize = 6;
- }
-
- CatPrint (Str, L"Mac(");
-
- for (Index = 0; Index < HwAddressSize; Index++) {
- CatPrint (Str, L"%02x", (UINTN) MAC->MacAddress.Addr[Index]);
- }
-
- CatPrint (Str, L")");
-}
-
-VOID
-DevPathIPv4 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- IPv4_DEVICE_PATH *IP;
-
- IP = DevPath;
- CatPrint (
- Str,
- L"IPv4(%d.%d.%d.%d:%d)",
- (UINTN) IP->RemoteIpAddress.Addr[0],
- (UINTN) IP->RemoteIpAddress.Addr[1],
- (UINTN) IP->RemoteIpAddress.Addr[2],
- (UINTN) IP->RemoteIpAddress.Addr[3],
- (UINTN) IP->RemotePort
- );
-}
-
-VOID
-DevPathIPv6 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- IPv6_DEVICE_PATH *IP;
-
- IP = DevPath;
- CatPrint (
- Str,
- L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
- (UINTN) IP->RemoteIpAddress.Addr[0],
- (UINTN) IP->RemoteIpAddress.Addr[1],
- (UINTN) IP->RemoteIpAddress.Addr[2],
- (UINTN) IP->RemoteIpAddress.Addr[3],
- (UINTN) IP->RemoteIpAddress.Addr[4],
- (UINTN) IP->RemoteIpAddress.Addr[5],
- (UINTN) IP->RemoteIpAddress.Addr[6],
- (UINTN) IP->RemoteIpAddress.Addr[7],
- (UINTN) IP->RemoteIpAddress.Addr[8],
- (UINTN) IP->RemoteIpAddress.Addr[9],
- (UINTN) IP->RemoteIpAddress.Addr[10],
- (UINTN) IP->RemoteIpAddress.Addr[11],
- (UINTN) IP->RemoteIpAddress.Addr[12],
- (UINTN) IP->RemoteIpAddress.Addr[13],
- (UINTN) IP->RemoteIpAddress.Addr[14],
- (UINTN) IP->RemoteIpAddress.Addr[15]
- );
-}
-
-VOID
-DevPathInfiniBand (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- INFINIBAND_DEVICE_PATH *InfiniBand;
-
- InfiniBand = DevPath;
- CatPrint (
- Str,
- L"Infiniband(%x,%g,%lx,%lx,%lx)",
- (UINTN) InfiniBand->ResourceFlags,
- InfiniBand->PortGid,
- InfiniBand->ServiceId,
- InfiniBand->TargetPortId,
- InfiniBand->DeviceId
- );
-}
-
-VOID
-DevPathUart (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- UART_DEVICE_PATH *Uart;
- CHAR8 Parity;
-
- Uart = DevPath;
- switch (Uart->Parity) {
- case 0:
- Parity = 'D';
- break;
-
- case 1:
- Parity = 'N';
- break;
-
- case 2:
- Parity = 'E';
- break;
-
- case 3:
- Parity = 'O';
- break;
-
- case 4:
- Parity = 'M';
- break;
-
- case 5:
- Parity = 'S';
- break;
-
- default:
- Parity = 'x';
- break;
- }
-
- if (Uart->BaudRate == 0) {
- CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);
- } else {
- CatPrint (Str, L"Uart(%d,%c,", Uart->BaudRate, Parity);
- }
-
- if (Uart->DataBits == 0) {
- CatPrint (Str, L"D,");
- } else {
- CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);
- }
-
- switch (Uart->StopBits) {
- case 0:
- CatPrint (Str, L"D)");
- break;
-
- case 1:
- CatPrint (Str, L"1)");
- break;
-
- case 2:
- CatPrint (Str, L"1.5)");
- break;
-
- case 3:
- CatPrint (Str, L"2)");
- break;
-
- default:
- CatPrint (Str, L"x)");
- break;
- }
-}
-
-VOID
-DevPathiSCSI (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- ISCSI_DEVICE_PATH_WITH_NAME *iSCSI;
- UINT16 Options;
-
- ASSERT (Str != NULL);
- ASSERT (DevPath != NULL);
-
- iSCSI = DevPath;
- CatPrint (
- Str,
- L"iSCSI(%s,%x,%lx,",
- iSCSI->iSCSITargetName,
- iSCSI->TargetPortalGroupTag,
- iSCSI->Lun
- );
-
- Options = iSCSI->LoginOption;
- CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None");
- CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None");
- if ((Options >> 11) & 0x0001) {
- CatPrint (Str, L"%s,", L"None");
- } else if ((Options >> 12) & 0x0001) {
- CatPrint (Str, L"%s,", L"CHAP_UNI");
- } else {
- CatPrint (Str, L"%s,", L"CHAP_BI");
-
- }
-
- CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved");
-}
-
-VOID
-DevPathHardDrive (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- HARDDRIVE_DEVICE_PATH *Hd;
-
- Hd = DevPath;
- switch (Hd->SignatureType) {
- case SIGNATURE_TYPE_MBR:
- CatPrint (
- Str,
- L"HD(Part%d,Sig%08x)",
- (UINTN) Hd->PartitionNumber,
- (UINTN) *((UINT32 *) (&(Hd->Signature[0])))
- );
- break;
-
- case SIGNATURE_TYPE_GUID:
- CatPrint (
- Str,
- L"HD(Part%d,Sig%g)",
- (UINTN) Hd->PartitionNumber,
- (EFI_GUID *) &(Hd->Signature[0])
- );
- break;
-
- default:
- CatPrint (
- Str,
- L"HD(Part%d,MBRType=%02x,SigType=%02x)",
- (UINTN) Hd->PartitionNumber,
- (UINTN) Hd->MBRType,
- (UINTN) Hd->SignatureType
- );
- break;
- }
-}
-
-VOID
-DevPathCDROM (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- CDROM_DEVICE_PATH *Cd;
-
- Cd = DevPath;
- CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);
-}
-
-VOID
-DevPathFilePath (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- FILEPATH_DEVICE_PATH *Fp;
-
- Fp = DevPath;
- CatPrint (Str, L"%s", Fp->PathName);
-}
-
-VOID
-DevPathMediaProtocol (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
-
- MediaProt = DevPath;
- CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
-}
-
-VOID
-DevPathFvFilePath (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
-
- FvFilePath = DevPath;
- CatPrint (Str, L"%g", &FvFilePath->FvFileName);
-}
-
-VOID
-DevPathBssBss (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- BBS_BBS_DEVICE_PATH *Bbs;
- CHAR16 *Type;
-
- Bbs = DevPath;
- switch (Bbs->DeviceType) {
- case BBS_TYPE_FLOPPY:
- Type = L"Floppy";
- break;
-
- case BBS_TYPE_HARDDRIVE:
- Type = L"Harddrive";
- break;
-
- case BBS_TYPE_CDROM:
- Type = L"CDROM";
- break;
-
- case BBS_TYPE_PCMCIA:
- Type = L"PCMCIA";
- break;
-
- case BBS_TYPE_USB:
- Type = L"Usb";
- break;
-
- case BBS_TYPE_EMBEDDED_NETWORK:
- Type = L"Net";
- break;
-
- case BBS_TYPE_BEV:
- Type = L"BEV";
- break;
-
- default:
- Type = L"?";
- break;
- }
- CatPrint (Str, L"Legacy-%s", Type);
-}
-
-VOID
-DevPathEndInstance (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- CatPrint (Str, L",");
-}
-
-VOID
-DevPathNodeUnknown (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath
- )
-{
- CatPrint (Str, L"?");
-}
-
-DEVICE_PATH_STRING_TABLE DevPathTable[] = {
- HARDWARE_DEVICE_PATH,
- HW_PCI_DP,
- DevPathPci,
- HARDWARE_DEVICE_PATH,
- HW_PCCARD_DP,
- DevPathPccard,
- HARDWARE_DEVICE_PATH,
- HW_MEMMAP_DP,
- DevPathMemMap,
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP,
- DevPathVendor,
- HARDWARE_DEVICE_PATH,
- HW_CONTROLLER_DP,
- DevPathController,
- ACPI_DEVICE_PATH,
- ACPI_DP,
- DevPathAcpi,
- ACPI_DEVICE_PATH,
- ACPI_EXTENDED_DP,
- DevPathExtendedAcpi,
- ACPI_DEVICE_PATH,
- ACPI_ADR_DP,
- DevPathAdrAcpi,
- MESSAGING_DEVICE_PATH,
- MSG_ATAPI_DP,
- DevPathAtapi,
- MESSAGING_DEVICE_PATH,
- MSG_SCSI_DP,
- DevPathScsi,
- MESSAGING_DEVICE_PATH,
- MSG_FIBRECHANNEL_DP,
- DevPathFibre,
- MESSAGING_DEVICE_PATH,
- MSG_1394_DP,
- DevPath1394,
- MESSAGING_DEVICE_PATH,
- MSG_USB_DP,
- DevPathUsb,
- MESSAGING_DEVICE_PATH,
- MSG_USB_WWID_DP,
- DevPathUsbWWID,
- MESSAGING_DEVICE_PATH,
- MSG_DEVICE_LOGICAL_UNIT_DP,
- DevPathLogicalUnit,
- MESSAGING_DEVICE_PATH,
- MSG_USB_CLASS_DP,
- DevPathUsbClass,
- MESSAGING_DEVICE_PATH,
- MSG_SATA_DP,
- DevPathSata,
- MESSAGING_DEVICE_PATH,
- MSG_I2O_DP,
- DevPathI2O,
- MESSAGING_DEVICE_PATH,
- MSG_MAC_ADDR_DP,
- DevPathMacAddr,
- MESSAGING_DEVICE_PATH,
- MSG_IPv4_DP,
- DevPathIPv4,
- MESSAGING_DEVICE_PATH,
- MSG_IPv6_DP,
- DevPathIPv6,
- MESSAGING_DEVICE_PATH,
- MSG_INFINIBAND_DP,
- DevPathInfiniBand,
- MESSAGING_DEVICE_PATH,
- MSG_UART_DP,
- DevPathUart,
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- DevPathVendor,
- MESSAGING_DEVICE_PATH,
- MSG_ISCSI_DP,
- DevPathiSCSI,
- MEDIA_DEVICE_PATH,
- MEDIA_HARDDRIVE_DP,
- DevPathHardDrive,
- MEDIA_DEVICE_PATH,
- MEDIA_CDROM_DP,
- DevPathCDROM,
- MEDIA_DEVICE_PATH,
- MEDIA_VENDOR_DP,
- DevPathVendor,
- MEDIA_DEVICE_PATH,
- MEDIA_FILEPATH_DP,
- DevPathFilePath,
- MEDIA_DEVICE_PATH,
- MEDIA_PROTOCOL_DP,
- DevPathMediaProtocol,
- MEDIA_DEVICE_PATH,
- MEDIA_PIWG_FW_FILE_DP,
- DevPathFvFilePath,
- BBS_DEVICE_PATH,
- BBS_BBS_DP,
- DevPathBssBss,
- END_DEVICE_PATH_TYPE,
- END_INSTANCE_DEVICE_PATH_SUBTYPE,
- DevPathEndInstance,
- 0,
- 0,
- NULL
-};
-
-
-/**
-
-**/
-CHAR16 *
-DevicePathToStr (
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath
- )
-{
- POOL_PRINT Str;
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
- VOID (*DumpNode) (POOL_PRINT *, VOID *);
-
- UINTN Index;
- UINTN NewSize;
-
- EFI_STATUS Status;
- CHAR16 *ToText;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
-
- ZeroMem (&Str, sizeof (Str));
-
- if (DevPath == NULL) {
- goto Done;
- }
-
- Status = gBS->LocateProtocol (
- &gEfiDevicePathToTextProtocolGuid,
- NULL,
- (VOID **) &DevPathToText
- );
- if (!EFI_ERROR (Status)) {
- ToText = DevPathToText->ConvertDevicePathToText (
- DevPath,
- FALSE,
- TRUE
- );
- ASSERT (ToText != NULL);
- return ToText;
- }
-
- //
- // Unpacked the device path
- //
- DevPath = BdsLibUnpackDevicePath (DevPath);
- ASSERT (DevPath);
-
- //
- // Process each device path node
- //
- DevPathNode = DevPath;
- while (!IsDevicePathEnd (DevPathNode)) {
- //
- // Find the handler to dump this device path node
- //
- DumpNode = NULL;
- for (Index = 0; DevPathTable[Index].Function; Index += 1) {
-
- if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&
- DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType
- ) {
- DumpNode = DevPathTable[Index].Function;
- break;
- }
- }
- //
- // If not found, use a generic function
- //
- if (!DumpNode) {
- DumpNode = DevPathNodeUnknown;
- }
- //
- // Put a path seperator in if needed
- //
- if (Str.len && DumpNode != DevPathEndInstance) {
- CatPrint (&Str, L"/");
- }
- //
- // Print this node of the device path
- //
- DumpNode (&Str, DevPathNode);
-
- //
- // Next device path node
- //
- DevPathNode = NextDevicePathNode (DevPathNode);
- }
- //
- // Shrink pool used for string allocation
- //
- gBS->FreePool (DevPath);
-
-Done:
- NewSize = (Str.len + 1) * sizeof (CHAR16);
- Str.str = ReallocatePool (Str.str, NewSize, NewSize);
- ASSERT (Str.str != NULL);
- Str.str[Str.len] = 0;
- return Str.str;
-}
-
-
-/**
- Function creates a device path data structure that identically matches the
- device path passed in.
-
- @param DevPath A pointer to a device path data structure.
-
- @return The new copy of DevPath is created to identically match the input.
- @return Otherwise, NULL is returned.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-LibDuplicateDevicePathInstance (
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *NewDevPath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
- EFI_DEVICE_PATH_PROTOCOL *Temp;
- UINTN Size;
-
- //
- // get the size of an instance from the input
- //
- Temp = DevPath;
- DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);
-
- //
- // Make a copy
- //
- NewDevPath = NULL;
- if (Size) {
- NewDevPath = AllocateZeroPool (Size);
- ASSERT (NewDevPath != NULL);
- }
-
- if (NewDevPath) {
- CopyMem (NewDevPath, DevicePathInst, Size);
- }
-
- return NewDevPath;
-}
+/** @file\r
+ BDS internal function define the default device path string, it can be\r
+ replaced by platform device path.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL;\r
+\r
+EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS;\r
+\r
+\r
+VOID *\r
+ReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+\r
+ OldPool - A pointer to the buffer whose size is being adjusted.\r
+\r
+ OldSize - The size of the current buffer.\r
+\r
+ NewSize - The size of the new buffer.\r
+\r
+Returns:\r
+\r
+ EFI_SUCEESS - The requested number of bytes were allocated.\r
+\r
+ EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.\r
+\r
+ EFI_INVALID_PARAMETER - The buffer was invalid.\r
+\r
+--*/\r
+{\r
+ VOID *NewPool;\r
+\r
+ NewPool = NULL;\r
+ if (NewSize) {\r
+ NewPool = AllocateZeroPool (NewSize);\r
+ }\r
+\r
+ if (OldPool) {\r
+ if (NewPool) {\r
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+ }\r
+\r
+ gBS->FreePool (OldPool);\r
+ }\r
+\r
+ return NewPool;\r
+}\r
+\r
+\r
+/**\r
+ Concatenates a formatted unicode string to allocated pool.\r
+ The caller must free the resulting buffer.\r
+\r
+ @param Str Tracks the allocated pool, size in use, and amount of pool\r
+ allocated.\r
+ @param fmt The format string\r
+\r
+ @return Allocated buffer with the formatted string printed in it.\r
+ @return The caller must free the allocated buffer. The buffer\r
+ @return allocation is not packed.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+CatPrint (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN CHAR16 *fmt,\r
+ ...\r
+ )\r
+{\r
+ UINT16 *AppendStr;\r
+ VA_LIST args;\r
+ UINTN strsize;\r
+\r
+ AppendStr = AllocateZeroPool (0x1000);\r
+ if (AppendStr == NULL) {\r
+ return Str->str;\r
+ }\r
+\r
+ VA_START (args, fmt);\r
+ UnicodeVSPrint (AppendStr, 0x1000, fmt, args);\r
+ VA_END (args);\r
+ if (NULL == Str->str) {\r
+ strsize = StrSize (AppendStr);\r
+ Str->str = AllocateZeroPool (strsize);\r
+ ASSERT (Str->str != NULL);\r
+ } else {\r
+ strsize = StrSize (AppendStr);\r
+ strsize += (StrSize (Str->str) - sizeof (UINT16));\r
+\r
+ Str->str = ReallocatePool (\r
+ Str->str,\r
+ StrSize (Str->str),\r
+ strsize\r
+ );\r
+ ASSERT (Str->str != NULL);\r
+ }\r
+\r
+ Str->maxlen = MAX_CHAR * sizeof (UINT16);\r
+ if (strsize < Str->maxlen) {\r
+ StrCat (Str->str, AppendStr);\r
+ Str->len = strsize - sizeof (UINT16);\r
+ }\r
+\r
+ gBS->FreePool (AppendStr);\r
+ return Str->str;\r
+}\r
+\r
+\r
+/**\r
+ Function unpacks a device path data structure so that all the nodes\r
+ of a device path are naturally aligned.\r
+\r
+ @param DevPath A pointer to a device path data structure\r
+\r
+ @return A ponter to new device If the memory for the device path is successfully allocated, then a\r
+ pointer to the new device path is returned. Otherwise, NULL is returned.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsLibUnpackDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Src;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dest;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;\r
+ UINTN Size;\r
+\r
+ //\r
+ // Walk device path and round sizes to valid boundries\r
+ //\r
+ Src = DevPath;\r
+ Size = 0;\r
+ for (;;) {\r
+ Size += DevicePathNodeLength (Src);\r
+ Size += ALIGN_SIZE (Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ //\r
+ // Allocate space for the unpacked path\r
+ //\r
+ NewPath = AllocateZeroPool (Size);\r
+ if (NewPath) {\r
+\r
+ ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
+\r
+ //\r
+ // Copy each node\r
+ //\r
+ Src = DevPath;\r
+ Dest = NewPath;\r
+ for (;;) {\r
+ Size = DevicePathNodeLength (Src);\r
+ CopyMem (Dest, Src, Size);\r
+ Size += ALIGN_SIZE (Size);\r
+ SetDevicePathNodeLength (Dest, Size);\r
+ Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
+ Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ }\r
+\r
+ return NewPath;\r
+}\r
+\r
+VOID\r
+DevPathPci (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCI_DEVICE_PATH *Pci;\r
+\r
+ Pci = DevPath;\r
+ CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);\r
+}\r
+\r
+VOID\r
+DevPathPccard (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCCARD_DEVICE_PATH *Pccard;\r
+\r
+ Pccard = DevPath;\r
+ CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);\r
+}\r
+\r
+VOID\r
+DevPathMemMap (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEMMAP_DEVICE_PATH *MemMap;\r
+\r
+ MemMap = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"MemMap(%d:%lx-%lx)",\r
+ MemMap->MemoryType,\r
+ MemMap->StartingAddress,\r
+ MemMap->EndingAddress\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathController (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CONTROLLER_DEVICE_PATH *Controller;\r
+\r
+ Controller = DevPath;\r
+ CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);\r
+}\r
+\r
+\r
+/**\r
+ Convert Vendor device path to device name\r
+\r
+ @param Str The buffer store device name\r
+ @param DevPath Pointer to vendor device path\r
+\r
+ @return When it return, the device name have been stored in *Str.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DevPathVendor (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ VENDOR_DEVICE_PATH *Vendor;\r
+ CHAR16 *Type;\r
+ UINTN DataLength;\r
+ UINTN Index;\r
+ UINT32 FlowControlMap;\r
+\r
+ UINT16 Info;\r
+\r
+ Vendor = DevPath;\r
+\r
+ switch (DevicePathType (&Vendor->Header)) {\r
+ case HARDWARE_DEVICE_PATH:\r
+ Type = L"Hw";\r
+// bugbug: nt 32 specific definition\r
+#if 0\r
+ //\r
+ // If the device is a winntbus device, we will give it a readable device name.\r
+ //\r
+ if (CompareGuid (&Vendor->Guid, &mEfiWinNtThunkProtocolGuid)) {\r
+ CatPrint (Str, L"%s", L"WinNtBus");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtGopGuid)) {\r
+ CatPrint (Str, L"%s", L"GOP");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtSerialPortGuid)) {\r
+ CatPrint (Str, L"%s", L"Serial");\r
+ return ;\r
+ }\r
+#endif\r
+ break;\r
+\r
+ case MESSAGING_DEVICE_PATH:\r
+ Type = L"Msg";\r
+ if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {\r
+ CatPrint (Str, L"VenPcAnsi()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {\r
+ CatPrint (Str, L"VenVt100()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {\r
+ CatPrint (Str, L"VenVt100Plus()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {\r
+ CatPrint (Str, L"VenUft8()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) {\r
+ FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);\r
+ switch (FlowControlMap & 0x00000003) {\r
+ case 0:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"None");\r
+ break;\r
+\r
+ case 1:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");\r
+ break;\r
+\r
+ case 2:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return ;\r
+\r
+ } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) {\r
+ CatPrint (\r
+ Str,\r
+ L"SAS(%lx,%lx,%x,",\r
+ ((SAS_DEVICE_PATH *) Vendor)->SasAddress,\r
+ ((SAS_DEVICE_PATH *) Vendor)->Lun,\r
+ ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort\r
+ );\r
+ Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);\r
+ if ((Info & 0x0f) == 0) {\r
+ CatPrint (Str, L"NoTopology,0,0,0,");\r
+ } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {\r
+ CatPrint (\r
+ Str,\r
+ L"%s,%s,%s,",\r
+ (Info & (0x1 << 4)) ? L"SATA" : L"SAS",\r
+ (Info & (0x1 << 5)) ? L"External" : L"Internal",\r
+ (Info & (0x1 << 6)) ? L"Expanded" : L"Direct"\r
+ );\r
+ if ((Info & 0x0f) == 1) {\r
+ CatPrint (Str, L"0,");\r
+ } else {\r
+ CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));\r
+ }\r
+ } else {\r
+ CatPrint (Str, L"0,0,0,0,");\r
+ }\r
+\r
+ CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);\r
+ return ;\r
+\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {\r
+ CatPrint (Str, L"DebugPort()");\r
+ return ;\r
+ }\r
+ break;\r
+\r
+ case MEDIA_DEVICE_PATH:\r
+ Type = L"Media";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+\r
+ CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);\r
+ DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);\r
+ if (DataLength > 0) {\r
+ CatPrint (Str, L",");\r
+ for (Index = 0; Index < DataLength; Index++) {\r
+ CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);\r
+ }\r
+ }\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+\r
+VOID\r
+DevPathAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+\r
+ Acpi = DevPath;\r
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);\r
+ } else {\r
+ CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathExtendedAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi;\r
+ //\r
+ // Index for HID, UID and CID strings, 0 for non-exist\r
+ //\r
+ UINT16 HIDSTRIdx;\r
+ UINT16 UIDSTRIdx;\r
+ UINT16 CIDSTRIdx;\r
+ UINT16 Index;\r
+ UINT16 Length;\r
+ UINT16 Anchor;\r
+ CHAR8 *AsChar8Array;\r
+\r
+ ASSERT (Str != NULL);\r
+ ASSERT (DevPath != NULL);\r
+\r
+ HIDSTRIdx = 0;\r
+ UIDSTRIdx = 0;\r
+ CIDSTRIdx = 0;\r
+ ExtendedAcpi = DevPath;\r
+ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);\r
+\r
+ ASSERT (Length >= 19);\r
+ AsChar8Array = (CHAR8 *) ExtendedAcpi;\r
+\r
+ //\r
+ // find HIDSTR\r
+ //\r
+ Anchor = 16;\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ HIDSTRIdx = Anchor;\r
+ }\r
+ //\r
+ // find UIDSTR\r
+ //\r
+ Anchor = (UINT16) (Index + 1);\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ UIDSTRIdx = Anchor;\r
+ }\r
+ //\r
+ // find CIDSTR\r
+ //\r
+ Anchor = (UINT16) (Index + 1);\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ CIDSTRIdx = Anchor;\r
+ }\r
+\r
+ if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {\r
+ CatPrint (Str, L"AcpiExp(");\r
+ if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+ }\r
+ if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+ }\r
+ if (UIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\")");\r
+ }\r
+ } else {\r
+ CatPrint (Str, L"AcpiEx(");\r
+ if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+ }\r
+ if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+ }\r
+ CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);\r
+\r
+ if (HIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\",");\r
+ }\r
+ if (CIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\",");\r
+ }\r
+ if (UIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\")");\r
+ }\r
+ }\r
+\r
+}\r
+\r
+VOID\r
+DevPathAdrAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_ADR_DEVICE_PATH *AcpiAdr;\r
+ UINT16 Index;\r
+ UINT16 Length;\r
+ UINT16 AdditionalAdrCount;\r
+\r
+ AcpiAdr = DevPath;\r
+ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);\r
+ AdditionalAdrCount = (UINT16) ((Length - 8) / 4);\r
+\r
+ CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);\r
+ for (Index = 0; Index < AdditionalAdrCount; Index++) {\r
+ CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));\r
+ }\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+VOID\r
+DevPathAtapi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ATAPI_DEVICE_PATH *Atapi;\r
+\r
+ Atapi = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Ata(%s,%s)",\r
+ Atapi->PrimarySecondary ? L"Secondary" : L"Primary",\r
+ Atapi->SlaveMaster ? L"Slave" : L"Master"\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathScsi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ SCSI_DEVICE_PATH *Scsi;\r
+\r
+ Scsi = DevPath;\r
+ CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);\r
+}\r
+\r
+VOID\r
+DevPathFibre (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FIBRECHANNEL_DEVICE_PATH *Fibre;\r
+\r
+ Fibre = DevPath;\r
+ CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
+}\r
+\r
+VOID\r
+DevPath1394 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ F1394_DEVICE_PATH *F1394;\r
+\r
+ F1394 = DevPath;\r
+ CatPrint (Str, L"1394(%g)", &F1394->Guid);\r
+}\r
+\r
+VOID\r
+DevPathUsb (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_DEVICE_PATH *Usb;\r
+\r
+ Usb = DevPath;\r
+ CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);\r
+}\r
+\r
+VOID\r
+DevPathUsbWWID (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_WWID_DEVICE_PATH *UsbWWId;\r
+\r
+ UsbWWId = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"UsbWwid(%x,%x,%x,\"WWID\")",\r
+ (UINTN) UsbWWId->VendorId,\r
+ (UINTN) UsbWWId->ProductId,\r
+ (UINTN) UsbWWId->InterfaceNumber\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathLogicalUnit (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;\r
+\r
+ LogicalUnit = DevPath;\r
+ CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);\r
+}\r
+\r
+VOID\r
+DevPathUsbClass (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_CLASS_DEVICE_PATH *UsbClass;\r
+\r
+ UsbClass = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Usb Class(%x,%x,%x,%x,%x)",\r
+ (UINTN) UsbClass->VendorId,\r
+ (UINTN) UsbClass->ProductId,\r
+ (UINTN) UsbClass->DeviceClass,\r
+ (UINTN) UsbClass->DeviceSubClass,\r
+ (UINTN) UsbClass->DeviceProtocol\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathSata (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ SATA_DEVICE_PATH *Sata;\r
+\r
+ Sata = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Sata(%x,%x,%x)",\r
+ (UINTN) Sata->HBAPortNumber,\r
+ (UINTN) Sata->PortMultiplierPortNumber,\r
+ (UINTN) Sata->Lun\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathI2O (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ I2O_DEVICE_PATH *I2O;\r
+\r
+ I2O = DevPath;\r
+ CatPrint (Str, L"I2O(%x)", (UINTN) I2O->Tid);\r
+}\r
+\r
+VOID\r
+DevPathMacAddr (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MAC_ADDR_DEVICE_PATH *MAC;\r
+ UINTN HwAddressSize;\r
+ UINTN Index;\r
+\r
+ MAC = DevPath;\r
+\r
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
+ if (MAC->IfType == 0x01 || MAC->IfType == 0x00) {\r
+ HwAddressSize = 6;\r
+ }\r
+\r
+ CatPrint (Str, L"Mac(");\r
+\r
+ for (Index = 0; Index < HwAddressSize; Index++) {\r
+ CatPrint (Str, L"%02x", (UINTN) MAC->MacAddress.Addr[Index]);\r
+ }\r
+\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+VOID\r
+DevPathIPv4 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv4_DEVICE_PATH *IP;\r
+\r
+ IP = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"IPv4(%d.%d.%d.%d:%d)",\r
+ (UINTN) IP->RemoteIpAddress.Addr[0],\r
+ (UINTN) IP->RemoteIpAddress.Addr[1],\r
+ (UINTN) IP->RemoteIpAddress.Addr[2],\r
+ (UINTN) IP->RemoteIpAddress.Addr[3],\r
+ (UINTN) IP->RemotePort\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathIPv6 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv6_DEVICE_PATH *IP;\r
+\r
+ IP = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",\r
+ (UINTN) IP->RemoteIpAddress.Addr[0],\r
+ (UINTN) IP->RemoteIpAddress.Addr[1],\r
+ (UINTN) IP->RemoteIpAddress.Addr[2],\r
+ (UINTN) IP->RemoteIpAddress.Addr[3],\r
+ (UINTN) IP->RemoteIpAddress.Addr[4],\r
+ (UINTN) IP->RemoteIpAddress.Addr[5],\r
+ (UINTN) IP->RemoteIpAddress.Addr[6],\r
+ (UINTN) IP->RemoteIpAddress.Addr[7],\r
+ (UINTN) IP->RemoteIpAddress.Addr[8],\r
+ (UINTN) IP->RemoteIpAddress.Addr[9],\r
+ (UINTN) IP->RemoteIpAddress.Addr[10],\r
+ (UINTN) IP->RemoteIpAddress.Addr[11],\r
+ (UINTN) IP->RemoteIpAddress.Addr[12],\r
+ (UINTN) IP->RemoteIpAddress.Addr[13],\r
+ (UINTN) IP->RemoteIpAddress.Addr[14],\r
+ (UINTN) IP->RemoteIpAddress.Addr[15]\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathInfiniBand (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ INFINIBAND_DEVICE_PATH *InfiniBand;\r
+\r
+ InfiniBand = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Infiniband(%x,%g,%lx,%lx,%lx)",\r
+ (UINTN) InfiniBand->ResourceFlags,\r
+ InfiniBand->PortGid,\r
+ InfiniBand->ServiceId,\r
+ InfiniBand->TargetPortId,\r
+ InfiniBand->DeviceId\r
+ );\r
+}\r
+\r
+VOID\r
+DevPathUart (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ UART_DEVICE_PATH *Uart;\r
+ CHAR8 Parity;\r
+\r
+ Uart = DevPath;\r
+ switch (Uart->Parity) {\r
+ case 0:\r
+ Parity = 'D';\r
+ break;\r
+\r
+ case 1:\r
+ Parity = 'N';\r
+ break;\r
+\r
+ case 2:\r
+ Parity = 'E';\r
+ break;\r
+\r
+ case 3:\r
+ Parity = 'O';\r
+ break;\r
+\r
+ case 4:\r
+ Parity = 'M';\r
+ break;\r
+\r
+ case 5:\r
+ Parity = 'S';\r
+ break;\r
+\r
+ default:\r
+ Parity = 'x';\r
+ break;\r
+ }\r
+\r
+ if (Uart->BaudRate == 0) {\r
+ CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);\r
+ } else {\r
+ CatPrint (Str, L"Uart(%d,%c,", Uart->BaudRate, Parity);\r
+ }\r
+\r
+ if (Uart->DataBits == 0) {\r
+ CatPrint (Str, L"D,");\r
+ } else {\r
+ CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);\r
+ }\r
+\r
+ switch (Uart->StopBits) {\r
+ case 0:\r
+ CatPrint (Str, L"D)");\r
+ break;\r
+\r
+ case 1:\r
+ CatPrint (Str, L"1)");\r
+ break;\r
+\r
+ case 2:\r
+ CatPrint (Str, L"1.5)");\r
+ break;\r
+\r
+ case 3:\r
+ CatPrint (Str, L"2)");\r
+ break;\r
+\r
+ default:\r
+ CatPrint (Str, L"x)");\r
+ break;\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathiSCSI (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ISCSI_DEVICE_PATH_WITH_NAME *iSCSI;\r
+ UINT16 Options;\r
+\r
+ ASSERT (Str != NULL);\r
+ ASSERT (DevPath != NULL);\r
+\r
+ iSCSI = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"iSCSI(%s,%x,%lx,",\r
+ iSCSI->iSCSITargetName,\r
+ iSCSI->TargetPortalGroupTag,\r
+ iSCSI->Lun\r
+ );\r
+\r
+ Options = iSCSI->LoginOption;\r
+ CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None");\r
+ CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None");\r
+ if ((Options >> 11) & 0x0001) {\r
+ CatPrint (Str, L"%s,", L"None");\r
+ } else if ((Options >> 12) & 0x0001) {\r
+ CatPrint (Str, L"%s,", L"CHAP_UNI");\r
+ } else {\r
+ CatPrint (Str, L"%s,", L"CHAP_BI");\r
+\r
+ }\r
+\r
+ CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved");\r
+}\r
+\r
+VOID\r
+DevPathHardDrive (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ HARDDRIVE_DEVICE_PATH *Hd;\r
+\r
+ Hd = DevPath;\r
+ switch (Hd->SignatureType) {\r
+ case SIGNATURE_TYPE_MBR:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%08x)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (UINTN) *((UINT32 *) (&(Hd->Signature[0])))\r
+ );\r
+ break;\r
+\r
+ case SIGNATURE_TYPE_GUID:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%g)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (EFI_GUID *) &(Hd->Signature[0])\r
+ );\r
+ break;\r
+\r
+ default:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (UINTN) Hd->MBRType,\r
+ (UINTN) Hd->SignatureType\r
+ );\r
+ break;\r
+ }\r
+}\r
+\r
+VOID\r
+DevPathCDROM (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CDROM_DEVICE_PATH *Cd;\r
+\r
+ Cd = DevPath;\r
+ CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);\r
+}\r
+\r
+VOID\r
+DevPathFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FILEPATH_DEVICE_PATH *Fp;\r
+\r
+ Fp = DevPath;\r
+ CatPrint (Str, L"%s", Fp->PathName);\r
+}\r
+\r
+VOID\r
+DevPathMediaProtocol (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;\r
+\r
+ MediaProt = DevPath;\r
+ CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);\r
+}\r
+\r
+VOID\r
+DevPathFvFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+\r
+ FvFilePath = DevPath;\r
+ CatPrint (Str, L"%g", &FvFilePath->FvFileName);\r
+}\r
+\r
+VOID\r
+DevPathBssBss (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ BBS_BBS_DEVICE_PATH *Bbs;\r
+ CHAR16 *Type;\r
+\r
+ Bbs = DevPath;\r
+ switch (Bbs->DeviceType) {\r
+ case BBS_TYPE_FLOPPY:\r
+ Type = L"Floppy";\r
+ break;\r
+\r
+ case BBS_TYPE_HARDDRIVE:\r
+ Type = L"Harddrive";\r
+ break;\r
+\r
+ case BBS_TYPE_CDROM:\r
+ Type = L"CDROM";\r
+ break;\r
+\r
+ case BBS_TYPE_PCMCIA:\r
+ Type = L"PCMCIA";\r
+ break;\r
+\r
+ case BBS_TYPE_USB:\r
+ Type = L"Usb";\r
+ break;\r
+\r
+ case BBS_TYPE_EMBEDDED_NETWORK:\r
+ Type = L"Net";\r
+ break;\r
+\r
+ case BBS_TYPE_BEV:\r
+ Type = L"BEV";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+ CatPrint (Str, L"Legacy-%s", Type);\r
+}\r
+\r
+VOID\r
+DevPathEndInstance (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L",");\r
+}\r
+\r
+VOID\r
+DevPathNodeUnknown (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L"?");\r
+}\r
+\r
+DEVICE_PATH_STRING_TABLE DevPathTable[] = {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCI_DP,\r
+ DevPathPci,\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCCARD_DP,\r
+ DevPathPccard,\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_MEMMAP_DP,\r
+ DevPathMemMap,\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ DevPathVendor,\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_CONTROLLER_DP,\r
+ DevPathController,\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_DP,\r
+ DevPathAcpi,\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_EXTENDED_DP,\r
+ DevPathExtendedAcpi,\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_ADR_DP,\r
+ DevPathAdrAcpi,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_ATAPI_DP,\r
+ DevPathAtapi,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_SCSI_DP,\r
+ DevPathScsi,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_FIBRECHANNEL_DP,\r
+ DevPathFibre,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_1394_DP,\r
+ DevPath1394,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_DP,\r
+ DevPathUsb,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_WWID_DP,\r
+ DevPathUsbWWID,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_DEVICE_LOGICAL_UNIT_DP,\r
+ DevPathLogicalUnit,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_CLASS_DP,\r
+ DevPathUsbClass,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_SATA_DP,\r
+ DevPathSata,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_I2O_DP,\r
+ DevPathI2O,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_MAC_ADDR_DP,\r
+ DevPathMacAddr,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv4_DP,\r
+ DevPathIPv4,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv6_DP,\r
+ DevPathIPv6,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_INFINIBAND_DP,\r
+ DevPathInfiniBand,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_UART_DP,\r
+ DevPathUart,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_VENDOR_DP,\r
+ DevPathVendor,\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_ISCSI_DP,\r
+ DevPathiSCSI,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_HARDDRIVE_DP,\r
+ DevPathHardDrive,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_CDROM_DP,\r
+ DevPathCDROM,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_VENDOR_DP,\r
+ DevPathVendor,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_FILEPATH_DP,\r
+ DevPathFilePath,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_PROTOCOL_DP,\r
+ DevPathMediaProtocol,\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_PIWG_FW_FILE_DP,\r
+ DevPathFvFilePath,\r
+ BBS_DEVICE_PATH,\r
+ BBS_BBS_DP,\r
+ DevPathBssBss,\r
+ END_DEVICE_PATH_TYPE,\r
+ END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
+ DevPathEndInstance,\r
+ 0,\r
+ 0,\r
+ NULL\r
+};\r
+\r
+\r
+/**\r
+ This function converts an input device structure to a Unicode string.\r
+\r
+ @param DevPath A pointer to the device path structure.\r
+\r
+ @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+DevicePathToStr (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ POOL_PRINT Str;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
+\r
+ UINTN Index;\r
+ UINTN NewSize;\r
+\r
+ EFI_STATUS Status;\r
+ CHAR16 *ToText;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+\r
+ ZeroMem (&Str, sizeof (Str));\r
+\r
+ if (DevPath == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DevPathToText\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ ToText = DevPathToText->ConvertDevicePathToText (\r
+ DevPath,\r
+ FALSE,\r
+ TRUE\r
+ );\r
+ ASSERT (ToText != NULL);\r
+ return ToText;\r
+ }\r
+\r
+ //\r
+ // Unpacked the device path\r
+ //\r
+ DevPath = BdsLibUnpackDevicePath (DevPath);\r
+ ASSERT (DevPath);\r
+\r
+ //\r
+ // Process each device path node\r
+ //\r
+ DevPathNode = DevPath;\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ //\r
+ // Find the handler to dump this device path node\r
+ //\r
+ DumpNode = NULL;\r
+ for (Index = 0; DevPathTable[Index].Function; Index += 1) {\r
+\r
+ if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
+ DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
+ ) {\r
+ DumpNode = DevPathTable[Index].Function;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If not found, use a generic function\r
+ //\r
+ if (!DumpNode) {\r
+ DumpNode = DevPathNodeUnknown;\r
+ }\r
+ //\r
+ // Put a path seperator in if needed\r
+ //\r
+ if (Str.len && DumpNode != DevPathEndInstance) {\r
+ CatPrint (&Str, L"/");\r
+ }\r
+ //\r
+ // Print this node of the device path\r
+ //\r
+ DumpNode (&Str, DevPathNode);\r
+\r
+ //\r
+ // Next device path node\r
+ //\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+ //\r
+ // Shrink pool used for string allocation\r
+ //\r
+ gBS->FreePool (DevPath);\r
+\r
+Done:\r
+ NewSize = (Str.len + 1) * sizeof (CHAR16);\r
+ Str.str = ReallocatePool (Str.str, NewSize, NewSize);\r
+ ASSERT (Str.str != NULL);\r
+ Str.str[Str.len] = 0;\r
+ return Str.str;\r
+}\r
+\r
+\r
+/**\r
+ Function creates a device path data structure that identically matches the\r
+ device path passed in.\r
+\r
+ @param DevPath A pointer to a device path data structure.\r
+\r
+ @return The new copy of DevPath is created to identically match the input.\r
+ @return Otherwise, NULL is returned.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+LibDuplicateDevicePathInstance (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ EFI_DEVICE_PATH_PROTOCOL *Temp;\r
+ UINTN Size;\r
+\r
+ //\r
+ // get the size of an instance from the input\r
+ //\r
+ Temp = DevPath;\r
+ DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+ //\r
+ // Make a copy\r
+ //\r
+ NewDevPath = NULL;\r
+ if (Size) {\r
+ NewDevPath = AllocateZeroPool (Size);\r
+ ASSERT (NewDevPath != NULL);\r
+ }\r
+\r
+ if (NewDevPath) {\r
+ CopyMem (NewDevPath, DevicePathInst, Size);\r
+ }\r
+\r
+ return NewDevPath;\r
+}\r
-/** @file
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BmMachine.h
-
-Abstract:
-
- Boot Manager Machine type
-
-
-
-Revision History
-
-
-**/
-
-#ifndef _BM_MACHINE_H
-#define _BM_MACHINE_H
-
-//
-// NOTE: This is not defined in UEFI spec.
-//
-#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
-
-#endif
+/** @file\r
+ Boot Manager Machine type\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BM_MACHINE_H\r
+#define _BM_MACHINE_H\r
+\r
+//\r
+// NOTE: This is not defined in UEFI spec.\r
+//\r
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"\r
+\r
+#endif\r
#/** @file\r
-# Component name for module GenericBdsLib\r
-#\r
-# FIX ME!\r
-# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
-#\r
-# All rights reserved. This program and the accompanying materials \r
-# are licensed and made available under the terms and conditions of the BSD License \r
-# which accompanies this distribution. The full text of the license may be found at \r
-# http://opensource.org/licenses/bsd-license.php \r
# \r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+# Component name for module GenericBdsLib\r
+# \r
+# Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#\r
+# \r
#**/\r
\r
[Defines]\r
Performance.c\r
BdsConnect.c\r
BdsMisc.c\r
- R8Lib.c\r
BdsConsole.c\r
BdsBoot.c\r
InternalBdsLib.h\r
- R8Lib.h\r
\r
[Sources.Ia32]\r
- Ia32/ClearDr.asm\r
Ia32/BmMachine.h\r
\r
[Sources.X64]\r
- x64/ClearDr.asm\r
x64/BmMachine.h\r
\r
[Sources.IPF]\r
-/** @file
-
-Copyright (c) 2004 - 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BmMachine.h
-
-Abstract:
-
- Boot Manager Machine type
-
-
-
-Revision History
-
-
-**/
-
-#ifndef _BM_MACHINE_H
-#define _BM_MACHINE_H
-
-//@MT:#include "CpuIA32.h"
-
-#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA32.EFI"
-
-#endif
+/** @file\r
+ Boot Manager Machine type\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BM_MACHINE_H\r
+#define _BM_MACHINE_H\r
+\r
+//@MT:#include "CpuIA32.h"\r
+\r
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA32.EFI"\r
+\r
+#endif\r
+++ /dev/null
- title ClearDr.asm
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2004, Intel Corporation
-; All rights reserved. This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; ClearDr.asm
-;
-; Abstract:
-;
-; Clear dr0 dr1 register
-;
-;------------------------------------------------------------------------------
-
- .686
- .MODEL FLAT,C
- .CODE
-
-;------------------------------------------------------------------------------
-; VOID
-; ClearDebugRegisters (
-; VOID
-; )
-;------------------------------------------------------------------------------
-ClearDebugRegisters PROC PUBLIC
- push eax
- xor eax, eax
- mov dr0, eax
- mov dr1, eax
- pop eax
- ret
-ClearDebugRegisters ENDP
-
-END
-
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- InternalBdsLib.h
-
-Abstract:
-
- BDS library definition, include the file and data structure
-
-
-**/
-
-#ifndef _INTERNAL_BDS_LIB_H_
-#define _INTERNAL_BDS_LIB_H_
-
-#include <PiDxe.h>
-
-#include <IndustryStandard/Pci22.h>
-
-#include <Protocol/BlockIo.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/Cpu.h>
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/DebugPort.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/SimpleTextIn.h>
-#include <Protocol/LegacyBios.h>
-#include <Protocol/SimpleTextOut.h>
-#include <Protocol/SimpleNetwork.h>
-#include <Protocol/DevicePathToText.h>
-#include <Protocol/FirmwareVolume2.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/AcpiS3Save.h>
-#include <Protocol/Performance.h>
-#include <Protocol/FirmwareVolumeDispatch.h>
-
-#include <Guid/MemoryTypeInformation.h>
-#include <Guid/FileInfo.h>
-#include <Guid/GlobalVariable.h>
-#include <Guid/PcAnsi.h>
-#include <Guid/ShellFile.h>
-#include <Guid/HobList.h>
-#include <Guid/GenericPlatformVariable.h>
-
-#include <Library/PrintLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/HobLib.h>
-#include <Library/BaseLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/PerformanceLib.h>
-#include <Library/PcdLib.h>
-#include <Library/IfrSupportLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/GenericBdsLib.h>
-#include <Library/TimerLib.h>
-
-#include "BmMachine.h"
-
-#include "R8Lib.h"
-
-#define PERFORMANCE_SIGNATURE EFI_SIGNATURE_32 ('P', 'e', 'r', 'f')
-#define PERF_TOKEN_SIZE 28
-#define PERF_TOKEN_LENGTH (PERF_TOKEN_SIZE - 1)
-#define PERF_PEI_ENTRY_MAX_NUM 50
-
-typedef struct {
- CHAR8 Token[PERF_TOKEN_SIZE];
- UINT32 Duration;
-} PERF_DATA;
-
-typedef struct {
- UINT64 BootToOs;
- UINT64 S3Resume;
- UINT32 S3EntryNum;
- PERF_DATA S3Entry[PERF_PEI_ENTRY_MAX_NUM];
- UINT64 CpuFreq;
- UINT64 BDSRaw;
- UINT32 Count;
- UINT32 Signiture;
-} PERF_HEADER;
-
-VOID
-WriteBootToOsPerformanceData (
- VOID
- );
-
-#endif // _BDS_LIB_H_
+/** @file\r
+ BDS library definition, include the file and data structure\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _INTERNAL_BDS_LIB_H_\r
+#define _INTERNAL_BDS_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/DebugPort.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/AcpiS3Save.h>\r
+#include <Protocol/Performance.h>\r
+#include <Protocol/FirmwareVolumeDispatch.h>\r
+\r
+#include <Guid/MemoryTypeInformation.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/PcAnsi.h>\r
+#include <Guid/ShellFile.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
+#include "BmMachine.h"\r
+\r
+#define PERFORMANCE_SIGNATURE EFI_SIGNATURE_32 ('P', 'e', 'r', 'f')\r
+#define PERF_TOKEN_SIZE 28\r
+#define PERF_TOKEN_LENGTH (PERF_TOKEN_SIZE - 1)\r
+#define PERF_PEI_ENTRY_MAX_NUM 50\r
+\r
+typedef struct {\r
+ CHAR8 Token[PERF_TOKEN_SIZE];\r
+ UINT32 Duration;\r
+} PERF_DATA;\r
+\r
+typedef struct {\r
+ UINT64 BootToOs;\r
+ UINT64 S3Resume;\r
+ UINT32 S3EntryNum;\r
+ PERF_DATA S3Entry[PERF_PEI_ENTRY_MAX_NUM];\r
+ UINT64 CpuFreq;\r
+ UINT64 BDSRaw;\r
+ UINT32 Count;\r
+ UINT32 Signiture;\r
+} PERF_HEADER;\r
+\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+ VOID\r
+ );\r
+\r
+#endif // _BDS_LIB_H_\r
-/** @file
-
-Copyright (c) 2004 - 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BmMachine.h
-
-Abstract:
-
- Boot Manager Machine type
-
-
-
-Revision History
-
-
-**/
-
-#ifndef _BM_MACHINE_H
-#define _BM_MACHINE_H
-
-//@MT:#include "CpuIA64.h"
-
-#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA64.EFI"
-
-#endif
+/** @file\r
+ Boot Manager Machine type\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BM_MACHINE_H\r
+#define _BM_MACHINE_H\r
+\r
+//@MT:#include "CpuIA64.h"\r
+\r
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTIA64.EFI"\r
+\r
+#endif\r
-/** @file
-
-Copyright (c) 2004, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- ShadowRom.c
-
-Abstract:
-
- Shadow all option rom
-
-Revision History
-
-
-**/
-
-//@MT:#include "Tiano.h"
-//@MT:#include "EfiDriverLib.h"
-
-//@MT:#include EFI_PROTOCOL_DEFINITION (LegacyBios)
-
-#include "InternalBdsLib.h"
-
-UINT8 mShadowRomFlag = 0;
-
-VOID
-ShadowAllOptionRom()
-{
- EFI_STATUS Status;
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
- //
- // Rom shadow only do once.
- //
- if (mShadowRomFlag == 0) {
- Status = gBS->LocateProtocol (
- &gEfiLegacyBiosProtocolGuid,
- NULL,
- (VOID **) &LegacyBios
- );
- if (!EFI_ERROR (Status)) {
- LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL);
- }
-
- mShadowRomFlag = 1;
- }
-
- return ;
-}
+/** @file\r
+ Shadow all option rom\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//@MT:#include "Tiano.h"\r
+//@MT:#include "EfiDriverLib.h"\r
+\r
+//@MT:#include EFI_PROTOCOL_DEFINITION (LegacyBios)\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+UINT8 mShadowRomFlag = 0;\r
+\r
+VOID\r
+ShadowAllOptionRom()\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ //\r
+ // Rom shadow only do once.\r
+ //\r
+ if (mShadowRomFlag == 0) {\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL);\r
+ }\r
+\r
+ mShadowRomFlag = 1;\r
+ }\r
+\r
+ return ;\r
+}\r
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Performance.c
-
-Abstract:
-
- This file include the file which can help to get the system
- performance, all the function will only include if the performance
- switch is set.
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-STATIC PERF_HEADER mPerfHeader;
-STATIC PERF_DATA mPerfData;
-
-STATIC
-VOID
-GetShortPdbFileName (
- CHAR8 *PdbFileName,
- CHAR8 *GaugeString
- )
-/*++
-
-Routine Description:
-
-Arguments:
-
-Returns:
-
---*/
-{
- UINTN Index;
- UINTN Index1;
- UINTN StartIndex;
- UINTN EndIndex;
-
- if (PdbFileName == NULL) {
- AsciiStrCpy (GaugeString, " ");
- } else {
- StartIndex = 0;
- for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
- ;
-
- for (Index = 0; PdbFileName[Index] != 0; Index++) {
- if (PdbFileName[Index] == '\\') {
- StartIndex = Index + 1;
- }
-
- if (PdbFileName[Index] == '.') {
- EndIndex = Index;
- }
- }
-
- Index1 = 0;
- for (Index = StartIndex; Index < EndIndex; Index++) {
- GaugeString[Index1] = PdbFileName[Index];
- Index1++;
- if (Index1 == PERF_TOKEN_LENGTH - 1) {
- break;
- }
- }
-
- GaugeString[Index1] = 0;
- }
-
- return ;
-}
-
-STATIC
-VOID
-GetNameFromHandle (
- IN EFI_HANDLE Handle,
- OUT CHAR8 *GaugeString
- )
-{
- EFI_STATUS Status;
- EFI_LOADED_IMAGE_PROTOCOL *Image;
- CHAR8 *PdbFileName;
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
-
- AsciiStrCpy (GaugeString, " ");
-
- //
- // Get handle name from image protocol
- //
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **) &Image
- );
-
- if (EFI_ERROR (Status)) {
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiDriverBindingProtocolGuid,
- (VOID **) &DriverBinding,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return ;
- }
- //
- // Get handle name from image protocol
- //
- Status = gBS->HandleProtocol (
- DriverBinding->ImageHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **) &Image
- );
- }
-
- PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
-
- if (PdbFileName != NULL) {
- GetShortPdbFileName (PdbFileName, GaugeString);
- }
-
- return ;
-}
-
-VOID
-WriteBootToOsPerformanceData (
- VOID
- )
-/*++
-
-Routine Description:
-
- Allocates a block of memory and writes performance data of booting to OS into it.
-
-Arguments:
-
- None
-
-Returns:
-
- None
-
---*/
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;
- UINT32 AcpiLowMemoryLength;
- UINT32 LimitCount;
- EFI_HANDLE *Handles;
- UINTN NoHandles;
- CHAR8 GaugeString[PERF_TOKEN_LENGTH];
- UINT8 *Ptr;
- UINT32 Index;
- UINT64 Ticker;
- UINT64 Freq;
- UINT32 Duration;
- UINTN LogEntryKey;
- CONST VOID *Handle;
- CONST CHAR8 *Token;
- CONST CHAR8 *Module;
- UINT64 StartTicker;
- UINT64 EndTicker;
- UINT64 StartValue;
- UINT64 EndValue;
- BOOLEAN CountUp;
-
- //
- // Retrive time stamp count as early as possilbe
- //
- Ticker = GetPerformanceCounter ();
-
- Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
-
- Freq = DivU64x32 (Freq, 1000);
-
- mPerfHeader.CpuFreq = Freq;
-
- //
- // Record BDS raw performance data
- //
- if (EndValue >= StartValue) {
- mPerfHeader.BDSRaw = Ticker - StartValue;
- CountUp = TRUE;
- } else {
- mPerfHeader.BDSRaw = StartValue - Ticker;
- CountUp = FALSE;
- }
-
- AcpiLowMemoryLength = 0x2000;
-
- //
- // Allocate a block of memory that contain performance data to OS
- //
- Status = gBS->AllocatePages (
- AllocateAnyPages,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
- &AcpiLowMemoryBase
- );
- if (EFI_ERROR (Status)) {
- return ;
- }
-
-
- Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));
- LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
-
- //
- // Put Detailed performance data into memory
- //
- Handles = NULL;
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &NoHandles,
- &Handles
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePages (AcpiLowMemoryBase, 1);
- return ;
- }
- //
- // Get DXE drivers performance
- //
- for (Index = 0; Index < NoHandles; Index++) {
- Ticker = 0;
- LogEntryKey = 0;
- while ((LogEntryKey = GetPerformanceMeasurement (
- LogEntryKey,
- &Handle,
- &Token,
- &Module,
- &StartTicker,
- &EndTicker)) != 0) {
- if ((Handle == Handles[Index]) && (EndTicker != 0)) {
- Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
- }
- }
-
- Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
-
- if (Duration > 0) {
-
- GetNameFromHandle (Handles[Index], GaugeString);
-
- AsciiStrCpy (mPerfData.Token, GaugeString);
- mPerfData.Duration = Duration;
-
- CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
- Ptr += sizeof (PERF_DATA);
-
- mPerfHeader.Count++;
- if (mPerfHeader.Count == LimitCount) {
- goto Done;
- }
- }
- }
-
- FreePool (Handles);
-
- //
- // Get inserted performance data
- //
- LogEntryKey = 0;
- while ((LogEntryKey = GetPerformanceMeasurement (
- LogEntryKey,
- &Handle,
- &Token,
- &Module,
- &StartTicker,
- &EndTicker)) != 0) {
- if (Handle == NULL && EndTicker != 0) {
-
- ZeroMem (&mPerfData, sizeof (PERF_DATA));
-
- AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
- Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
-
- mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
-
- CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
- Ptr += sizeof (PERF_DATA);
-
- mPerfHeader.Count++;
- if (mPerfHeader.Count == LimitCount) {
- goto Done;
- }
- }
- }
-
-Done:
-
- mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
-
- //
- // Put performance data to memory
- //
- CopyMem (
- (UINTN *) (UINTN) AcpiLowMemoryBase,
- &mPerfHeader,
- sizeof (PERF_HEADER)
- );
-
- gRT->SetVariable (
- L"PerfDataMemAddr",
- &gEfiGenericPlatformVariableGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof (EFI_PHYSICAL_ADDRESS),
- &AcpiLowMemoryBase
- );
-
- return ;
-}
+/** @file\r
+ This file include the file which can help to get the system\r
+ performance, all the function will only include if the performance\r
+ switch is set.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+STATIC PERF_HEADER mPerfHeader;\r
+STATIC PERF_DATA mPerfData;\r
+\r
+STATIC\r
+VOID\r
+GetShortPdbFileName (\r
+ CHAR8 *PdbFileName,\r
+ CHAR8 *GaugeString\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINTN StartIndex;\r
+ UINTN EndIndex;\r
+\r
+ if (PdbFileName == NULL) {\r
+ AsciiStrCpy (GaugeString, " ");\r
+ } else {\r
+ StartIndex = 0;\r
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
+ ;\r
+\r
+ for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
+ if (PdbFileName[Index] == '\\') {\r
+ StartIndex = Index + 1;\r
+ }\r
+\r
+ if (PdbFileName[Index] == '.') {\r
+ EndIndex = Index;\r
+ }\r
+ }\r
+\r
+ Index1 = 0;\r
+ for (Index = StartIndex; Index < EndIndex; Index++) {\r
+ GaugeString[Index1] = PdbFileName[Index];\r
+ Index1++;\r
+ if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ GaugeString[Index1] = 0;\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+STATIC\r
+VOID\r
+GetNameFromHandle (\r
+ IN EFI_HANDLE Handle,\r
+ OUT CHAR8 *GaugeString\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *Image;\r
+ CHAR8 *PdbFileName;\r
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+\r
+ AsciiStrCpy (GaugeString, " ");\r
+\r
+ //\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &Image\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ (VOID **) &DriverBinding,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+ //\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverBinding->ImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &Image\r
+ );\r
+ }\r
+\r
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
+\r
+ if (PdbFileName != NULL) {\r
+ GetShortPdbFileName (PdbFileName, GaugeString);\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Allocates a block of memory and writes performance data of booting to OS into it.\r
+\r
+Arguments:\r
+ \r
+ None\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;\r
+ UINT32 AcpiLowMemoryLength;\r
+ UINT32 LimitCount;\r
+ EFI_HANDLE *Handles;\r
+ UINTN NoHandles;\r
+ CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
+ UINT8 *Ptr;\r
+ UINT32 Index;\r
+ UINT64 Ticker;\r
+ UINT64 Freq;\r
+ UINT32 Duration;\r
+ UINTN LogEntryKey;\r
+ CONST VOID *Handle;\r
+ CONST CHAR8 *Token;\r
+ CONST CHAR8 *Module;\r
+ UINT64 StartTicker;\r
+ UINT64 EndTicker;\r
+ UINT64 StartValue;\r
+ UINT64 EndValue;\r
+ BOOLEAN CountUp;\r
+\r
+ //\r
+ // Retrive time stamp count as early as possilbe\r
+ //\r
+ Ticker = GetPerformanceCounter ();\r
+\r
+ Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
+ \r
+ Freq = DivU64x32 (Freq, 1000);\r
+\r
+ mPerfHeader.CpuFreq = Freq;\r
+\r
+ //\r
+ // Record BDS raw performance data\r
+ //\r
+ if (EndValue >= StartValue) {\r
+ mPerfHeader.BDSRaw = Ticker - StartValue;\r
+ CountUp = TRUE;\r
+ } else {\r
+ mPerfHeader.BDSRaw = StartValue - Ticker;\r
+ CountUp = FALSE;\r
+ }\r
+\r
+ AcpiLowMemoryLength = 0x2000;\r
+\r
+ //\r
+ // Allocate a block of memory that contain performance data to OS\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiACPIReclaimMemory,\r
+ EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
+ &AcpiLowMemoryBase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+\r
+ Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));\r
+ LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
+\r
+ //\r
+ // Put Detailed performance data into memory\r
+ //\r
+ Handles = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &NoHandles,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (AcpiLowMemoryBase, 1);\r
+ return ;\r
+ }\r
+ //\r
+ // Get DXE drivers performance\r
+ //\r
+ for (Index = 0; Index < NoHandles; Index++) {\r
+ Ticker = 0;\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Handle,\r
+ &Token,\r
+ &Module,\r
+ &StartTicker,\r
+ &EndTicker)) != 0) {\r
+ if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
+ Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+ }\r
+ }\r
+\r
+ Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+ if (Duration > 0) {\r
+\r
+ GetNameFromHandle (Handles[Index], GaugeString);\r
+\r
+ AsciiStrCpy (mPerfData.Token, GaugeString);\r
+ mPerfData.Duration = Duration;\r
+\r
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+ Ptr += sizeof (PERF_DATA);\r
+\r
+ mPerfHeader.Count++;\r
+ if (mPerfHeader.Count == LimitCount) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (Handles);\r
+\r
+ //\r
+ // Get inserted performance data\r
+ //\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Handle,\r
+ &Token,\r
+ &Module,\r
+ &StartTicker,\r
+ &EndTicker)) != 0) {\r
+ if (Handle == NULL && EndTicker != 0) {\r
+\r
+ ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
+\r
+ AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
+ Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+\r
+ mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+ Ptr += sizeof (PERF_DATA);\r
+\r
+ mPerfHeader.Count++;\r
+ if (mPerfHeader.Count == LimitCount) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+\r
+ mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
+\r
+ //\r
+ // Put performance data to memory\r
+ //\r
+ CopyMem (\r
+ (UINTN *) (UINTN) AcpiLowMemoryBase,\r
+ &mPerfHeader,\r
+ sizeof (PERF_HEADER)\r
+ );\r
+\r
+ gRT->SetVariable (\r
+ L"PerfDataMemAddr",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (EFI_PHYSICAL_ADDRESS),\r
+ &AcpiLowMemoryBase\r
+ );\r
+\r
+ return ;\r
+}\r
+++ /dev/null
-/**@file
- Copyright (c) 2007, Intel Corporation
-
- All rights reserved. This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-/**
- Get current boot mode.
-
- @param HobStart Start pointer of hob list
- @param BootMode Current boot mode recorded in PHIT hob
-
- @retval EFI_NOT_FOUND Invalid hob header
- @retval EFI_SUCCESS Boot mode found
-
-**/
-EFI_STATUS
-R8_GetHobBootMode (
- IN VOID *HobStart,
- OUT EFI_BOOT_MODE *BootMode
- )
-{
- //
- // Porting Guide:
- // This library interface is simply obsolete.
- // Include the source code to user code.
- // In fact, since EFI_HANDOFF_HOB must be the first Hob,
- // the following code can retrieve boot mode.
- //
- // EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
- //
- // HandOffHob = GetHobList ();
- // ASSERT (HandOffHob->Header.HobType == EFI_HOB_TYPE_HANDOFF);
- //
- // BootMode = HandOffHob->BootMode;
- //
- EFI_PEI_HOB_POINTERS Hob;
-
- Hob.Raw = HobStart;
- if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {
- return EFI_NOT_FOUND;
- }
-
- *BootMode = Hob.HandoffInformationTable->BootMode;
- return EFI_SUCCESS;
-}
-
-
-
-
-/**
- Get the next guid hob.
-
- @param HobStart A pointer to the start hob.
- @param Guid A pointer to a guid.
- @param Buffer A pointer to the buffer.
- @param BufferSize Buffer size.
-
- @retval EFI_NOT_FOUND Next Guid hob not found
- @retval EFI_SUCCESS Next Guid hob found and data for this Guid got
- @retval EFI_INVALID_PARAMETER invalid parameter
-
-**/
-EFI_STATUS
-R8_GetNextGuidHob (
- IN OUT VOID **HobStart,
- IN EFI_GUID * Guid,
- OUT VOID **Buffer,
- OUT UINTN *BufferSize OPTIONAL
- )
-{
- //
- // Porting Guide:
- // This library interface is changed substantially with R9 counerpart GetNextGuidHob ().
- // 1. R9 GetNextGuidHob has two parameters and returns the matched GUID HOB from the StartHob.
- // 2. R9 GetNextGuidHob does not strip the HOB header, so caller is required to apply
- // GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () to extract the data section and its
- // size info respectively.
- // 3. this function does not skip the starting HOB pointer unconditionally:
- // it returns HobStart back if HobStart itself meets the requirement;
- // caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
- //
- EFI_PEI_HOB_POINTERS GuidHob;
-
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- GuidHob.Raw = GetNextGuidHob (Guid, *HobStart);
- if (GuidHob.Raw == NULL) {
- return EFI_NOT_FOUND;
- }
-
- *Buffer = GET_GUID_HOB_DATA (GuidHob.Guid);
- if (BufferSize != NULL) {
- *BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
- }
-
- *HobStart = GET_NEXT_HOB (GuidHob);
-
- return EFI_SUCCESS;
-}
-
-
+++ /dev/null
-/**@file
- Copyright (c) 2007, Intel Corporation
-
- All rights reserved. This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-
-**/
-
-
-
-/**
- Get current boot mode.
-
- @param HobStart Start pointer of hob list
- @param BootMode Current boot mode recorded in PHIT hob
-
- @retval EFI_NOT_FOUND Invalid hob header
- @retval EFI_SUCCESS Boot mode found
-
-**/
-EFI_STATUS
-R8_GetHobBootMode (
- IN VOID *HobStart,
- OUT EFI_BOOT_MODE *BootMode
- )
-;
-
-
-
-
-/**
- Get the next guid hob.
-
- @param HobStart A pointer to the start hob.
- @param Guid A pointer to a guid.
- @param Buffer A pointer to the buffer.
- @param BufferSize Buffer size.
-
- @retval EFI_NOT_FOUND Next Guid hob not found
- @retval EFI_SUCCESS Next Guid hob found and data for this Guid got
- @retval EFI_INVALID_PARAMETER invalid parameter
-
-**/
-EFI_STATUS
-R8_GetNextGuidHob (
- IN OUT VOID **HobStart,
- IN EFI_GUID * Guid,
- OUT VOID **Buffer,
- OUT UINTN *BufferSize OPTIONAL
- )
-;
-
-
-/** @file
-
-Copyright (c) 2005 - 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- BmMachine.h
-
-Abstract:
-
- Boot Manager Machine type
-
-
-
-Revision History
-
-
-**/
-
-#ifndef _BM_MACHINE_H
-#define _BM_MACHINE_H
-
-//@MT:#include "CpuIA32.h"
-
-#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTX64.EFI"
-
-#endif
+/** @file\r
+ Boot Manager Machine type\r
+\r
+Copyright (c) 2005 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BM_MACHINE_H\r
+#define _BM_MACHINE_H\r
+\r
+//@MT:#include "CpuIA32.h"\r
+\r
+#define DEFAULT_REMOVABLE_FILE_NAME L"\\EFI\\BOOT\\BOOTX64.EFI"\r
+\r
+#endif\r
+++ /dev/null
- title ClearDr.asm
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2005, Intel Corporation
-; All rights reserved. This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
-; http://opensource.org/licenses/bsd-license.php
-;
-; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-;
-; Module Name:
-;
-; ClearDr.asm
-;
-; Abstract:
-;
-; Clear dr0 dr1 register
-;
-;------------------------------------------------------------------------------
-
-text SEGMENT
-
-;------------------------------------------------------------------------------
-; VOID
-; ClearDebugRegisters (
-; VOID
-; )
-;------------------------------------------------------------------------------
-ClearDebugRegisters PROC PUBLIC
- push rax
- xor rax, rax
- mov dr0, rax
- mov dr1, rax
- pop rax
- ret
-ClearDebugRegisters ENDP
-
-END
-