+ For EFI boot option, BDS separate them as six types:\r
+ 1. Network - The boot option points to the SimpleNetworkProtocol device.\r
+ Bds will try to automatically create this type boot option when enumerate.\r
+ 2. Shell - The boot option points to internal flash shell.\r
+ Bds will try to automatically create this type boot option when enumerate.\r
+ 3. Removable BlockIo - The boot option only points to the removable media\r
+ device, like USB flash disk, DVD, Floppy etc.\r
+ These device should contain a *removable* blockIo\r
+ protocol in their device handle.\r
+ Bds will try to automatically create this type boot option\r
+ when enumerate.\r
+ 4. Fixed BlockIo - The boot option only points to a Fixed blockIo device,\r
+ like HardDisk.\r
+ These device should contain a *fixed* blockIo\r
+ protocol in their device handle.\r
+ BDS will skip fixed blockIo devices, and NOT\r
+ automatically create boot option for them. But BDS\r
+ will help to delete those fixed blockIo boot option,\r
+ whose description rule conflict with other auto-created\r
+ boot options.\r
+ 5. Non-BlockIo Simplefile - The boot option points to a device whose handle\r
+ has SimpleFileSystem Protocol, but has no blockio\r
+ protocol. These devices do not offer blockIo\r
+ protocol, but BDS still can get the\r
+ \EFI\BOOT\boot{machinename}.EFI by SimpleFileSystem\r
+ Protocol.\r
+ 6. File - The boot option points to a file. These boot options are usually\r
+ created by user manually or OS loader. BDS will not delete or modify\r
+ these boot options.\r
+\r
+ This function will enumerate all possible boot device in the system, and\r
+ automatically create boot options for Network, Shell, Removable BlockIo,\r
+ and Non-BlockIo Simplefile devices.\r
+ It will only execute once of every boot.\r
+\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+ @retval EFI_SUCCESS Finished all the boot device enumerate and create\r
+ the boot option base on that boot device\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to enumerate the boot device and create the boot option list\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformBdsLibEnumerateAllBootOption (\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 FloppyNumber;\r
+ UINT16 HarddriveNumber;\r
+ UINT16 CdromNumber;\r
+ UINT16 UsbNumber;\r
+ UINT16 MiscNumber;\r
+ UINT16 ScsiNumber;\r
+ UINT16 NonBlockNumber;\r
+ UINTN NumberBlockIoHandles;\r
+ EFI_HANDLE *BlockIoHandles;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ BOOLEAN Removable[2];\r
+ UINTN RemovableIndex;\r
+ UINTN Index;\r
+ UINTN NumOfLoadFileHandles;\r
+ EFI_HANDLE *LoadFileHandles;\r
+ UINTN FvHandleCount;\r
+ EFI_HANDLE *FvHandleBuffer;\r
+ EFI_FV_FILETYPE Type;\r
+ UINTN Size;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN DevicePathType;\r
+ CHAR16 Buffer[40];\r
+ EFI_HANDLE *FileSystemHandles;\r
+ UINTN NumberFileSystemHandles;\r
+ BOOLEAN NeedDelete;\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ CHAR8 *PlatLang;\r
+ CHAR8 *LastLang;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+ CHAR16 *MacStr;\r
+ CHAR16 *IPverStr;\r
+ EFI_HANDLE *NetworkHandles;\r
+ UINTN BufferSize;\r
+\r
+ FloppyNumber = 0;\r
+ HarddriveNumber = 0;\r
+ CdromNumber = 0;\r
+ UsbNumber = 0;\r
+ MiscNumber = 0;\r
+ ScsiNumber = 0;\r
+ PlatLang = NULL;\r
+ LastLang = NULL;\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+ //\r
+ // If the boot device enumerate happened, just get the boot\r
+ // device from the boot order variable\r
+ //\r
+ if (mEnumBootDevice) {\r
+ GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, (VOID**)&LastLang, NULL);\r
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatLang, NULL);\r
+ ASSERT (PlatLang != NULL);\r
+ if ((LastLang != NULL) && (AsciiStrCmp (LastLang, PlatLang) == 0)) {\r
+ Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ FreePool (LastLang);\r
+ FreePool (PlatLang);\r
+ return Status;\r
+ } else {\r
+ Status = gRT->SetVariable (\r
+ LAST_ENUM_LANGUAGE_VARIABLE_NAME,\r
+ &gLastEnumLangGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ AsciiStrSize (PlatLang),\r
+ PlatLang\r
+ );\r
+ //\r
+ // Failure to set the variable only impacts the performance next time enumerating the boot options.\r
+ //\r
+\r
+ if (LastLang != NULL) {\r
+ FreePool (LastLang);\r
+ }\r
+ FreePool (PlatLang);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Notes: this dirty code is to get the legacy boot option from the\r
+ // BBS table and create to variable as the EFI boot option, it should\r
+ // be removed after the CSM can provide legacy boot option directly\r
+ //\r
+ REFRESH_LEGACY_BOOT_OPTIONS;\r
+\r
+ //\r
+ // Delete invalid boot option\r
+ //\r
+ BdsDeleteAllInvalidEfiBootOption ();\r
+\r
+ //\r
+ // Parse removable media followed by fixed media.\r
+ // The Removable[] array is used by the for-loop below to create removable media boot options \r
+ // at first, and then to create fixed media boot options.\r
+ //\r
+ Removable[0] = FALSE;\r
+ Removable[1] = TRUE;\r
+\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &NumberBlockIoHandles,\r
+ &BlockIoHandles\r
+ );\r
+\r
+ for (RemovableIndex = 0; RemovableIndex < 2; RemovableIndex++) {\r
+ for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ BlockIoHandles[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ //\r
+ // skip the logical partition\r
+ //\r
+ if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // firstly fixed block io then the removable block io\r
+ //\r
+ if (BlkIo->Media->RemovableMedia == Removable[RemovableIndex]) {\r
+ continue;\r
+ }\r
+ DevicePath = DevicePathFromHandle (BlockIoHandles[Index]);\r
+ DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
+\r
+ switch (DevicePathType) {\r
+ case BDS_EFI_ACPI_FLOPPY_BOOT:\r
+ if (FloppyNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ FloppyNumber++;\r
+ break;\r
+\r
+ //\r
+ // Assume a removable SATA device should be the DVD/CD device, a fixed SATA device should be the Hard Drive device.\r
+ //\r
+ case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
+ case BDS_EFI_MESSAGE_SATA_BOOT:\r
+ if (BlkIo->Media->RemovableMedia) {\r
+ if (CdromNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));\r
+ }\r
+ CdromNumber++;\r
+ } else {\r
+ if (HarddriveNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)), HarddriveNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)));\r
+ }\r
+ HarddriveNumber++;\r
+ }\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
+ if (UsbNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ UsbNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_SCSI_BOOT:\r
+ if (ScsiNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ ScsiNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_MISC_BOOT:\r
+ default:\r
+ if (MiscNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ MiscNumber++;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (NumberBlockIoHandles != 0) {\r
+ FreePool (BlockIoHandles);\r
+ }\r