/** @file\r
Library functions which relates with booting.\r
\r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\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
\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
}\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
+ Return TRUE when the boot option is auto-created instead of manually added.\r
\r
+ @param BootOption Pointer to the boot option to check.\r
+\r
+ @retval TRUE The boot option is auto-created.\r
+ @retval FALSE The boot option is manually added.\r
**/\r
-BM_BOOT_TYPE\r
-BmDevicePathType (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+BOOLEAN\r
+BmIsAutoCreateBootOption (\r
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\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
+ if ((BootOption->OptionalDataSize == sizeof (EFI_GUID)) &&\r
+ CompareGuid ((EFI_GUID *) BootOption->OptionalData, &mBmAutoCreateBootOptionGuid)\r
+ ) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
}\r
-\r
- return BmMiscBoot;\r
}\r
\r
/**\r
\r
FV address may change across reboot. This routine promises the FV file device path is right.\r
\r
- @param DevicePath The Memory Mapped Device Path to get the file buffer.\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
**/\r
VOID *\r
-BmGetFileBufferByMemmapFv (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+BmGetFileBufferByFvFilePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
OUT UINTN *FileSize\r
)\r
EFI_HANDLE *FvHandles;\r
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
VOID *FileBuffer;\r
- \r
- FvFileNode = DevicePath;\r
+\r
+ //\r
+ // Get the file buffer by using the exactly FilePath.\r
+ //\r
+ FvFileNode = FilePath;\r
Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);\r
if (!EFI_ERROR (Status)) {\r
- FileBuffer = GetFileBufferByFilePath (TRUE, DevicePath, FileSize, &AuthenticationStatus);\r
+ FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
if (FileBuffer != NULL) {\r
- *FullPath = DuplicateDevicePath (DevicePath);\r
+ *FullPath = DuplicateDevicePath (FilePath);\r
}\r
return FileBuffer;\r
}\r
\r
- FvFileNode = NextDevicePathNode (DevicePath);\r
+ //\r
+ // Only wide match other FVs if it's a memory mapped FV file path.\r
+ //\r
+ if ((DevicePathType (FilePath) != HARDWARE_DEVICE_PATH) || (DevicePathSubType (FilePath) != HW_MEMMAP_DP)) {\r
+ return NULL;\r
+ }\r
+\r
+ FvFileNode = NextDevicePathNode (FilePath);\r
\r
//\r
// Firstly find the FV file in current FV\r
(VOID **) &LoadedImage\r
);\r
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);\r
- FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+ FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
FreePool (NewDevicePath);\r
\r
if (FileBuffer != NULL) {\r
continue;\r
}\r
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);\r
- FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+ FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
FreePool (NewDevicePath);\r
}\r
\r
}\r
\r
/**\r
- Check if it's a Memory Mapped FV Device Path.\r
+ Check if it's a Device Path pointing to FV file.\r
\r
The function doesn't garentee the device path points to existing FV file.\r
\r
@param DevicePath Input device path.\r
\r
- @retval TRUE The device path is a Memory Mapped FV Device Path.\r
- @retval FALSE The device path is NOT a Memory Mapped FV Device Path.\r
+ @retval TRUE The device path is a FV File Device Path.\r
+ @retval FALSE The device path is NOT a FV File Device Path.\r
**/\r
BOOLEAN\r
-BmIsMemmapFvFilePath (\r
+BmIsFvFilePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
)\r
{\r
- EFI_DEVICE_PATH_PROTOCOL *FileNode;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+\r
+ Node = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ return TRUE;\r
+ }\r
\r
if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (DevicePath) == HW_MEMMAP_DP)) {\r
- FileNode = NextDevicePathNode (DevicePath);\r
- if ((DevicePathType (FileNode) == MEDIA_DEVICE_PATH) && (DevicePathSubType (FileNode) == MEDIA_PIWG_FW_FILE_DP)) {\r
- return IsDevicePathEnd (NextDevicePathNode (FileNode));\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MEDIA_PIWG_FW_FILE_DP)) {\r
+ return IsDevicePathEnd (NextDevicePathNode (DevicePath));\r
}\r
}\r
-\r
return FALSE;\r
}\r
\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
return NULL;\r
}\r
\r
+/**\r
+ Expand URI device path node to be full device path in platform.\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
+**/\r
+VOID *\r
+BmExpandUriDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
+ OUT UINTN *FileSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *Handles;\r
+ VOID *FileBuffer;\r
+\r
+ EfiBootManagerConnectAll ();\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles);\r
+ if (EFI_ERROR (Status)) {\r
+ HandleCount = 0;\r
+ Handles = NULL;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ FileBuffer = BmGetFileBufferFromLoadFile (Handles[Index], FilePath, FullPath, FileSize);\r
+ if (FileBuffer != NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+\r
+ return FileBuffer;\r
+}\r
+\r
/**\r
Save the partition DevicePath to the CachedDevicePath as the first instance.\r
\r
return FileBuffer;\r
}\r
\r
+/**\r
+ Check whether Left and Right are the same without matching the specific\r
+ device path data in IP device path and URI device path node.\r
+\r
+ @retval TRUE Left and Right are the same.\r
+ @retval FALSE Left and Right are the different.\r
+**/\r
+BOOLEAN\r
+BmMatchHttpBootDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Left,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Right\r
+ )\r
+{\r
+ for (; !IsDevicePathEnd (Left) && !IsDevicePathEnd (Right)\r
+ ; Left = NextDevicePathNode (Left), Right = NextDevicePathNode (Right)\r
+ ) {\r
+ if (CompareMem (Left, Right, DevicePathNodeLength (Left)) != 0) {\r
+ if ((DevicePathType (Left) != MESSAGING_DEVICE_PATH) || (DevicePathType (Right) != MESSAGING_DEVICE_PATH)) {\r
+ return FALSE;\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
+ ) {\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+ return (BOOLEAN) (IsDevicePathEnd (Left) && IsDevicePathEnd (Right));\r
+}\r
+\r
+/**\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
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFileSystem (\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
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\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
+ 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
+ return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize);\r
+ } else {\r
+ return NULL;\r
+ }\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
+ @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 or NULL if fails.\r
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFile (\r
+ IN EFI_HANDLE LoadFileHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
+ OUT UINTN *FileSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+ VOID *FileBuffer;\r
+ BOOLEAN LoadFileSystem;\r
+ EFI_HANDLE RamDiskHandle;\r
+ UINTN BufferSize;\r
+\r
+ *FileSize = 0;\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
+\r
+ LoadFileSystem = (BOOLEAN) (Status == EFI_WARN_FILE_SYSTEM);\r
+ FileBuffer = LoadFileSystem ? AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize)) : AllocatePool (BufferSize);\r
+ if (FileBuffer == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ if (LoadFileSystem) {\r
+ FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+ } else {\r
+ FreePool (FileBuffer);\r
+ }\r
+ return NULL;\r
+ }\r
+\r
+ if (LoadFileSystem) {\r
+ FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize, &RamDiskHandle);\r
+ if (FileBuffer == NULL) {\r
+ //\r
+ // If there is no bootable executable in the populated\r
+ //\r
+ BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));\r
+ }\r
+ } else {\r
+ *FileSize = BufferSize;\r
+ *FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));\r
+ }\r
+\r
+ return FileBuffer;\r
+}\r
+\r
+/**\r
+ Get the file buffer from all the Load File instances.\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
+BmGetFileBufferFromLoadFiles (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
+ OUT UINTN *FileSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+\r
+ //\r
+ // Get file buffer from load file instance.\r
+ //\r
+ Node = FilePath;\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {\r
+ //\r
+ // When wide match happens, pass full device path to LoadFile (),\r
+ // otherwise, pass remaining device path to LoadFile ().\r
+ //\r
+ FilePath = Node;\r
+ } else {\r
+ Handle = NULL;\r
+ //\r
+ // Use wide match algorithm to find one when\r
+ // cannot find a LoadFile instance to exactly match the FilePath\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadFileProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Handles = NULL;\r
+ HandleCount = 0;\r
+ }\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ if (BmMatchHttpBootDevicePath (DevicePathFromHandle (Handles[Index]), FilePath)) {\r
+ Handle = Handles[Index];\r
+ break;\r
+ }\r
+ }\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+ }\r
+\r
+ if (Handle == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ return BmGetFileBufferFromLoadFile (Handle, FilePath, FullPath, FileSize);\r
+}\r
+\r
/**\r
Get the load option by its device path.\r
\r
// Expand the File-path device path\r
//\r
return BmExpandFileDevicePath (FilePath, FullPath, FileSize);\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
} else {\r
for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
}\r
\r
//\r
- // Fix up the boot option path if it points to a FV in memory map style of device path\r
+ // Get file buffer from FV file path.\r
//\r
- if (BmIsMemmapFvFilePath (FilePath)) {\r
- return BmGetFileBufferByMemmapFv (FilePath, FullPath, FileSize);\r
+ if (BmIsFvFilePath (FilePath)) {\r
+ return BmGetFileBufferByFvFilePath (FilePath, FullPath, FileSize);\r
}\r
\r
//\r
- // Directly reads the load option when it doesn't reside in simple file system instance (LoadFile/LoadFile2),\r
- // or it directly points to a file in simple file system instance.\r
+ // Get file buffer from simple file system.\r
//\r
Node = FilePath;\r
- Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
- FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
- if (FileBuffer != NULL) {\r
- if (EFI_ERROR (Status)) {\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
- } else {\r
- //\r
- // LoadFile () may cause the device path of the Handle be updated.\r
- //\r
- *FullPath = AppendDevicePath (DevicePathFromHandle (Handle), Node);\r
}\r
+ return FileBuffer;\r
}\r
\r
- return FileBuffer;\r
+ return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);\r
}\r
\r
/**\r
UINTN OriginalOptionNumber;\r
EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
EFI_HANDLE FvHandle;\r
VOID *FileBuffer;\r
UINTN FileSize;\r
EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
EFI_EVENT LegacyBootEvent;\r
+ UINTN RamDiskSizeInPages;\r
\r
if (BootOption == NULL) {\r
return;\r
//\r
// 5. Load EFI boot option to ImageHandle\r
//\r
- ImageHandle = NULL;\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
+ if (FileBuffer != NULL) {\r
+ RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);\r
+ }\r
DEBUG_CODE (\r
if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {\r
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));\r
(EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
);\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
// 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
- if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT) {\r
- if (PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {\r
- BmSetMemoryTypeInformationVariable ();\r
- }\r
+ if (RamDiskDevicePath == NULL) {\r
+ RamDiskSizeInPages = 0;\r
+ } else {\r
+ BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
}\r
+ BmSetMemoryTypeInformationVariable (\r
+ (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT),\r
+ RamDiskSizeInPages\r
+ );\r
\r
DEBUG_CODE_BEGIN();\r
if (BootOption->Description == NULL) {\r
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
ASSERT_EFI_ERROR (Status);\r
\r
- ImageInfo->LoadOptionsSize = BootOption->OptionalDataSize;\r
- ImageInfo->LoadOptions = BootOption->OptionalData;\r
+ if (!BmIsAutoCreateBootOption (BootOption)) {\r
+ ImageInfo->LoadOptionsSize = BootOption->OptionalDataSize;\r
+ ImageInfo->LoadOptions = BootOption->OptionalData;\r
+ }\r
\r
//\r
// Clean to NULL because the image is loaded directly from the firmwares boot manager.\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
-/**\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
- 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
- }\r
- }\r
-\r
- FreePool (Visited);\r
-}\r
-\r
/**\r
Emuerate all possible bootable medias in the following order:\r
1. Removable BlockIo - The boot option only points to the removable media\r
for (Index = 0; Index < NvBootOptionCount; Index++) {\r
if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) || \r
(DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)\r
- ) &&\r
- (NvBootOptions[Index].OptionalDataSize == sizeof (EFI_GUID)) &&\r
- CompareGuid ((EFI_GUID *) NvBootOptions[Index].OptionalData, &mBmAutoCreateBootOptionGuid)\r
+ ) && BmIsAutoCreateBootOption (&NvBootOptions[Index])\r
) {\r
//\r
// Only check those added by BDS\r