/** @file\r
Library functions which relates with booting.\r
\r
-Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
-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
+Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "InternalBm.h"\r
\r
-#define VENDOR_IDENTIFICATION_OFFSET 3\r
-#define VENDOR_IDENTIFICATION_LENGTH 8\r
-#define PRODUCT_IDENTIFICATION_OFFSET 11\r
-#define PRODUCT_IDENTIFICATION_LENGTH 16\r
-\r
-CONST UINT16 mBmUsbLangId = 0x0409; // English\r
-CHAR16 mBmUefiPrefix[] = L"UEFI ";\r
+EFI_RAM_DISK_PROTOCOL *mRamDisk = NULL;\r
\r
EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mBmRefreshLegacyBootOption = NULL;\r
EFI_BOOT_MANAGER_LEGACY_BOOT mBmLegacyBoot = NULL;\r
\r
-LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);\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
EFI_GUID mBmHardDriveBootVariableGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x08, 0xe2, 0x0e, 0x90, 0x6c, 0xb6, 0xde } };\r
EFI_GUID mBmAutoCreateBootOptionGuid = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };\r
\r
+/**\r
+\r
+ End Perf entry of BDS\r
+\r
+ @param Event The triggered event.\r
+ @param Context Context for this event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BmEndOfBdsPerfCode (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Record the performance data for End of BDS\r
+ //\r
+ PERF_CROSSMODULE_END("BDS");\r
+\r
+ return ;\r
+}\r
+\r
/**\r
The function registers the legacy boot support capabilities.\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 AcpiFloppyBoot If given device path contains ACPI_DEVICE_PATH type device path node\r
- which HID is floppy device.\r
- @retval MessageAtapiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_ATAPI_DP.\r
- @retval MessageSataBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_SATA_DP.\r
- @retval MessageScsiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_SCSI_DP.\r
- @retval MessageUsbBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_USB_DP.\r
- @retval MessageNetworkBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,\r
- MSG_IPv4_DP or MSG_IPv6_DP.\r
- @retval MessageHttpBoot If given device path contains MESSAGING_DEVICE_PATH type device path node\r
- and its last device path node's subtype is MSG_URI_DP.\r
- @retval UnsupportedBoot If tiven device path doesn't match the above condition, it's not supported.\r
-\r
-**/\r
-BM_BOOT_TYPE\r
-BmDevicePathType (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *Node;\r
- EFI_DEVICE_PATH_PROTOCOL *NextNode;\r
-\r
- ASSERT (DevicePath != NULL);\r
-\r
- for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {\r
- switch (DevicePathType (Node)) {\r
-\r
- case ACPI_DEVICE_PATH:\r
- if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {\r
- return BmAcpiFloppyBoot;\r
- }\r
- break;\r
-\r
- case HARDWARE_DEVICE_PATH:\r
- if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {\r
- return BmHardwareDeviceBoot;\r
- }\r
- break;\r
-\r
- case MESSAGING_DEVICE_PATH:\r
- //\r
- // Skip LUN device node\r
- //\r
- NextNode = Node;\r
- do {\r
- NextNode = NextDevicePathNode (NextNode);\r
- } while (\r
- (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)\r
- );\r
-\r
- //\r
- // If the device path not only point to driver device, it is not a messaging device path,\r
- //\r
- if (!IsDevicePathEndType (NextNode)) {\r
- continue;\r
- }\r
-\r
- switch (DevicePathSubType (Node)) {\r
- case MSG_ATAPI_DP:\r
- return BmMessageAtapiBoot;\r
- break;\r
-\r
- case MSG_SATA_DP:\r
- return BmMessageSataBoot;\r
- break;\r
-\r
- case MSG_USB_DP:\r
- return BmMessageUsbBoot;\r
- break;\r
-\r
- case MSG_SCSI_DP:\r
- return BmMessageScsiBoot;\r
- break;\r
-\r
- case MSG_MAC_ADDR_DP:\r
- case MSG_VLAN_DP:\r
- case MSG_IPv4_DP:\r
- case MSG_IPv6_DP:\r
- return BmMessageNetworkBoot;\r
- break;\r
-\r
- case MSG_URI_DP:\r
- return BmMessageHttpBoot;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- return BmMiscBoot;\r
-}\r
-\r
/**\r
Find the boot option in the NV storage and return the option number.\r
\r
EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
UINTN BootOptionCount;\r
UINTN Index;\r
- \r
+\r
OptionNumber = LoadOptionNumberUnassigned;\r
\r
//\r
}\r
\r
/**\r
- Get the file buffer using a Memory Mapped Device Path.\r
-\r
+ Return the correct FV file path.\r
FV address may change across reboot. This routine promises the FV file device path is right.\r
\r
@param FilePath The Memory Mapped Device Path to get the file buffer.\r
- @param FullPath Receive the updated FV Device Path pointint to the file.\r
- @param FileSize Receive the file buffer size.\r
\r
- @return The file buffer.\r
+ @return The updated FV Device Path pointint to the file.\r
**/\r
-VOID *\r
-BmGetFileBufferByFvFilePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmAdjustFvFilePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
)\r
{\r
EFI_STATUS Status;\r
EFI_DEVICE_PATH_PROTOCOL *FvFileNode;\r
EFI_HANDLE FvHandle;\r
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
- UINT32 AuthenticationStatus;\r
UINTN FvHandleCount;\r
EFI_HANDLE *FvHandles;\r
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
- VOID *FileBuffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullPath;\r
\r
//\r
// Get the file buffer by using the exactly FilePath.\r
FvFileNode = FilePath;\r
Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);\r
if (!EFI_ERROR (Status)) {\r
- FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer != NULL) {\r
- *FullPath = DuplicateDevicePath (FilePath);\r
- }\r
- return FileBuffer;\r
+ return DuplicateDevicePath (FilePath);\r
}\r
\r
//\r
(VOID **) &LoadedImage\r
);\r
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);\r
- FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
+ FullPath = BmAdjustFvFilePath (NewDevicePath);\r
FreePool (NewDevicePath);\r
-\r
- if (FileBuffer != NULL) {\r
- return FileBuffer;\r
+ if (FullPath != NULL) {\r
+ return FullPath;\r
}\r
\r
//\r
&FvHandleCount,\r
&FvHandles\r
);\r
- for (Index = 0; (Index < FvHandleCount) && (FileBuffer == NULL); Index++) {\r
+ for (Index = 0; Index < FvHandleCount; Index++) {\r
if (FvHandles[Index] == LoadedImage->DeviceHandle) {\r
//\r
- // Skip current FV\r
+ // Skip current FV, it was handed in first step.\r
//\r
continue;\r
}\r
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);\r
- FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
+ FullPath = BmAdjustFvFilePath (NewDevicePath);\r
FreePool (NewDevicePath);\r
+ if (FullPath != NULL) {\r
+ break;\r
+ }\r
}\r
- \r
+\r
if (FvHandles != NULL) {\r
FreePool (FvHandles);\r
}\r
- return FileBuffer;\r
+ return FullPath;\r
}\r
\r
/**\r
Check if it's a Device Path pointing to FV file.\r
- \r
+\r
The function doesn't garentee the device path points to existing FV file.\r
\r
@param DevicePath Input device path.\r
return TRUE;\r
}\r
\r
-/**\r
- Eliminate the extra spaces in the Str to one space.\r
-\r
- @param Str Input string info.\r
-**/\r
-VOID\r
-BmEliminateExtraSpaces (\r
- IN CHAR16 *Str\r
- )\r
-{\r
- UINTN Index;\r
- UINTN ActualIndex;\r
-\r
- for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {\r
- if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {\r
- Str[ActualIndex++] = Str[Index];\r
- }\r
- }\r
- Str[ActualIndex] = L'\0';\r
-}\r
-\r
-/**\r
- Try to get the controller's ATA/ATAPI description.\r
-\r
- @param Handle Controller handle.\r
-\r
- @return The description string.\r
-**/\r
-CHAR16 *\r
-BmGetDescriptionFromDiskInfo (\r
- IN EFI_HANDLE Handle\r
- )\r
-{\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- EFI_DISK_INFO_PROTOCOL *DiskInfo;\r
- UINT32 BufferSize;\r
- EFI_ATAPI_IDENTIFY_DATA IdentifyData;\r
- EFI_SCSI_INQUIRY_DATA InquiryData;\r
- CHAR16 *Description;\r
- UINTN Length;\r
- CONST UINTN ModelNameLength = 40;\r
- CONST UINTN SerialNumberLength = 20;\r
- CHAR8 *StrPtr;\r
- UINT8 Temp;\r
-\r
- Description = NULL;\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDiskInfoProtocolGuid,\r
- (VOID **) &DiskInfo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || \r
- CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
- BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA);\r
- Status = DiskInfo->Identify (\r
- DiskInfo,\r
- &IdentifyData,\r
- &BufferSize\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));\r
- ASSERT (Description != NULL);\r
- for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {\r
- Description[Index] = (CHAR16) IdentifyData.ModelName[Index + 1];\r
- Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];\r
- }\r
-\r
- Length = Index;\r
- Description[Length++] = L' ';\r
-\r
- for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {\r
- Description[Length + Index] = (CHAR16) IdentifyData.SerialNo[Index + 1];\r
- Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];\r
- }\r
- Length += Index;\r
- Description[Length++] = L'\0';\r
- ASSERT (Length == ModelNameLength + SerialNumberLength + 2);\r
-\r
- BmEliminateExtraSpaces (Description);\r
- }\r
- } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
- BufferSize = sizeof (EFI_SCSI_INQUIRY_DATA);\r
- Status = DiskInfo->Inquiry (\r
- DiskInfo,\r
- &InquiryData,\r
- &BufferSize\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));\r
- ASSERT (Description != NULL);\r
-\r
- //\r
- // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification\r
- // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, \r
- // Here combine the vendor identification and product identification to the description.\r
- //\r
- StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);\r
- Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];\r
- StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';\r
- AsciiStrToUnicodeStr (StrPtr, Description);\r
- StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;\r
-\r
- //\r
- // Add one space at the middle of vendor information and product information.\r
- //\r
- Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';\r
-\r
- StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);\r
- StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';\r
- AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);\r
-\r
- BmEliminateExtraSpaces (Description);\r
- }\r
- }\r
-\r
- return Description;\r
-}\r
-\r
-/**\r
- Try to get the controller's USB description.\r
-\r
- @param Handle Controller handle.\r
-\r
- @return The description string.\r
-**/\r
-CHAR16 *\r
-BmGetUsbDescription (\r
- IN EFI_HANDLE Handle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- CHAR16 NullChar;\r
- CHAR16 *Manufacturer;\r
- CHAR16 *Product;\r
- CHAR16 *SerialNumber;\r
- CHAR16 *Description;\r
- EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
- UINTN DescMaxSize;\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- NullChar = L'\0';\r
-\r
- Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- Status = UsbIo->UsbGetStringDescriptor (\r
- UsbIo,\r
- mBmUsbLangId,\r
- DevDesc.StrManufacturer,\r
- &Manufacturer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Manufacturer = &NullChar;\r
- }\r
- \r
- Status = UsbIo->UsbGetStringDescriptor (\r
- UsbIo,\r
- mBmUsbLangId,\r
- DevDesc.StrProduct,\r
- &Product\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Product = &NullChar;\r
- }\r
- \r
- Status = UsbIo->UsbGetStringDescriptor (\r
- UsbIo,\r
- mBmUsbLangId,\r
- DevDesc.StrSerialNumber,\r
- &SerialNumber\r
- );\r
- if (EFI_ERROR (Status)) {\r
- SerialNumber = &NullChar;\r
- }\r
-\r
- if ((Manufacturer == &NullChar) &&\r
- (Product == &NullChar) &&\r
- (SerialNumber == &NullChar)\r
- ) {\r
- return NULL;\r
- }\r
-\r
- DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);\r
- Description = AllocateZeroPool (DescMaxSize);\r
- ASSERT (Description != NULL);\r
- StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);\r
- StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
- StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product); \r
- StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
- StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber);\r
-\r
- if (Manufacturer != &NullChar) {\r
- FreePool (Manufacturer);\r
- }\r
- if (Product != &NullChar) {\r
- FreePool (Product);\r
- }\r
- if (SerialNumber != &NullChar) {\r
- FreePool (SerialNumber);\r
- }\r
-\r
- BmEliminateExtraSpaces (Description);\r
-\r
- return Description;\r
-}\r
-\r
-/**\r
- Return the boot description for the controller based on the type.\r
-\r
- @param Handle Controller handle.\r
-\r
- @return The description string.\r
-**/\r
-CHAR16 *\r
-BmGetMiscDescription (\r
- IN EFI_HANDLE Handle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *Description;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
-\r
- switch (BmDevicePathType (DevicePathFromHandle (Handle))) {\r
- case BmAcpiFloppyBoot:\r
- Description = L"Floppy";\r
- break;\r
-\r
- case BmMessageAtapiBoot:\r
- case BmMessageSataBoot:\r
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
- ASSERT_EFI_ERROR (Status);\r
- //\r
- // Assume a removable SATA device should be the DVD/CD device\r
- //\r
- Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";\r
- break;\r
-\r
- case BmMessageUsbBoot:\r
- Description = L"USB Device";\r
- break;\r
-\r
- case BmMessageScsiBoot:\r
- Description = L"SCSI Device";\r
- break;\r
-\r
- case BmHardwareDeviceBoot:\r
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
- if (!EFI_ERROR (Status)) {\r
- Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";\r
- } else {\r
- Description = L"Misc Device";\r
- }\r
- break;\r
-\r
- case BmMessageNetworkBoot:\r
- Description = L"Network";\r
- break;\r
-\r
- case BmMessageHttpBoot:\r
- Description = L"Http";\r
- break;\r
-\r
- default:\r
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs);\r
- if (!EFI_ERROR (Status)) {\r
- Description = L"Non-Block Boot Device";\r
- } else {\r
- Description = L"Misc Device";\r
- }\r
- break;\r
- }\r
-\r
- return AllocateCopyPool (StrSize (Description), Description);\r
-}\r
-\r
-/**\r
- Register the platform provided boot description handler.\r
-\r
- @param Handler The platform provided boot description handler\r
-\r
- @retval EFI_SUCCESS The handler was registered successfully.\r
- @retval EFI_ALREADY_STARTED The handler was already registered.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiBootManagerRegisterBootDescriptionHandler (\r
- IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- BM_BOOT_DESCRIPTION_ENTRY *Entry;\r
-\r
- for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
- ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
- ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
- ) {\r
- Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
- if (Entry->Handler == Handler) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
- }\r
-\r
- Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));\r
- if (Entry == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;\r
- Entry->Handler = Handler;\r
- InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {\r
- BmGetUsbDescription,\r
- BmGetDescriptionFromDiskInfo,\r
- BmGetMiscDescription\r
-};\r
-\r
-/**\r
- Return the boot description for the controller.\r
-\r
- @param Handle Controller handle.\r
-\r
- @return The description string.\r
-**/\r
-CHAR16 *\r
-BmGetBootDescription (\r
- IN EFI_HANDLE Handle\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- BM_BOOT_DESCRIPTION_ENTRY *Entry;\r
- CHAR16 *Description;\r
- CHAR16 *DefaultDescription;\r
- CHAR16 *Temp;\r
- UINTN Index;\r
-\r
- //\r
- // Firstly get the default boot description\r
- //\r
- DefaultDescription = NULL;\r
- for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof (mBmBootDescriptionHandlers[0]); Index++) {\r
- DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle);\r
- if (DefaultDescription != NULL) {\r
- //\r
- // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
- // ONLY for core provided boot description handler.\r
- //\r
- Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); \r
- ASSERT (Temp != NULL);\r
- StrCpyS ( Temp, \r
- (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
- mBmUefiPrefix\r
- );\r
- StrCatS ( Temp, \r
- (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
- DefaultDescription\r
- );\r
- FreePool (DefaultDescription);\r
- DefaultDescription = Temp;\r
- break;\r
- }\r
- }\r
- ASSERT (DefaultDescription != NULL);\r
-\r
- //\r
- // Secondly query platform for the better boot description\r
- //\r
- for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
- ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
- ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
- ) {\r
- Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
- Description = Entry->Handler (Handle, DefaultDescription);\r
- if (Description != NULL) {\r
- FreePool (DefaultDescription);\r
- return Description;\r
- }\r
- }\r
-\r
- return DefaultDescription;\r
-}\r
-\r
/**\r
Check whether a USB device match the specified USB WWID device path. This\r
function follows "Load Option Processing" behavior in UEFI specification.\r
}\r
\r
/**\r
- Find a USB device which match the specified short-form device path start with \r
+ Find a USB device which match the specified short-form device path start with\r
USB Class or USB WWID device path. If ParentDevicePath is NULL, this function\r
will search in all USB devices of the platform. If ParentDevicePath is not NULL,\r
this function will only search in its child devices.\r
\r
@param DevicePath The device path that contains USB Class or USB WWID device path.\r
- @param ParentDevicePathSize The length of the device path before the USB Class or \r
+ @param ParentDevicePathSize The length of the device path before the USB Class or\r
USB WWID device path.\r
@param UsbIoHandleCount A pointer to the count of the returned USB IO handles.\r
\r
UINTN Index;\r
BOOLEAN Matched;\r
\r
- ASSERT (UsbIoHandleCount != NULL); \r
+ ASSERT (UsbIoHandleCount != NULL);\r
\r
//\r
// Get all UsbIo Handles.\r
\r
@param FilePath The device path pointing to a load option.\r
It could be a short-form device path.\r
- @param FullPath Return the full device path of the load option after\r
- short-form device path expanding.\r
- Caller is responsible to free it.\r
- @param FileSize Return the load option size.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
@param ShortformNode Pointer to the USB short-form device path node in the FilePath buffer.\r
\r
- @return The load option buffer. Caller is responsible to free the memory.\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
**/\r
-VOID *\r
+EFI_DEVICE_PATH_PROTOCOL *\r
BmExpandUsbDevicePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode\r
)\r
{\r
UINTN ParentDevicePathSize;\r
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *NextFullPath;\r
EFI_HANDLE *Handles;\r
UINTN HandleCount;\r
UINTN Index;\r
- VOID *FileBuffer;\r
+ BOOLEAN GetNext;\r
\r
+ NextFullPath = NULL;\r
+ GetNext = (BOOLEAN)(FullPath == NULL);\r
ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) FilePath;\r
RemainingDevicePath = NextDevicePathNode (ShortformNode);\r
- FileBuffer = NULL;\r
Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);\r
\r
- for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {\r
- FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);\r
- FileBuffer = BmGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
- FreePool (FullDevicePath);\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ FilePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);\r
+ if (FilePath == NULL) {\r
+ //\r
+ // Out of memory.\r
+ //\r
+ continue;\r
+ }\r
+ NextFullPath = BmGetNextLoadOptionDevicePath (FilePath, NULL);\r
+ FreePool (FilePath);\r
+ if (NextFullPath == NULL) {\r
+ //\r
+ // No BlockIo or SimpleFileSystem under FilePath.\r
+ //\r
+ continue;\r
+ }\r
+ if (GetNext) {\r
+ break;\r
+ } else {\r
+ GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);\r
+ FreePool (NextFullPath);\r
+ NextFullPath = NULL;\r
+ }\r
}\r
\r
if (Handles != NULL) {\r
FreePool (Handles);\r
}\r
\r
- return FileBuffer;\r
+ return NextFullPath;\r
}\r
\r
/**\r
\r
@param FilePath The device path pointing to a load option.\r
It could be a short-form device path.\r
- @param FullPath Return the full device path of the load option after\r
- short-form device path expanding.\r
- Caller is responsible to free it.\r
- @param FileSize Return the load option size.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
\r
- @return The load option buffer. Caller is responsible to free the memory.\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
**/\r
-VOID *\r
+EFI_DEVICE_PATH_PROTOCOL *\r
BmExpandFileDevicePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath\r
)\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE *Handles;\r
EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
UINTN MediaType;\r
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
- VOID *FileBuffer;\r
- UINT32 AuthenticationStatus;\r
- \r
+ EFI_DEVICE_PATH_PROTOCOL *NextFullPath;\r
+ BOOLEAN GetNext;\r
+\r
EfiBootManagerConnectAll ();\r
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);\r
if (EFI_ERROR (Status)) {\r
Handles = NULL;\r
}\r
\r
+ GetNext = (BOOLEAN)(FullPath == NULL);\r
+ NextFullPath = NULL;\r
//\r
// Enumerate all removable media devices followed by all fixed media devices,\r
// followed by media devices which don't layer on block io.\r
(MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||\r
(MediaType == 2 && BlockIo == NULL)\r
) {\r
- FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);\r
- FileBuffer = GetFileBufferByFilePath (TRUE, FullDevicePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer != NULL) {\r
- *FullPath = FullDevicePath;\r
- FreePool (Handles);\r
- return FileBuffer;\r
+ NextFullPath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);\r
+ if (GetNext) {\r
+ break;\r
+ } else {\r
+ GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);\r
+ FreePool (NextFullPath);\r
+ NextFullPath = NULL;\r
}\r
- FreePool (FullDevicePath);\r
}\r
}\r
+ if (NextFullPath != NULL) {\r
+ break;\r
+ }\r
}\r
\r
if (Handles != NULL) {\r
FreePool (Handles);\r
}\r
\r
- *FullPath = NULL;\r
- return NULL;\r
+ return NextFullPath;\r
}\r
\r
/**\r
\r
@param FilePath The device path pointing to a load option.\r
It could be a short-form device path.\r
- @param FullPath Return the full device path of the load option after\r
- short-form device path expanding.\r
- Caller is responsible to free it.\r
- @param FileSize Return the load option size.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
\r
- @return The load option buffer. Caller is responsible to free the memory.\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
**/\r
-VOID *\r
+EFI_DEVICE_PATH_PROTOCOL *\r
BmExpandUriDevicePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath\r
)\r
{\r
EFI_STATUS Status;\r
UINTN Index;\r
UINTN HandleCount;\r
EFI_HANDLE *Handles;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
- VOID *FileBuffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *NextFullPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
+ BOOLEAN GetNext;\r
\r
EfiBootManagerConnectAll ();\r
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles);\r
Handles = NULL;\r
}\r
\r
- FileBuffer = NULL;\r
-\r
+ NextFullPath = NULL;\r
+ GetNext = (BOOLEAN)(FullPath == NULL);\r
for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (Handles[Index], &gEfiLoadFileProtocolGuid, (VOID *) &LoadFile);\r
- ASSERT_EFI_ERROR (Status);\r
+ NextFullPath = BmExpandLoadFile (Handles[Index], FilePath);\r
\r
- FileBuffer = NULL;\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, FileSize, FileBuffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FileBuffer = AllocatePool (*FileSize);\r
- if (FileBuffer == NULL) {\r
- break;\r
- }\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, FileSize, FileBuffer);\r
+ if (NextFullPath == NULL) {\r
+ continue;\r
}\r
\r
- if (!EFI_ERROR (Status)) {\r
+ if (GetNext) {\r
+ break;\r
+ } else {\r
+ GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);\r
//\r
- // LoadFile() returns a file buffer mapping to a file system.\r
+ // Free the resource occupied by the RAM disk.\r
//\r
- if (Status == EFI_WARN_FILE_SYSTEM) {\r
- return BmGetFileBufferFromLoadFileFileSystem (Handles[Index], FullPath, FileSize);\r
+ RamDiskDevicePath = BmGetRamDiskDevicePath (NextFullPath);\r
+ if (RamDiskDevicePath != NULL) {\r
+ BmDestroyRamDisk (RamDiskDevicePath);\r
+ FreePool (RamDiskDevicePath);\r
}\r
-\r
- ASSERT (Status == EFI_SUCCESS);\r
- *FullPath = DuplicateDevicePath (DevicePathFromHandle (Handles[Index]));\r
- break;\r
- }\r
-\r
- if (FileBuffer != NULL) {\r
- FreePool (FileBuffer);\r
+ FreePool (NextFullPath);\r
+ NextFullPath = NULL;\r
}\r
}\r
\r
FreePool (Handles);\r
}\r
\r
- return FileBuffer;\r
+ return NextFullPath;\r
}\r
\r
/**\r
{\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
UINTN Count;\r
- \r
+\r
if (BmMatchDevicePaths (*CachedDevicePath, DevicePath)) {\r
TempDevicePath = *CachedDevicePath;\r
*CachedDevicePath = BmDelPartMatchInstance (*CachedDevicePath, DevicePath);\r
\r
@param FilePath The device path pointing to a load option.\r
It could be a short-form device path.\r
- @param FullPath Return the full device path of the load option after\r
- short-form device path expanding.\r
- Caller is responsible to free it.\r
- @param FileSize Return the load option size.\r
\r
- @return The load option buffer. Caller is responsible to free the memory.\r
+ @return The full device path pointing to the load option.\r
**/\r
-VOID *\r
+EFI_DEVICE_PATH_PROTOCOL *\r
BmExpandPartitionDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
)\r
{\r
EFI_STATUS Status;\r
UINTN BlockIoHandleCount;\r
EFI_HANDLE *BlockIoBuffer;\r
- VOID *FileBuffer;\r
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;\r
UINTN Index;\r
EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;\r
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullPath;\r
UINTN CachedDevicePathSize;\r
BOOLEAN NeedAdjust;\r
EFI_DEVICE_PATH_PROTOCOL *Instance;\r
UINTN Size;\r
\r
- FileBuffer = 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
ASSERT_EFI_ERROR (Status);\r
}\r
\r
+ FullPath = NULL;\r
if (CachedDevicePath != NULL) {\r
TempNewDevicePath = CachedDevicePath;\r
NeedAdjust = FALSE;\r
Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
if (!EFI_ERROR (Status)) {\r
TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));\r
- FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+ //\r
+ // TempDevicePath = ACPI()/PCI()/ATA()/Partition()\r
+ // or = ACPI()/PCI()/ATA()/Partition()/.../A.EFI\r
+ //\r
+ // When TempDevicePath = ACPI()/PCI()/ATA()/Partition(),\r
+ // it may expand to two potienal full paths (nested partition, rarely happen):\r
+ // 1. ACPI()/PCI()/ATA()/Partition()/Partition(A1)/EFI/BootX64.EFI\r
+ // 2. ACPI()/PCI()/ATA()/Partition()/Partition(A2)/EFI/BootX64.EFI\r
+ // For simplicity, only #1 is returned.\r
+ //\r
+ FullPath = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);\r
FreePool (TempDevicePath);\r
\r
- if (FileBuffer != NULL) {\r
+ if (FullPath != NULL) {\r
//\r
// Adjust the 'HDDP' instances sequence if the matched one is not first one.\r
//\r
\r
FreePool (Instance);\r
FreePool (CachedDevicePath);\r
- return FileBuffer;\r
+ return FullPath;\r
}\r
}\r
}\r
// Find the matched partition device path\r
//\r
TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));\r
- FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+ FullPath = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);\r
FreePool (TempDevicePath);\r
\r
- if (FileBuffer != NULL) {\r
+ if (FullPath != NULL) {\r
BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);\r
\r
//\r
if (BlockIoBuffer != NULL) {\r
FreePool (BlockIoBuffer);\r
}\r
- return FileBuffer;\r
+ return FullPath;\r
}\r
\r
/**\r
by appending EFI_REMOVABLE_MEDIA_FILE_NAME.\r
\r
@param DevicePath The media device path pointing to a BlockIo or SimpleFileSystem instance.\r
- @param FullPath Return the full device path pointing to the load option.\r
- @param FileSize Return the size of the load option.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
\r
- @return The load option buffer.\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
**/\r
-VOID *\r
+EFI_DEVICE_PATH_PROTOCOL *\r
BmExpandMediaDevicePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath\r
)\r
{\r
EFI_STATUS Status;\r
EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
VOID *Buffer;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *NextFullPath;\r
UINTN Size;\r
UINTN TempSize;\r
EFI_HANDLE *SimpleFileSystemHandles;\r
UINTN NumberSimpleFileSystemHandles;\r
UINTN Index;\r
- VOID *FileBuffer;\r
- UINT32 AuthenticationStatus;\r
+ BOOLEAN GetNext;\r
\r
+ GetNext = (BOOLEAN)(FullPath == NULL);\r
//\r
// Check whether the device is connected\r
//\r
if (!EFI_ERROR (Status)) {\r
ASSERT (IsDevicePathEnd (TempDevicePath));\r
\r
- TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
- FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer == NULL) {\r
- FreePool (TempDevicePath);\r
- TempDevicePath = NULL;\r
+ NextFullPath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+ //\r
+ // For device path pointing to simple file system, it only expands to one full path.\r
+ //\r
+ if (GetNext) {\r
+ return NextFullPath;\r
+ } else {\r
+ FreePool (NextFullPath);\r
+ return NULL;\r
}\r
- *FullPath = TempDevicePath;\r
- return FileBuffer;\r
}\r
\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
- // For device boot option only pointing to the removable device handle, \r
- // should make sure all its children handles (its child partion or media handles) are created and connected. \r
+ // For device boot option only pointing to the removable device handle,\r
+ // should make sure all its children handles (its child partion or media handles)\r
+ // are created and connected.\r
//\r
gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
\r
// returned. After the Block IO protocol is reinstalled, subsequent\r
// Block IO read/write will success.\r
//\r
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
- ASSERT_EFI_ERROR (Status);\r
Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
if (Buffer != NULL) {\r
BlockIo->ReadBlocks (\r
//\r
// Detect the the default boot file from removable Media\r
//\r
- FileBuffer = NULL;\r
- *FullPath = NULL;\r
+ NextFullPath = NULL;\r
Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;\r
gBS->LocateHandleBuffer (\r
ByProtocol,\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, DevicePath, Size) == 0)) {\r
- TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
- FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer != NULL) {\r
- *FullPath = TempDevicePath;\r
+ NextFullPath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+ if (GetNext) {\r
break;\r
+ } else {\r
+ GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);\r
+ FreePool (NextFullPath);\r
+ NextFullPath = NULL;\r
}\r
- FreePool (TempDevicePath);\r
}\r
}\r
\r
FreePool (SimpleFileSystemHandles);\r
}\r
\r
- return FileBuffer;\r
+ return NextFullPath;\r
}\r
\r
/**\r
return FALSE;\r
}\r
\r
+ if (DevicePathSubType (Left) == MSG_DNS_DP) {\r
+ Left = NextDevicePathNode (Left);\r
+ }\r
+\r
+ if (DevicePathSubType (Right) == MSG_DNS_DP) {\r
+ Right = NextDevicePathNode (Right);\r
+ }\r
+\r
if (((DevicePathSubType (Left) != MSG_IPv4_DP) || (DevicePathSubType (Right) != MSG_IPv4_DP)) &&\r
((DevicePathSubType (Left) != MSG_IPv6_DP) || (DevicePathSubType (Right) != MSG_IPv6_DP)) &&\r
((DevicePathSubType (Left) != MSG_URI_DP) || (DevicePathSubType (Right) != MSG_URI_DP))\r
Get the file buffer from the file system produced by Load File instance.\r
\r
@param LoadFileHandle The handle of LoadFile instance.\r
- @param FullPath Return the full device path pointing to the load option.\r
- @param FileSize Return the size of the load option.\r
+ @param RamDiskHandle Return the RAM Disk handle.\r
\r
- @return The load option buffer.\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
**/\r
-VOID *\r
-BmGetFileBufferFromLoadFileFileSystem (\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmExpandNetworkFileSystem (\r
IN EFI_HANDLE LoadFileHandle,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ OUT EFI_HANDLE *RamDiskHandle\r
)\r
{\r
EFI_STATUS Status;\r
&HandleCount,\r
&Handles\r
);\r
- if (EFI_ERROR (Status)) {\r
- Handles = NULL;\r
- HandleCount = 0;\r
+ if (EFI_ERROR (Status)) {\r
+ Handles = NULL;\r
+ HandleCount = 0;\r
+ }\r
+\r
+ Handle = NULL;\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Node = DevicePathFromHandle (Handles[Index]);\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status) &&\r
+ (Handle == LoadFileHandle) &&\r
+ (DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)) {\r
+ //\r
+ // Find the BlockIo instance populated from the LoadFile.\r
+ //\r
+ Handle = Handles[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+\r
+ if (Index == HandleCount) {\r
+ Handle = NULL;\r
+ }\r
+\r
+ *RamDiskHandle = Handle;\r
+\r
+ if (Handle != NULL) {\r
+ //\r
+ // Re-use BmExpandMediaDevicePath() to get the full device path of load option.\r
+ // But assume only one SimpleFileSystem can be found under the BlockIo.\r
+ //\r
+ return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), NULL);\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Return the RAM Disk device path created by LoadFile.\r
+\r
+ @param FilePath The source file path.\r
+\r
+ @return Callee-to-free RAM Disk device path\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmGetRamDiskDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_HANDLE Handle;\r
+\r
+ Node = FilePath;\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status) &&\r
+ (DevicePathType (Node) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)\r
+ ) {\r
+\r
+ //\r
+ // Construct the device path pointing to RAM Disk\r
+ //\r
+ Node = NextDevicePathNode (Node);\r
+ RamDiskDevicePath = DuplicateDevicePath (FilePath);\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+ SetDevicePathEndNode ((VOID *) ((UINTN) RamDiskDevicePath + ((UINTN) Node - (UINTN) FilePath)));\r
+ return RamDiskDevicePath;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Return the buffer and buffer size occupied by the RAM Disk.\r
+\r
+ @param RamDiskDevicePath RAM Disk device path.\r
+ @param RamDiskSizeInPages Return RAM Disk size in pages.\r
+\r
+ @retval RAM Disk buffer.\r
+**/\r
+VOID *\r
+BmGetRamDiskMemoryInfo (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath,\r
+ OUT UINTN *RamDiskSizeInPages\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ UINT64 StartingAddr;\r
+ UINT64 EndingAddr;\r
+\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+\r
+ *RamDiskSizeInPages = 0;\r
+\r
+ //\r
+ // Get the buffer occupied by RAM Disk.\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &RamDiskDevicePath, &Handle);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT ((DevicePathType (RamDiskDevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (RamDiskDevicePath) == MEDIA_RAM_DISK_DP));\r
+ StartingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->StartingAddr);\r
+ EndingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->EndingAddr);\r
+ *RamDiskSizeInPages = EFI_SIZE_TO_PAGES ((UINTN) (EndingAddr - StartingAddr + 1));\r
+ return (VOID *) (UINTN) StartingAddr;\r
+}\r
+\r
+/**\r
+ Destroy the RAM Disk.\r
+\r
+ The destroy operation includes to call RamDisk.Unregister to\r
+ unregister the RAM DISK from RAM DISK driver, free the memory\r
+ allocated for the RAM Disk.\r
+\r
+ @param RamDiskDevicePath RAM Disk device path.\r
+**/\r
+VOID\r
+BmDestroyRamDisk (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *RamDiskBuffer;\r
+ UINTN RamDiskSizeInPages;\r
+\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+\r
+ RamDiskBuffer = BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
+\r
+ //\r
+ // Destroy RAM Disk.\r
+ //\r
+ if (mRamDisk == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID *) &mRamDisk);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ Status = mRamDisk->Unregister (RamDiskDevicePath);\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePages (RamDiskBuffer, RamDiskSizeInPages);\r
+}\r
+\r
+/**\r
+ Get the file buffer from the specified Load File instance.\r
+\r
+ @param LoadFileHandle The specified Load File instance.\r
+ @param FilePath The file path which will pass to LoadFile().\r
+\r
+ @return The full device path pointing to the load option buffer.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmExpandLoadFile (\r
+ IN EFI_HANDLE LoadFileHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+ VOID *FileBuffer;\r
+ EFI_HANDLE RamDiskHandle;\r
+ UINTN BufferSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullPath;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ LoadFileHandle,\r
+ &gEfiLoadFileProtocolGuid,\r
+ (VOID **) &LoadFile,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ FileBuffer = NULL;\r
+ BufferSize = 0;\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if ((Status != EFI_WARN_FILE_SYSTEM) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+ return NULL;\r
}\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Node = DevicePathFromHandle (Handles[Index]);\r
- Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
- if (!EFI_ERROR (Status) &&\r
- (Handle == LoadFileHandle) &&\r
- (DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)) {\r
- Handle = Handles[Index];\r
- break;\r
- }\r
+\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // The load option buffer is directly returned by LoadFile.\r
+ //\r
+ return DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));\r
}\r
\r
- if (Handles != NULL) {\r
- FreePool (Handles);\r
+ //\r
+ // The load option resides in a RAM disk.\r
+ //\r
+ FileBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize));\r
+ if (FileBuffer == NULL) {\r
+ return NULL;\r
}\r
\r
- if (Index != HandleCount) {\r
- return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize);\r
- } else {\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
return NULL;\r
}\r
+\r
+ FullPath = BmExpandNetworkFileSystem (LoadFileHandle, &RamDiskHandle);\r
+ if (FullPath == NULL) {\r
+ //\r
+ // Free the memory occupied by the RAM disk if there is no BlockIo or SimpleFileSystem instance.\r
+ //\r
+ BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));\r
+ }\r
+\r
+ return FullPath;\r
}\r
\r
/**\r
- Get the file buffer from Load File instance.\r
+ Return the full device path pointing to the load option.\r
+\r
+ FilePath may:\r
+ 1. Exactly matches to a LoadFile instance.\r
+ 2. Cannot match to any LoadFile instance. Wide match is required.\r
+ In either case, the routine may return:\r
+ 1. A copy of FilePath when FilePath matches to a LoadFile instance and\r
+ the LoadFile returns a load option buffer.\r
+ 2. A new device path with IP and URI information updated when wide match\r
+ happens.\r
+ 3. A new device path pointing to a load option in RAM disk.\r
+ In either case, only one full device path is returned for a specified\r
+ FilePath.\r
\r
@param FilePath The media device path pointing to a LoadFile instance.\r
- @param FullPath Return the full device path pointing to the load option.\r
- @param FileSize Return the size of the load option.\r
\r
@return The load option buffer.\r
**/\r
-VOID *\r
-BmGetFileBufferFromLoadFile (\r
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmExpandLoadFiles (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
)\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
- VOID *FileBuffer;\r
EFI_HANDLE *Handles;\r
UINTN HandleCount;\r
UINTN Index;\r
EFI_DEVICE_PATH_PROTOCOL *Node;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
- UINTN BufferSize;\r
\r
//\r
// Get file buffer from load file instance.\r
return NULL;\r
}\r
\r
- Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **) &LoadFile);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- BufferSize = 0;\r
- FileBuffer = NULL;\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FileBuffer = AllocatePool (BufferSize);\r
- if (FileBuffer != NULL) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // LoadFile() returns a file buffer mapping to a file system.\r
- //\r
- if (Status == EFI_WARN_FILE_SYSTEM) {\r
- return BmGetFileBufferFromLoadFileFileSystem (Handle, FullPath, FileSize);\r
- }\r
-\r
- ASSERT (Status == EFI_SUCCESS);\r
- //\r
- // LoadFile () may cause the device path of the Handle be updated.\r
- //\r
- *FullPath = DuplicateDevicePath (DevicePathFromHandle (Handle));\r
- *FileSize = BufferSize;\r
- return FileBuffer;\r
- } else {\r
- return NULL;\r
- }\r
+ return BmExpandLoadFile (Handle, FilePath);\r
}\r
\r
/**\r
@return The load option buffer. Caller is responsible to free the memory.\r
**/\r
VOID *\r
-BmGetLoadOptionBuffer (\r
+EFIAPI\r
+EfiBootManagerGetLoadOptionBuffer (\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
OUT UINTN *FileSize\r
)\r
+{\r
+ *FullPath = NULL;\r
+\r
+ EfiBootManagerConnectDevicePath (FilePath, NULL);\r
+ return BmGetNextLoadOptionBuffer (LoadOptionTypeMax, FilePath, FullPath, FileSize);\r
+}\r
+\r
+/**\r
+ Get the next possible full path pointing to the load option.\r
+ The routine doesn't guarantee the returned full path points to an existing\r
+ file, and it also doesn't guarantee the existing file is a valid load option.\r
+ BmGetNextLoadOptionBuffer() guarantees.\r
+\r
+ @param FilePath The device path pointing to a load option.\r
+ It could be a short-form device path.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
+\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmGetNextLoadOptionDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath\r
+ )\r
{\r
EFI_HANDLE Handle;\r
- VOID *FileBuffer;\r
- UINT32 AuthenticationStatus;\r
EFI_DEVICE_PATH_PROTOCOL *Node;\r
EFI_STATUS Status;\r
\r
- ASSERT ((FilePath != NULL) && (FullPath != NULL) && (FileSize != NULL));\r
-\r
- EfiBootManagerConnectDevicePath (FilePath, NULL);\r
-\r
- *FullPath = NULL;\r
- *FileSize = 0;\r
- FileBuffer = NULL;\r
+ ASSERT (FilePath != NULL);\r
\r
//\r
// Boot from media device by adding a default file name \EFI\BOOT\BOOT{machine type short-name}.EFI\r
}\r
\r
if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {\r
- return BmExpandMediaDevicePath (FilePath, FullPath, FileSize);\r
+ return BmExpandMediaDevicePath (FilePath, FullPath);\r
}\r
\r
//\r
//\r
// Expand the Harddrive device path\r
//\r
- return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize);\r
+ if (FullPath == NULL) {\r
+ return BmExpandPartitionDevicePath (FilePath);\r
+ } else {\r
+ return NULL;\r
+ }\r
} else if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&\r
(DevicePathSubType (FilePath) == MEDIA_FILEPATH_DP)) {\r
//\r
// Expand the File-path device path\r
//\r
- return BmExpandFileDevicePath (FilePath, FullPath, FileSize);\r
+ return BmExpandFileDevicePath (FilePath, FullPath);\r
} else if ((DevicePathType (FilePath) == MESSAGING_DEVICE_PATH) &&\r
(DevicePathSubType (FilePath) == MSG_URI_DP)) {\r
//\r
// Expand the URI device path\r
//\r
- return BmExpandUriDevicePath (FilePath, FullPath, FileSize);\r
+ return BmExpandUriDevicePath (FilePath, FullPath);\r
} else {\r
- for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
- if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
- ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) || (DevicePathSubType (Node) == MSG_USB_WWID_DP))) {\r
- break;\r
+ Node = FilePath;\r
+ Status = gBS->LocateDevicePath (&gEfiUsbIoProtocolGuid, &Node, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Only expand the USB WWID/Class device path\r
+ // when FilePath doesn't point to a physical UsbIo controller.\r
+ // Otherwise, infinite recursion will happen.\r
+ //\r
+ for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) || (DevicePathSubType (Node) == MSG_USB_WWID_DP))) {\r
+ break;\r
+ }\r
}\r
- }\r
\r
- if (!IsDevicePathEnd (Node)) {\r
//\r
// Expand the USB WWID/Class device path\r
//\r
- FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);\r
- if ((FileBuffer == NULL) && (FilePath == Node)) {\r
- //\r
- // Boot Option device path starts with USB Class or USB WWID device path.\r
- // For Boot Option device path which doesn't begin with the USB Class or\r
- // USB WWID device path, it's not needed to connect again here.\r
- //\r
- BmConnectUsbShortFormDevicePath (FilePath);\r
- FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);\r
+ if (!IsDevicePathEnd (Node)) {\r
+ if (FilePath == Node) {\r
+ //\r
+ // Boot Option device path starts with USB Class or USB WWID device path.\r
+ // For Boot Option device path which doesn't begin with the USB Class or\r
+ // USB WWID device path, it's not needed to connect again here.\r
+ //\r
+ BmConnectUsbShortFormDevicePath (FilePath);\r
+ }\r
+ return BmExpandUsbDevicePath (FilePath, FullPath, Node);\r
}\r
- return FileBuffer;\r
}\r
}\r
\r
//\r
- // Get file buffer from FV file path.\r
+ // For the below cases, FilePath only expands to one Full path.\r
+ // So just handle the case when FullPath == NULL.\r
+ //\r
+ if (FullPath != NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Load option resides in FV.\r
//\r
if (BmIsFvFilePath (FilePath)) {\r
- return BmGetFileBufferByFvFilePath (FilePath, FullPath, FileSize);\r
+ return BmAdjustFvFilePath (FilePath);\r
}\r
\r
//\r
- // Get file buffer from simple file system.\r
+ // Load option resides in Simple File System.\r
//\r
Node = FilePath;\r
Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);\r
if (!EFI_ERROR (Status)) {\r
- FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer != NULL) {\r
- *FullPath = DuplicateDevicePath (FilePath);\r
+ return DuplicateDevicePath (FilePath);\r
+ }\r
+\r
+ //\r
+ // Last chance to try: Load option may be loaded through LoadFile.\r
+ //\r
+ return BmExpandLoadFiles (FilePath);\r
+}\r
+\r
+/**\r
+ Check if it's a Device Path pointing to BootManagerMenu.\r
+\r
+ @param DevicePath Input device path.\r
+\r
+ @retval TRUE The device path is BootManagerMenu File Device Path.\r
+ @retval FALSE The device path is NOT BootManagerMenu File Device Path.\r
+**/\r
+BOOLEAN\r
+BmIsBootManagerMenuFilePath (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+)\r
+{\r
+ EFI_HANDLE FvHandle;\r
+ VOID *NameGuid;\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);\r
+ if (NameGuid != NULL) {\r
+ return CompareGuid (NameGuid, PcdGetPtr (PcdBootManagerMenuFile));\r
}\r
- return FileBuffer;\r
}\r
\r
- return BmGetFileBufferFromLoadFile (FilePath, FullPath, FileSize);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Report status code with EFI_RETURN_STATUS_EXTENDED_DATA about LoadImage() or\r
+ StartImage() failure.\r
+\r
+ @param[in] ErrorCode An Error Code in the Software Class, DXE Boot\r
+ Service Driver Subclass. ErrorCode will be used to\r
+ compose the Value parameter for status code\r
+ reporting. Must be one of\r
+ EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR and\r
+ EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED.\r
+\r
+ @param[in] FailureStatus The failure status returned by the boot service\r
+ that should be reported.\r
+**/\r
+VOID\r
+BmReportLoadFailure (\r
+ IN UINT32 ErrorCode,\r
+ IN EFI_STATUS FailureStatus\r
+ )\r
+{\r
+ EFI_RETURN_STATUS_EXTENDED_DATA ExtendedData;\r
+\r
+ if (!ReportErrorCodeEnabled ()) {\r
+ return;\r
+ }\r
+\r
+ ASSERT (\r
+ (ErrorCode == EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR) ||\r
+ (ErrorCode == EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)\r
+ );\r
+\r
+ ZeroMem (&ExtendedData, sizeof (ExtendedData));\r
+ ExtendedData.ReturnStatus = FailureStatus;\r
+\r
+ REPORT_STATUS_CODE_EX (\r
+ (EFI_ERROR_CODE | EFI_ERROR_MINOR),\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | ErrorCode),\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ &ExtendedData.DataHeader + 1,\r
+ sizeof (ExtendedData) - sizeof (ExtendedData.DataHeader)\r
+ );\r
}\r
\r
/**\r
Attempt to boot the EFI boot option. This routine sets L"BootCurent" and\r
also signals the EFI ready to boot event. If the device path for the option\r
- starts with a BBS device path a legacy boot is attempted via the registered \r
- gLegacyBoot function. Short form device paths are also supported via this \r
+ starts with a BBS device path a legacy boot is attempted via the registered\r
+ gLegacyBoot function. Short form device paths are also supported via this\r
rountine. A device path starting with MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP,\r
MSG_USB_CLASS_DP gets expaned out to find the first device that matches.\r
- If the BootOption Device Path fails the removable media boot algorithm \r
- is attempted (\EFI\BOOTIA32.EFI, \EFI\BOOTX64.EFI,... only one file type \r
+ If the BootOption Device Path fails the removable media boot algorithm\r
+ is attempted (\EFI\BOOTIA32.EFI, \EFI\BOOTX64.EFI,... only one file type\r
is tried per processor type)\r
\r
@param BootOption Boot Option to try and boot.\r
UINTN OptionNumber;\r
UINTN OriginalOptionNumber;\r
EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
- EFI_DEVICE_PATH_PROTOCOL *Node;\r
- EFI_HANDLE FvHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
VOID *FileBuffer;\r
UINTN FileSize;\r
EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
// 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute\r
// the boot option.\r
//\r
- Node = BootOption->FilePath;\r
- Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
- if (!EFI_ERROR (Status) && CompareGuid (\r
- EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
- PcdGetPtr (PcdBootManagerMenuFile)\r
- )) {\r
+ if (BmIsBootManagerMenuFilePath (BootOption->FilePath)) {\r
DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));\r
BmStopHotkeyService (NULL, NULL);\r
} else {\r
//\r
// 4. Repair system through DriverHealth protocol\r
//\r
- BmRepairAllControllers ();\r
+ BmRepairAllControllers (0);\r
}\r
\r
PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
\r
//\r
- // 5. Load EFI boot option to ImageHandle\r
+ // 5. 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
+ BmSetMemoryTypeInformationVariable (\r
+ (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
+ );\r
+\r
//\r
- ImageHandle = NULL;\r
+ // 6. Load EFI boot option to ImageHandle\r
+ //\r
+ DEBUG_CODE_BEGIN ();\r
+ if (BootOption->Description == NULL) {\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ ImageHandle = NULL;\r
+ RamDiskDevicePath = NULL;\r
if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {\r
- Status = EFI_NOT_FOUND;\r
- FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
- DEBUG_CODE (\r
- if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {\r
- DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));\r
- BmPrintDp (BootOption->FilePath);\r
- DEBUG ((EFI_D_INFO, " -> "));\r
- BmPrintDp (FilePath);\r
- DEBUG ((EFI_D_INFO, "\n"));\r
- }\r
- );\r
- if (BmIsLoadOptionPeHeaderValid (BootOption->OptionType, FileBuffer, FileSize)) {\r
+ Status = EFI_NOT_FOUND;\r
+ FilePath = NULL;\r
+ EfiBootManagerConnectDevicePath (BootOption->FilePath, NULL);\r
+ FileBuffer = BmGetNextLoadOptionBuffer (LoadOptionTypeBoot, BootOption->FilePath, &FilePath, &FileSize);\r
+ if (FileBuffer != NULL) {\r
+ RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);\r
+\r
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
Status = gBS->LoadImage (\r
TRUE,\r
\r
if (EFI_ERROR (Status)) {\r
//\r
- // Report Status Code to indicate that the failure to load boot option\r
+ // Report Status Code with the failure status to indicate that the failure to load boot option\r
//\r
- REPORT_STATUS_CODE (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
- );\r
+ BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status);\r
BootOption->Status = Status;\r
+ //\r
+ // Destroy the RAM disk\r
+ //\r
+ if (RamDiskDevicePath != NULL) {\r
+ BmDestroyRamDisk (RamDiskDevicePath);\r
+ FreePool (RamDiskDevicePath);\r
+ }\r
return;\r
}\r
}\r
\r
- //\r
- // 6. 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
- BmSetMemoryTypeInformationVariable (\r
- (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
- );\r
-\r
- DEBUG_CODE_BEGIN();\r
- if (BootOption->Description == NULL) {\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
- } else {\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
- }\r
- DEBUG_CODE_END();\r
-\r
//\r
// Check to see if we should legacy BOOT. If yes then do the legacy boot\r
// Write boot to OS performance data for Legacy boot\r
//\r
Status = EfiCreateEventLegacyBootEx(\r
TPL_NOTIFY,\r
- BmWriteBootToOsPerformanceData,\r
- NULL, \r
+ BmEndOfBdsPerfCode,\r
+ NULL,\r
&LegacyBootEvent\r
);\r
ASSERT_EFI_ERROR (Status);\r
PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
return;\r
}\r
- \r
+\r
//\r
// Provide the image with its load options\r
//\r
// Write boot to OS performance data for UEFI boot\r
//\r
PERF_CODE (\r
- BmWriteBootToOsPerformanceData (NULL, NULL);\r
+ BmEndOfBdsPerfCode (NULL, NULL);\r
);\r
\r
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));\r
BootOption->Status = Status;\r
if (EFI_ERROR (Status)) {\r
//\r
- // Report Status Code to indicate that boot failure\r
+ // Report Status Code with the failure status to indicate that boot failure\r
//\r
- REPORT_STATUS_CODE (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)\r
- );\r
+ BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED, Status);\r
}\r
PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
\r
+ //\r
+ // Destroy the RAM disk\r
+ //\r
+ if (RamDiskDevicePath != NULL) {\r
+ BmDestroyRamDisk (RamDiskDevicePath);\r
+ FreePool (RamDiskDevicePath);\r
+ }\r
+\r
//\r
// Clear the Watchdog Timer after the image returns\r
//\r
}\r
\r
//\r
- // find the partition device path node\r
+ // Match all the partition device path nodes including the nested partition nodes\r
//\r
while (!IsDevicePathEnd (BlockIoDevicePath)) {\r
if ((DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&\r
(DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP)\r
) {\r
- break;\r
- }\r
-\r
- BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);\r
- }\r
-\r
- if (IsDevicePathEnd (BlockIoDevicePath)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
- //\r
- Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;\r
-\r
- //\r
- // Match Signature and PartitionNumber.\r
- // Unused bytes in Signature are initiaized with zeros.\r
- //\r
- return (BOOLEAN) (\r
- (Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&\r
- (Node->MBRType == HardDriveDevicePath->MBRType) &&\r
- (Node->SignatureType == HardDriveDevicePath->SignatureType) &&\r
- (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0)\r
- );\r
-}\r
-\r
-/**\r
- Enumerate all boot option descriptions and append " 2"/" 3"/... to make\r
- unique description.\r
-\r
- @param BootOptions Array of boot options.\r
- @param BootOptionCount Count of boot options.\r
-**/\r
-VOID\r
-BmMakeBootOptionDescriptionUnique (\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,\r
- UINTN BootOptionCount\r
- )\r
-{\r
- UINTN Base;\r
- UINTN Index;\r
- UINTN DescriptionSize;\r
- UINTN MaxSuffixSize;\r
- BOOLEAN *Visited;\r
- UINTN MatchCount;\r
-\r
- if (BootOptionCount == 0) {\r
- return;\r
- }\r
-\r
- //\r
- // Calculate the maximum buffer size for the number suffix.\r
- // The initial sizeof (CHAR16) is for the blank space before the number.\r
- //\r
- MaxSuffixSize = sizeof (CHAR16);\r
- for (Index = BootOptionCount; Index != 0; Index = Index / 10) {\r
- MaxSuffixSize += sizeof (CHAR16);\r
- }\r
-\r
- Visited = AllocateZeroPool (sizeof (BOOLEAN) * BootOptionCount);\r
- ASSERT (Visited != NULL);\r
+ //\r
+ // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
+ //\r
+ Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;\r
\r
- for (Base = 0; Base < BootOptionCount; Base++) {\r
- if (!Visited[Base]) {\r
- MatchCount = 1;\r
- Visited[Base] = TRUE;\r
- DescriptionSize = StrSize (BootOptions[Base].Description);\r
- for (Index = Base + 1; Index < BootOptionCount; Index++) {\r
- if (!Visited[Index] && StrCmp (BootOptions[Base].Description, BootOptions[Index].Description) == 0) {\r
- Visited[Index] = TRUE;\r
- MatchCount++;\r
- FreePool (BootOptions[Index].Description);\r
- BootOptions[Index].Description = AllocatePool (DescriptionSize + MaxSuffixSize);\r
- UnicodeSPrint (\r
- BootOptions[Index].Description, DescriptionSize + MaxSuffixSize,\r
- L"%s %d",\r
- BootOptions[Base].Description, MatchCount\r
- );\r
- }\r
+ //\r
+ // Match Signature and PartitionNumber.\r
+ // Unused bytes in Signature are initiaized with zeros.\r
+ //\r
+ if ((Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&\r
+ (Node->MBRType == HardDriveDevicePath->MBRType) &&\r
+ (Node->SignatureType == HardDriveDevicePath->SignatureType) &&\r
+ (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0)) {\r
+ return TRUE;\r
}\r
}\r
+\r
+ BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);\r
}\r
\r
- FreePool (Visited);\r
+ return FALSE;\r
}\r
\r
/**\r
3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting\r
SimpleFileSystem Protocol, but not supporting BlockIo\r
protocol.\r
- 4. LoadFile - The boot option points to the media supporting \r
+ 4. LoadFile - The boot option points to the media supporting\r
LoadFile protocol.\r
Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior\r
\r
}\r
\r
//\r
- // Parse load file, assuming UEFI Network boot option\r
+ // Parse load file protocol\r
//\r
gBS->LocateHandleBuffer (\r
ByProtocol,\r
&Handles\r
);\r
for (Index = 0; Index < HandleCount; Index++) {\r
+ //\r
+ // Ignore BootManagerMenu. its boot option will be created by EfiBootManagerGetBootManagerMenu().\r
+ //\r
+ if (BmIsBootManagerMenuFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+ continue;\r
+ }\r
\r
Description = BmGetBootDescription (Handles[Index]);\r
BootOptions = ReallocatePool (\r
// Remove invalid EFI boot options from NV\r
//\r
for (Index = 0; Index < NvBootOptionCount; Index++) {\r
- if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) || \r
+ if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) ||\r
(DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)\r
) && BmIsAutoCreateBootOption (&NvBootOptions[Index])\r
) {\r
// Only check those added by BDS\r
// so that the boot options added by end-user or OS installer won't be deleted\r
//\r
- if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {\r
+ if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == -1) {\r
Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
//\r
// Deleting variable with current variable implementation shouldn't fail.\r
// Add new EFI boot options to NV\r
//\r
for (Index = 0; Index < BootOptionCount; Index++) {\r
- if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {\r
+ if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == -1) {\r
EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
//\r
// Try best to add the boot options so continue upon failure.\r
}\r
\r
/**\r
- This function is called to create the boot option for the Boot Manager Menu.\r
+ This function is called to get or create the boot option for the Boot Manager Menu.\r
\r
The Boot Manager Menu is shown after successfully booting a boot option.\r
Assume the BootManagerMenuFile is in the same FV as the module links to this library.\r
@param BootOption Return the boot option of the Boot Manager Menu\r
\r
@retval EFI_SUCCESS Successfully register the Boot Manager Menu.\r
- @retval Status Return status of gRT->SetVariable (). BootOption still points\r
- to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+ @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+ @retval others Return status of gRT->SetVariable (). BootOption still points\r
+ to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+ and EFI_NOT_FOUND.\r
**/\r
EFI_STATUS\r
BmRegisterBootManagerMenu (\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *Handles;\r
+ UINTN Index;\r
+ VOID *Data;\r
+ UINTN DataSize;\r
\r
- Status = GetSectionFromFv (\r
- PcdGetPtr (PcdBootManagerMenuFile),\r
- EFI_SECTION_USER_INTERFACE,\r
- 0,\r
- (VOID **) &Description,\r
- &DescriptionLength\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Description = NULL;\r
+ DevicePath = NULL;\r
+ Description = NULL;\r
+ //\r
+ // Try to find BootManagerMenu from LoadFile protocol\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadFileProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ if (BmIsBootManagerMenuFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+ DevicePath = DuplicateDevicePath (DevicePathFromHandle (Handles[Index]));\r
+ Description = BmGetBootDescription (Handles[Index]);\r
+ break;\r
+ }\r
+ }\r
+ if (HandleCount != 0) {\r
+ FreePool (Handles);\r
}\r
\r
- EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
- Status = gBS->HandleProtocol (\r
- gImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **) &LoadedImage\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- DevicePath = AppendDevicePathNode (\r
- DevicePathFromHandle (LoadedImage->DeviceHandle),\r
- (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
- );\r
- ASSERT (DevicePath != NULL);\r
+ if (DevicePath == NULL) {\r
+ Data = NULL;\r
+ Status = GetSectionFromFv (\r
+ PcdGetPtr (PcdBootManagerMenuFile),\r
+ EFI_SECTION_PE32,\r
+ 0,\r
+ (VOID **) &Data,\r
+ &DataSize\r
+ );\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN, "[Bds]BootManagerMenu FFS section can not be found, skip its boot option registration\n"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Get BootManagerMenu application's description from EFI User Interface Section.\r
+ //\r
+ Status = GetSectionFromFv (\r
+ PcdGetPtr (PcdBootManagerMenuFile),\r
+ EFI_SECTION_USER_INTERFACE,\r
+ 0,\r
+ (VOID **) &Description,\r
+ &DescriptionLength\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Description = NULL;\r
+ }\r
+\r
+ EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
+ Status = gBS->HandleProtocol (\r
+ gImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImage\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DevicePath = AppendDevicePathNode (\r
+ DevicePathFromHandle (LoadedImage->DeviceHandle),\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
+ );\r
+ ASSERT (DevicePath != NULL);\r
+ }\r
\r
Status = EfiBootManagerInitializeLoadOption (\r
BootOption,\r
/**\r
Return the boot option corresponding to the Boot Manager Menu.\r
It may automatically create one if the boot option hasn't been created yet.\r
- \r
+\r
@param BootOption Return the Boot Manager Menu.\r
\r
@retval EFI_SUCCESS The Boot Manager Menu is successfully returned.\r
- @retval Status Return status of gRT->SetVariable (). BootOption still points\r
- to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+ @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+ @retval others Return status of gRT->SetVariable (). BootOption still points\r
+ to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+ and EFI_NOT_FOUND.\r
**/\r
EFI_STATUS\r
EFIAPI\r
UINTN BootOptionCount;\r
EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
UINTN Index;\r
- EFI_DEVICE_PATH_PROTOCOL *Node;\r
- EFI_HANDLE FvHandle;\r
- \r
+\r
BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
\r
for (Index = 0; Index < BootOptionCount; Index++) {\r
- Node = BootOptions[Index].FilePath;\r
- Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
- if (!EFI_ERROR (Status)) {\r
- if (CompareGuid (\r
- EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
- PcdGetPtr (PcdBootManagerMenuFile)\r
- )\r
- ) { \r
+ if (BmIsBootManagerMenuFilePath (BootOptions[Index].FilePath)) {\r
Status = EfiBootManagerInitializeLoadOption (\r
BootOption,\r
BootOptions[Index].OptionNumber,\r
);\r
ASSERT_EFI_ERROR (Status);\r
break;\r
- }\r
}\r
}\r
\r
}\r
}\r
\r
+/**\r
+ Get the next possible full path pointing to the load option.\r
+ The routine doesn't guarantee the returned full path points to an existing\r
+ file, and it also doesn't guarantee the existing file is a valid load option.\r
+ BmGetNextLoadOptionBuffer() guarantees.\r
+\r
+ @param FilePath The device path pointing to a load option.\r
+ It could be a short-form device path.\r
+ @param FullPath The full path returned by the routine in last call.\r
+ Set to NULL in first call.\r
+\r
+ @return The next possible full path pointing to the load option.\r
+ Caller is responsible to free the memory.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+EfiBootManagerGetNextLoadOptionDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath\r
+ )\r
+{\r
+ return BmGetNextLoadOptionDevicePath(FilePath, FullPath);\r
+}\r