+++ /dev/null
-/** @file\r
- BDS Lib functions which relate with create or process the boot option.\r
-\r
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "InternalBdsLib.h"\r
-#include "String.h"\r
-\r
-BOOLEAN mEnumBootDevice = FALSE;\r
-EFI_HII_HANDLE gBdsLibStringPackHandle = NULL;\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_END(NULL, "BDS", NULL, 0);\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- The constructor function register UNI strings into imageHandle.\r
-\r
- It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.\r
-\r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The constructor successfully added string package.\r
- @retval Other value The constructor can't add string package.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GenericBdsLibConstructor (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
-\r
- gBdsLibStringPackHandle = HiiAddPackages (\r
- &gBdsLibStringPackageGuid,\r
- ImageHandle,\r
- GenericBdsLibStrings,\r
- NULL\r
- );\r
-\r
- ASSERT (gBdsLibStringPackHandle != NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Deletete the Boot Option from EFI Variable. The Boot Order Arrray\r
- is also updated.\r
-\r
- @param OptionNumber The number of Boot option want to be deleted.\r
- @param BootOrder The Boot Order array.\r
- @param BootOrderSize The size of the Boot Order Array.\r
-\r
- @retval EFI_SUCCESS The Boot Option Variable was found and removed\r
- @retval EFI_UNSUPPORTED The Boot Option Variable store was inaccessible\r
- @retval EFI_NOT_FOUND The Boot Option Variable was not found\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsDeleteBootOption (\r
- IN UINTN OptionNumber,\r
- IN OUT UINT16 *BootOrder,\r
- IN OUT UINTN *BootOrderSize\r
- )\r
-{\r
- CHAR16 BootOption[9];\r
- UINTN Index;\r
- EFI_STATUS Status;\r
-\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
- Status = gRT->SetVariable (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- 0,\r
- 0,\r
- NULL\r
- );\r
- //\r
- // Deleting variable with existing variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // adjust boot order array\r
- //\r
- for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
- if (BootOrder[Index] == OptionNumber) {\r
- CopyMem (&BootOrder[Index], &BootOrder[Index+1], *BootOrderSize - (Index+1) * sizeof (UINT16));\r
- *BootOrderSize -= sizeof (UINT16);\r
- break;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-/**\r
-\r
- Translate the first n characters of an Ascii string to\r
- Unicode characters. The count n is indicated by parameter\r
- Size. If Size is greater than the length of string, then\r
- the entire string is translated.\r
-\r
-\r
- @param AStr Pointer to input Ascii string.\r
- @param Size The number of characters to translate.\r
- @param UStr Pointer to output Unicode string buffer.\r
-\r
-**/\r
-VOID\r
-AsciiToUnicodeSize (\r
- IN UINT8 *AStr,\r
- IN UINTN Size,\r
- OUT UINT16 *UStr\r
- )\r
-{\r
- UINTN Idx;\r
-\r
- Idx = 0;\r
- while (AStr[Idx] != 0) {\r
- UStr[Idx] = (CHAR16) AStr[Idx];\r
- if (Idx == Size) {\r
- break;\r
- }\r
-\r
- Idx++;\r
- }\r
- UStr[Idx] = 0;\r
-}\r
-\r
-/**\r
- Build Legacy Device Name String according.\r
-\r
- @param CurBBSEntry BBS Table.\r
- @param Index Index.\r
- @param BufSize The buffer size.\r
- @param BootString The output string.\r
-\r
-**/\r
-VOID\r
-BdsBuildLegacyDevNameString (\r
- IN BBS_TABLE *CurBBSEntry,\r
- IN UINTN Index,\r
- IN UINTN BufSize,\r
- OUT CHAR16 *BootString\r
- )\r
-{\r
- CHAR16 *Fmt;\r
- CHAR16 *Type;\r
- UINT8 *StringDesc;\r
- CHAR16 Temp[80];\r
-\r
- switch (Index) {\r
- //\r
- // Primary Master\r
- //\r
- case 1:\r
- Fmt = L"Primary Master %s";\r
- break;\r
-\r
- //\r
- // Primary Slave\r
- //\r
- case 2:\r
- Fmt = L"Primary Slave %s";\r
- break;\r
-\r
- //\r
- // Secondary Master\r
- //\r
- case 3:\r
- Fmt = L"Secondary Master %s";\r
- break;\r
-\r
- //\r
- // Secondary Slave\r
- //\r
- case 4:\r
- Fmt = L"Secondary Slave %s";\r
- break;\r
-\r
- default:\r
- Fmt = L"%s";\r
- break;\r
- }\r
-\r
- switch (CurBBSEntry->DeviceType) {\r
- case BBS_FLOPPY:\r
- Type = L"Floppy";\r
- break;\r
-\r
- case BBS_HARDDISK:\r
- Type = L"Harddisk";\r
- break;\r
-\r
- case BBS_CDROM:\r
- Type = L"CDROM";\r
- break;\r
-\r
- case BBS_PCMCIA:\r
- Type = L"PCMCIAe";\r
- break;\r
-\r
- case BBS_USB:\r
- Type = L"USB";\r
- break;\r
-\r
- case BBS_EMBED_NETWORK:\r
- Type = L"Network";\r
- break;\r
-\r
- case BBS_BEV_DEVICE:\r
- Type = L"BEVe";\r
- break;\r
-\r
- case BBS_UNKNOWN:\r
- default:\r
- Type = L"Unknown";\r
- break;\r
- }\r
- //\r
- // If current BBS entry has its description then use it.\r
- //\r
- StringDesc = (UINT8 *) (((UINTN) CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
- if (NULL != StringDesc) {\r
- //\r
- // Only get fisrt 32 characters, this is suggested by BBS spec\r
- //\r
- AsciiToUnicodeSize (StringDesc, 32, Temp);\r
- Fmt = L"%s";\r
- Type = Temp;\r
- }\r
-\r
- //\r
- // BbsTable 16 entries are for onboard IDE.\r
- // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
- //\r
- if (Index >= 5 && Index <= 16 && (CurBBSEntry->DeviceType == BBS_HARDDISK || CurBBSEntry->DeviceType == BBS_CDROM)) {\r
- Fmt = L"%s %d";\r
- UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
- } else {\r
- UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
- }\r
-}\r
-\r
-/**\r
-\r
- Create a legacy boot option for the specified entry of\r
- BBS table, save it as variable, and append it to the boot\r
- order list.\r
-\r
-\r
- @param CurrentBbsEntry Pointer to current BBS table.\r
- @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS\r
- @param Index Index of the specified entry in BBS table.\r
- @param BootOrderList On input, the original boot order list.\r
- On output, the new boot order list attached with the\r
- created node.\r
- @param BootOrderListSize On input, the original size of boot order list.\r
- On output, the size of new boot order list.\r
-\r
- @retval EFI_SUCCESS Boot Option successfully created.\r
- @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
- @retval Other Error occurs while setting variable.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsCreateLegacyBootOption (\r
- IN BBS_TABLE *CurrentBbsEntry,\r
- IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,\r
- IN UINTN Index,\r
- IN OUT UINT16 **BootOrderList,\r
- IN OUT UINTN *BootOrderListSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 CurrentBootOptionNo;\r
- UINT16 BootString[10];\r
- CHAR16 BootDesc[100];\r
- CHAR8 HelpString[100];\r
- UINT16 *NewBootOrderList;\r
- UINTN BufferSize;\r
- UINTN StringLen;\r
- VOID *Buffer;\r
- UINT8 *Ptr;\r
- UINT16 CurrentBbsDevPathSize;\r
- UINTN BootOrderIndex;\r
- UINTN BootOrderLastIndex;\r
- UINTN ArrayIndex;\r
- BOOLEAN IndexNotFound;\r
- BBS_BBS_DEVICE_PATH *NewBbsDevPathNode;\r
-\r
- if ((*BootOrderList) == NULL) {\r
- CurrentBootOptionNo = 0;\r
- } else {\r
- for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
- IndexNotFound = TRUE;\r
- for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
- if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
- IndexNotFound = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- if (!IndexNotFound) {\r
- continue;\r
- } else {\r
- break;\r
- }\r
- }\r
-\r
- CurrentBootOptionNo = (UINT16) ArrayIndex;\r
- }\r
-\r
- UnicodeSPrint (\r
- BootString,\r
- sizeof (BootString),\r
- L"Boot%04x",\r
- CurrentBootOptionNo\r
- );\r
-\r
- BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
-\r
- //\r
- // Create new BBS device path node with description string\r
- //\r
- UnicodeStrToAsciiStrS (BootDesc, HelpString, sizeof (HelpString));\r
-\r
- StringLen = AsciiStrLen (HelpString);\r
- NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
- if (NewBbsDevPathNode == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));\r
- CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);\r
- SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
-\r
- //\r
- // Create entire new CurrentBbsDevPath with end node\r
- //\r
- CurrentBbsDevPath = AppendDevicePathNode (\r
- NULL,\r
- (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode\r
- );\r
- if (CurrentBbsDevPath == NULL) {\r
- FreePool (NewBbsDevPathNode);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
-\r
- BufferSize = sizeof (UINT32) +\r
- sizeof (UINT16) +\r
- StrSize (BootDesc) +\r
- CurrentBbsDevPathSize +\r
- sizeof (BBS_TABLE) +\r
- sizeof (UINT16);\r
-\r
- Buffer = AllocateZeroPool (BufferSize);\r
- if (Buffer == NULL) {\r
- FreePool (NewBbsDevPathNode);\r
- FreePool (CurrentBbsDevPath);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Ptr = (UINT8 *) Buffer;\r
-\r
- *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
- Ptr += sizeof (UINT32);\r
-\r
- *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
- Ptr += sizeof (UINT16);\r
-\r
- CopyMem (\r
- Ptr,\r
- BootDesc,\r
- StrSize (BootDesc)\r
- );\r
- Ptr += StrSize (BootDesc);\r
-\r
- CopyMem (\r
- Ptr,\r
- CurrentBbsDevPath,\r
- CurrentBbsDevPathSize\r
- );\r
- Ptr += CurrentBbsDevPathSize;\r
-\r
- CopyMem (\r
- Ptr,\r
- CurrentBbsEntry,\r
- sizeof (BBS_TABLE)\r
- );\r
-\r
- Ptr += sizeof (BBS_TABLE);\r
- *((UINT16 *) Ptr) = (UINT16) Index;\r
-\r
- Status = gRT->SetVariable (\r
- BootString,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- BufferSize,\r
- Buffer\r
- );\r
-\r
- FreePool (Buffer);\r
-\r
- Buffer = NULL;\r
-\r
- NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
- if (NULL == NewBootOrderList) {\r
- FreePool (NewBbsDevPathNode);\r
- FreePool (CurrentBbsDevPath);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (*BootOrderList != NULL) {\r
- CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
- FreePool (*BootOrderList);\r
- }\r
-\r
- BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
- NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;\r
- *BootOrderListSize += sizeof (UINT16);\r
- *BootOrderList = NewBootOrderList;\r
-\r
- FreePool (NewBbsDevPathNode);\r
- FreePool (CurrentBbsDevPath);\r
- return Status;\r
-}\r
-\r
-/**\r
- Check if the boot option is a legacy one.\r
-\r
- @param BootOptionVar The boot option data payload.\r
- @param BbsEntry The BBS Table.\r
- @param BbsIndex The table index.\r
-\r
- @retval TRUE It is a legacy boot option.\r
- @retval FALSE It is not a legacy boot option.\r
-\r
-**/\r
-BOOLEAN\r
-BdsIsLegacyBootOption (\r
- IN UINT8 *BootOptionVar,\r
- OUT BBS_TABLE **BbsEntry,\r
- OUT UINT16 *BbsIndex\r
- )\r
-{\r
- UINT8 *Ptr;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- BOOLEAN Ret;\r
- UINT16 DevPathLen;\r
-\r
- Ptr = BootOptionVar;\r
- Ptr += sizeof (UINT32);\r
- DevPathLen = *(UINT16 *) Ptr;\r
- Ptr += sizeof (UINT16);\r
- Ptr += StrSize ((UINT16 *) Ptr);\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
- if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
- Ptr += DevPathLen;\r
- *BbsEntry = (BBS_TABLE *) Ptr;\r
- Ptr += sizeof (BBS_TABLE);\r
- *BbsIndex = *(UINT16 *) Ptr;\r
- Ret = TRUE;\r
- } else {\r
- *BbsEntry = NULL;\r
- Ret = FALSE;\r
- }\r
-\r
- return Ret;\r
-}\r
-\r
-/**\r
- Delete all the invalid legacy boot options.\r
-\r
- @retval EFI_SUCCESS All invalide legacy boot options are deleted.\r
- @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
- @retval EFI_NOT_FOUND Fail to retrive variable of boot order.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsDeleteAllInvalidLegacyBootOptions (\r
- VOID\r
- )\r
-{\r
- UINT16 *BootOrder;\r
- UINT8 *BootOptionVar;\r
- UINTN BootOrderSize;\r
- UINTN BootOptionSize;\r
- EFI_STATUS Status;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *LocalHddInfo;\r
- BBS_TABLE *LocalBbsTable;\r
- BBS_TABLE *BbsEntry;\r
- UINT16 BbsIndex;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN Index;\r
- UINT16 BootOption[10];\r
- UINT16 BootDesc[100];\r
- BOOLEAN DescStringMatch;\r
-\r
- Status = EFI_SUCCESS;\r
- BootOrder = NULL;\r
- BootOrderSize = 0;\r
- HddCount = 0;\r
- BbsCount = 0;\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\r
- BbsEntry = NULL;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- BootOrder = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\r
- if (BootOrder == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &LocalHddInfo,\r
- &BbsCount,\r
- &LocalBbsTable\r
- );\r
-\r
- Index = 0;\r
- while (Index < BootOrderSize / sizeof (UINT16)) {\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
- BootOptionVar = BdsLibGetVariableAndSize (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
- if (NULL == BootOptionVar) {\r
- BootOptionSize = 0;\r
- Status = gRT->GetVariable (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- NULL,\r
- &BootOptionSize,\r
- BootOptionVar\r
- );\r
- if (Status == EFI_NOT_FOUND) {\r
- //\r
- // Update BootOrder\r
- //\r
- BdsDeleteBootOption (\r
- BootOrder[Index],\r
- BootOrder,\r
- &BootOrderSize\r
- );\r
- continue;\r
- } else {\r
- FreePool (BootOrder);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
-\r
- //\r
- // Skip Non-Legacy boot option\r
- //\r
- if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
- if (BootOptionVar!= NULL) {\r
- FreePool (BootOptionVar);\r
- }\r
- Index++;\r
- continue;\r
- }\r
-\r
- if (BbsIndex < BbsCount) {\r
- //\r
- // Check if BBS Description String is changed\r
- //\r
- DescStringMatch = FALSE;\r
- BdsBuildLegacyDevNameString (\r
- &LocalBbsTable[BbsIndex],\r
- BbsIndex,\r
- sizeof (BootDesc),\r
- BootDesc\r
- );\r
-\r
- if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
- DescStringMatch = TRUE;\r
- }\r
-\r
- if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
- (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
- (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
- DescStringMatch) {\r
- Index++;\r
- continue;\r
- }\r
- }\r
-\r
- if (BootOptionVar != NULL) {\r
- FreePool (BootOptionVar);\r
- }\r
- //\r
- // should delete\r
- //\r
- BdsDeleteBootOption (\r
- BootOrder[Index],\r
- BootOrder,\r
- &BootOrderSize\r
- );\r
- }\r
-\r
- //\r
- // Adjust the number of boot options.\r
- //\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- //\r
- // Shrinking variable with existing variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
- FreePool (BootOrder);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Find all legacy boot option by device type.\r
-\r
- @param BootOrder The boot order array.\r
- @param BootOptionNum The number of boot option.\r
- @param DevType Device type.\r
- @param DevName Device name.\r
- @param Attribute The boot option attribute.\r
- @param BbsIndex The BBS table index.\r
- @param OptionNumber The boot option index.\r
-\r
- @retval TRUE The Legacy boot option is found.\r
- @retval FALSE The legacy boot option is not found.\r
-\r
-**/\r
-BOOLEAN\r
-BdsFindLegacyBootOptionByDevTypeAndName (\r
- IN UINT16 *BootOrder,\r
- IN UINTN BootOptionNum,\r
- IN UINT16 DevType,\r
- IN CHAR16 *DevName,\r
- OUT UINT32 *Attribute,\r
- OUT UINT16 *BbsIndex,\r
- OUT UINT16 *OptionNumber\r
- )\r
-{\r
- UINTN Index;\r
- CHAR16 BootOption[9];\r
- UINTN BootOptionSize;\r
- UINT8 *BootOptionVar;\r
- BBS_TABLE *BbsEntry;\r
- BOOLEAN Found;\r
-\r
- BbsEntry = NULL;\r
- Found = FALSE;\r
-\r
- if (NULL == BootOrder) {\r
- return Found;\r
- }\r
-\r
- //\r
- // Loop all boot option from variable\r
- //\r
- for (Index = 0; Index < BootOptionNum; Index++) {\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[Index]);\r
- BootOptionVar = BdsLibGetVariableAndSize (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
- if (NULL == BootOptionVar) {\r
- continue;\r
- }\r
-\r
- //\r
- // Skip Non-legacy boot option\r
- //\r
- if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- if (\r
- (BbsEntry->DeviceType != DevType) ||\r
- (StrCmp (DevName, (CHAR16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) != 0)\r
- ) {\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- *Attribute = *(UINT32 *) BootOptionVar;\r
- *OptionNumber = BootOrder[Index];\r
- Found = TRUE;\r
- FreePool (BootOptionVar);\r
- break;\r
- }\r
-\r
- return Found;\r
-}\r
-\r
-/**\r
- Create a legacy boot option.\r
-\r
- @param BbsItem The BBS Table entry.\r
- @param Index Index of the specified entry in BBS table.\r
- @param BootOrderList The boot order list.\r
- @param BootOrderListSize The size of boot order list.\r
-\r
- @retval EFI_OUT_OF_RESOURCE No enough memory.\r
- @retval EFI_SUCCESS The function complete successfully.\r
- @return Other value if the legacy boot option is not created.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsCreateOneLegacyBootOption (\r
- IN BBS_TABLE *BbsItem,\r
- IN UINTN Index,\r
- IN OUT UINT16 **BootOrderList,\r
- IN OUT UINTN *BootOrderListSize\r
- )\r
-{\r
- BBS_BBS_DEVICE_PATH BbsDevPathNode;\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
-\r
- DevPath = NULL;\r
-\r
- //\r
- // Create device path node.\r
- //\r
- BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;\r
- BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
- SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
- BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
- CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
-\r
- DevPath = AppendDevicePathNode (\r
- NULL,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
- );\r
- if (NULL == DevPath) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = BdsCreateLegacyBootOption (\r
- BbsItem,\r
- DevPath,\r
- Index,\r
- BootOrderList,\r
- BootOrderListSize\r
- );\r
- BbsItem->BootPriority = 0x00;\r
-\r
- FreePool (DevPath);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Add the legacy boot options from BBS table if they do not exist.\r
-\r
- @retval EFI_SUCCESS The boot options are added successfully\r
- or they are already in boot options.\r
- @retval EFI_NOT_FOUND No legacy boot options is found.\r
- @retval EFI_OUT_OF_RESOURCE No enough memory.\r
- @return Other value LegacyBoot options are not added.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsAddNonExistingLegacyBootOptions (\r
- VOID\r
- )\r
-{\r
- UINT16 *BootOrder;\r
- UINTN BootOrderSize;\r
- EFI_STATUS Status;\r
- CHAR16 Desc[100];\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *LocalHddInfo;\r
- BBS_TABLE *LocalBbsTable;\r
- UINT16 BbsIndex;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINT16 Index;\r
- UINT32 Attribute;\r
- UINT16 OptionNumber;\r
- BOOLEAN Exist;\r
-\r
- HddCount = 0;\r
- BbsCount = 0;\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &LocalHddInfo,\r
- &BbsCount,\r
- &LocalBbsTable\r
- );\r
-\r
- BootOrder = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\r
- if (BootOrder == NULL) {\r
- BootOrderSize = 0;\r
- }\r
-\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
- (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
- ) {\r
- continue;\r
- }\r
-\r
- BdsBuildLegacyDevNameString (&LocalBbsTable[Index], Index, sizeof (Desc), Desc);\r
-\r
- Exist = BdsFindLegacyBootOptionByDevTypeAndName (\r
- BootOrder,\r
- BootOrderSize / sizeof (UINT16),\r
- LocalBbsTable[Index].DeviceType,\r
- Desc,\r
- &Attribute,\r
- &BbsIndex,\r
- &OptionNumber\r
- );\r
- if (!Exist) {\r
- //\r
- // Not found such type of legacy device in boot options or we found but it's disabled\r
- // so we have to create one and put it to the tail of boot order list\r
- //\r
- Status = BdsCreateOneLegacyBootOption (\r
- &LocalBbsTable[Index],\r
- Index,\r
- &BootOrder,\r
- &BootOrderSize\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- ASSERT (BootOrder != NULL);\r
- BbsIndex = Index;\r
- OptionNumber = BootOrder[BootOrderSize / sizeof (UINT16) - 1];\r
- }\r
- }\r
-\r
- ASSERT (BbsIndex == Index);\r
- }\r
-\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- if (BootOrder != NULL) {\r
- FreePool (BootOrder);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Fill the device order buffer.\r
-\r
- @param BbsTable The BBS table.\r
- @param BbsType The BBS Type.\r
- @param BbsCount The BBS Count.\r
- @param Buf device order buffer.\r
-\r
- @return The device order buffer.\r
-\r
-**/\r
-UINT16 *\r
-BdsFillDevOrderBuf (\r
- IN BBS_TABLE *BbsTable,\r
- IN BBS_TYPE BbsType,\r
- IN UINTN BbsCount,\r
- OUT UINT16 *Buf\r
- )\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
- continue;\r
- }\r
-\r
- if (BbsTable[Index].DeviceType != BbsType) {\r
- continue;\r
- }\r
-\r
- *Buf = (UINT16) (Index & 0xFF);\r
- Buf++;\r
- }\r
-\r
- return Buf;\r
-}\r
-\r
-/**\r
- Create the device order buffer.\r
-\r
- @param BbsTable The BBS table.\r
- @param BbsCount The BBS Count.\r
-\r
- @retval EFI_SUCCES The buffer is created and the EFI variable named\r
- VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid is\r
- set correctly.\r
- @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
- @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail\r
- because of hardware error.\r
-**/\r
-EFI_STATUS\r
-BdsCreateDevOrder (\r
- IN BBS_TABLE *BbsTable,\r
- IN UINT16 BbsCount\r
- )\r
-{\r
- UINTN Index;\r
- UINTN FDCount;\r
- UINTN HDCount;\r
- UINTN CDCount;\r
- UINTN NETCount;\r
- UINTN BEVCount;\r
- UINTN TotalSize;\r
- UINTN HeaderSize;\r
- LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
- LEGACY_DEV_ORDER_ENTRY *DevOrderPtr;\r
- EFI_STATUS Status;\r
-\r
- FDCount = 0;\r
- HDCount = 0;\r
- CDCount = 0;\r
- NETCount = 0;\r
- BEVCount = 0;\r
- TotalSize = 0;\r
- HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
- DevOrder = NULL;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // Count all boot devices\r
- //\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
- continue;\r
- }\r
-\r
- switch (BbsTable[Index].DeviceType) {\r
- case BBS_FLOPPY:\r
- FDCount++;\r
- break;\r
-\r
- case BBS_HARDDISK:\r
- HDCount++;\r
- break;\r
-\r
- case BBS_CDROM:\r
- CDCount++;\r
- break;\r
-\r
- case BBS_EMBED_NETWORK:\r
- NETCount++;\r
- break;\r
-\r
- case BBS_BEV_DEVICE:\r
- BEVCount++;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
- TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
- TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
- TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
- TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
-\r
- //\r
- // Create buffer to hold all boot device order\r
- //\r
- DevOrder = AllocateZeroPool (TotalSize);\r
- if (NULL == DevOrder) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- DevOrderPtr = DevOrder;\r
-\r
- DevOrderPtr->BbsType = BBS_FLOPPY;\r
- DevOrderPtr->Length = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);\r
-\r
- DevOrderPtr->BbsType = BBS_HARDDISK;\r
- DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);\r
-\r
- DevOrderPtr->BbsType = BBS_CDROM;\r
- DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);\r
-\r
- DevOrderPtr->BbsType = BBS_EMBED_NETWORK;\r
- DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);\r
-\r
- DevOrderPtr->BbsType = BBS_BEV_DEVICE;\r
- DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);\r
-\r
- ASSERT (TotalSize == ((UINTN) DevOrderPtr - (UINTN) DevOrder));\r
-\r
- //\r
- // Save device order for legacy boot device to variable.\r
- //\r
- Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- TotalSize,\r
- DevOrder\r
- );\r
- FreePool (DevOrder);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Add the legacy boot devices from BBS table into\r
- the legacy device boot order.\r
-\r
- @retval EFI_SUCCESS The boot devices are added successfully.\r
- @retval EFI_NOT_FOUND The legacy boot devices are not found.\r
- @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough.\r
- @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable\r
- because of hardware error.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsUpdateLegacyDevOrder (\r
- VOID\r
- )\r
-{\r
- LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
- LEGACY_DEV_ORDER_ENTRY *NewDevOrder;\r
- LEGACY_DEV_ORDER_ENTRY *Ptr;\r
- LEGACY_DEV_ORDER_ENTRY *NewPtr;\r
- UINTN DevOrderSize;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- EFI_STATUS Status;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *LocalHddInfo;\r
- BBS_TABLE *LocalBbsTable;\r
- UINTN Index;\r
- UINTN Index2;\r
- UINTN *Idx;\r
- UINTN FDCount;\r
- UINTN HDCount;\r
- UINTN CDCount;\r
- UINTN NETCount;\r
- UINTN BEVCount;\r
- UINTN TotalSize;\r
- UINTN HeaderSize;\r
- UINT16 *NewFDPtr;\r
- UINT16 *NewHDPtr;\r
- UINT16 *NewCDPtr;\r
- UINT16 *NewNETPtr;\r
- UINT16 *NewBEVPtr;\r
- UINT16 *NewDevPtr;\r
- UINTN FDIndex;\r
- UINTN HDIndex;\r
- UINTN CDIndex;\r
- UINTN NETIndex;\r
- UINTN BEVIndex;\r
-\r
- Idx = NULL;\r
- FDCount = 0;\r
- HDCount = 0;\r
- CDCount = 0;\r
- NETCount = 0;\r
- BEVCount = 0;\r
- TotalSize = 0;\r
- HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
- FDIndex = 0;\r
- HDIndex = 0;\r
- CDIndex = 0;\r
- NETIndex = 0;\r
- BEVIndex = 0;\r
- NewDevPtr = NULL;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &LocalHddInfo,\r
- &BbsCount,\r
- &LocalBbsTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- DevOrder = BdsLibGetVariableAndSize (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- &DevOrderSize\r
- );\r
- if (NULL == DevOrder) {\r
- return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
- }\r
- //\r
- // First we figure out how many boot devices with same device type respectively\r
- //\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
- (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
- ) {\r
- continue;\r
- }\r
-\r
- switch (LocalBbsTable[Index].DeviceType) {\r
- case BBS_FLOPPY:\r
- FDCount++;\r
- break;\r
-\r
- case BBS_HARDDISK:\r
- HDCount++;\r
- break;\r
-\r
- case BBS_CDROM:\r
- CDCount++;\r
- break;\r
-\r
- case BBS_EMBED_NETWORK:\r
- NETCount++;\r
- break;\r
-\r
- case BBS_BEV_DEVICE:\r
- BEVCount++;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
- TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
- TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
- TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
- TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
-\r
- NewDevOrder = AllocateZeroPool (TotalSize);\r
- if (NULL == NewDevOrder) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
-\r
-\r
- //\r
- // copy FD\r
- //\r
- Ptr = DevOrder;\r
- NewPtr = NewDevOrder;\r
- NewPtr->BbsType = Ptr->BbsType;\r
- NewPtr->Length = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
- for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY\r
- ) {\r
- continue;\r
- }\r
-\r
- NewPtr->Data[FDIndex] = Ptr->Data[Index];\r
- FDIndex++;\r
- }\r
- NewFDPtr = NewPtr->Data;\r
-\r
- //\r
- // copy HD\r
- //\r
- Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
- NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
- NewPtr->BbsType = Ptr->BbsType;\r
- NewPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
- for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK\r
- ) {\r
- continue;\r
- }\r
-\r
- NewPtr->Data[HDIndex] = Ptr->Data[Index];\r
- HDIndex++;\r
- }\r
- NewHDPtr = NewPtr->Data;\r
-\r
- //\r
- // copy CD\r
- //\r
- Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
- NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
- NewPtr->BbsType = Ptr->BbsType;\r
- NewPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
- for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM\r
- ) {\r
- continue;\r
- }\r
-\r
- NewPtr->Data[CDIndex] = Ptr->Data[Index];\r
- CDIndex++;\r
- }\r
- NewCDPtr = NewPtr->Data;\r
-\r
- //\r
- // copy NET\r
- //\r
- Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
- NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
- NewPtr->BbsType = Ptr->BbsType;\r
- NewPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
- for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK\r
- ) {\r
- continue;\r
- }\r
-\r
- NewPtr->Data[NETIndex] = Ptr->Data[Index];\r
- NETIndex++;\r
- }\r
- NewNETPtr = NewPtr->Data;\r
-\r
- //\r
- // copy BEV\r
- //\r
- Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
- NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
- NewPtr->BbsType = Ptr->BbsType;\r
- NewPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
- for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE\r
- ) {\r
- continue;\r
- }\r
-\r
- NewPtr->Data[BEVIndex] = Ptr->Data[Index];\r
- BEVIndex++;\r
- }\r
- NewBEVPtr = NewPtr->Data;\r
-\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
- (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
- ) {\r
- continue;\r
- }\r
-\r
- switch (LocalBbsTable[Index].DeviceType) {\r
- case BBS_FLOPPY:\r
- Idx = &FDIndex;\r
- NewDevPtr = NewFDPtr;\r
- break;\r
-\r
- case BBS_HARDDISK:\r
- Idx = &HDIndex;\r
- NewDevPtr = NewHDPtr;\r
- break;\r
-\r
- case BBS_CDROM:\r
- Idx = &CDIndex;\r
- NewDevPtr = NewCDPtr;\r
- break;\r
-\r
- case BBS_EMBED_NETWORK:\r
- Idx = &NETIndex;\r
- NewDevPtr = NewNETPtr;\r
- break;\r
-\r
- case BBS_BEV_DEVICE:\r
- Idx = &BEVIndex;\r
- NewDevPtr = NewBEVPtr;\r
- break;\r
-\r
- default:\r
- Idx = NULL;\r
- break;\r
- }\r
- //\r
- // at this point we have copied those valid indexes to new buffer\r
- // and we should check if there is any new appeared boot device\r
- //\r
- if (Idx != NULL) {\r
- for (Index2 = 0; Index2 < *Idx; Index2++) {\r
- if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index2 == *Idx) {\r
- //\r
- // Index2 == *Idx means we didn't find Index\r
- // so Index is a new appeared device's index in BBS table\r
- // insert it before disabled indexes.\r
- //\r
- for (Index2 = 0; Index2 < *Idx; Index2++) {\r
- if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {\r
- break;\r
- }\r
- }\r
- CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));\r
- NewDevPtr[Index2] = (UINT16) (Index & 0xFF);\r
- (*Idx)++;\r
- }\r
- }\r
- }\r
-\r
- FreePool (DevOrder);\r
-\r
- Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- TotalSize,\r
- NewDevOrder\r
- );\r
- FreePool (NewDevOrder);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Set Boot Priority for specified device type.\r
-\r
- @param DeviceType The device type.\r
- @param BbsIndex The BBS index to set the highest priority. Ignore when -1.\r
- @param LocalBbsTable The BBS table.\r
- @param Priority The prority table.\r
-\r
- @retval EFI_SUCCESS The function completes successfully.\r
- @retval EFI_NOT_FOUND Failed to find device.\r
- @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device order.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsSetBootPriority4SameTypeDev (\r
- IN UINT16 DeviceType,\r
- IN UINTN BbsIndex,\r
- IN OUT BBS_TABLE *LocalBbsTable,\r
- IN OUT UINT16 *Priority\r
- )\r
-{\r
- LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
- LEGACY_DEV_ORDER_ENTRY *DevOrderPtr;\r
- UINTN DevOrderSize;\r
- UINTN Index;\r
-\r
- DevOrder = BdsLibGetVariableAndSize (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- &DevOrderSize\r
- );\r
- if (NULL == DevOrder) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- DevOrderPtr = DevOrder;\r
- while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {\r
- if (DevOrderPtr->BbsType == DeviceType) {\r
- break;\r
- }\r
-\r
- DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);\r
- }\r
-\r
- if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {\r
- FreePool (DevOrder);\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- if (BbsIndex != (UINTN) -1) {\r
- LocalBbsTable[BbsIndex].BootPriority = *Priority;\r
- (*Priority)++;\r
- }\r
- //\r
- // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
- //\r
- for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {\r
- if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {\r
- //\r
- // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
- //\r
- } else if (DevOrderPtr->Data[Index] != BbsIndex) {\r
- LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;\r
- (*Priority)++;\r
- }\r
- }\r
-\r
- FreePool (DevOrder);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Print the BBS Table.\r
-\r
- @param LocalBbsTable The BBS table.\r
- @param BbsCount The count of entry in BBS table.\r
-**/\r
-VOID\r
-PrintBbsTable (\r
- IN BBS_TABLE *LocalBbsTable,\r
- IN UINT16 BbsCount\r
- )\r
-{\r
- UINT16 Idx;\r
-\r
- DEBUG ((DEBUG_ERROR, "\n"));\r
- DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
- DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
- for (Idx = 0; Idx < BbsCount; Idx++) {\r
- if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
- (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
- (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
- ) {\r
- continue;\r
- }\r
-\r
- DEBUG (\r
- (DEBUG_ERROR,\r
- " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
- (UINTN) Idx,\r
- (UINTN) LocalBbsTable[Idx].BootPriority,\r
- (UINTN) LocalBbsTable[Idx].Bus,\r
- (UINTN) LocalBbsTable[Idx].Device,\r
- (UINTN) LocalBbsTable[Idx].Function,\r
- (UINTN) LocalBbsTable[Idx].Class,\r
- (UINTN) LocalBbsTable[Idx].SubClass,\r
- (UINTN) LocalBbsTable[Idx].DeviceType,\r
- (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
- (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
- (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
- (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
- (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
- );\r
- }\r
-\r
- DEBUG ((DEBUG_ERROR, "\n"));\r
-}\r
-\r
-/**\r
- Set the boot priority for BBS entries based on boot option entry and boot order.\r
-\r
- @param Entry The boot option is to be checked for refresh BBS table.\r
-\r
- @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.\r
- @retval EFI_NOT_FOUND BBS entries can't be found.\r
- @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsRefreshBbsTableForBoot (\r
- IN BDS_COMMON_OPTION *Entry\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 BbsIndex;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *LocalHddInfo;\r
- BBS_TABLE *LocalBbsTable;\r
- UINT16 DevType;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN Index;\r
- UINT16 Priority;\r
- UINT16 *BootOrder;\r
- UINTN BootOrderSize;\r
- UINT8 *BootOptionVar;\r
- UINTN BootOptionSize;\r
- CHAR16 BootOption[9];\r
- UINT8 *Ptr;\r
- UINT16 DevPathLen;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
- UINT16 *DeviceType;\r
- UINTN DeviceTypeCount;\r
- UINTN DeviceTypeIndex;\r
-\r
- HddCount = 0;\r
- BbsCount = 0;\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\r
- DevType = BBS_UNKNOWN;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &LocalHddInfo,\r
- &BbsCount,\r
- &LocalBbsTable\r
- );\r
- //\r
- // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
- // We will set them according to the settings setup by user\r
- //\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
- (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
- (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
- LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
- }\r
- }\r
- //\r
- // boot priority always starts at 0\r
- //\r
- Priority = 0;\r
- if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
- //\r
- // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
- //\r
- DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
- BbsIndex = *(UINT16 *) ((BBS_TABLE *) Entry->LoadOptions + 1);\r
- Status = BdsSetBootPriority4SameTypeDev (\r
- DevType,\r
- BbsIndex,\r
- LocalBbsTable,\r
- &Priority\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
- //\r
- // we have to set the boot priority for other BBS entries with different device types\r
- //\r
- BootOrder = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\r
- DeviceType = AllocatePool (BootOrderSize + sizeof (UINT16));\r
- ASSERT (DeviceType != NULL);\r
-\r
- DeviceType[0] = DevType;\r
- DeviceTypeCount = 1;\r
- for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
- BootOptionVar = BdsLibGetVariableAndSize (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
- if (NULL == BootOptionVar) {\r
- continue;\r
- }\r
-\r
- Ptr = BootOptionVar;\r
-\r
- Ptr += sizeof (UINT32);\r
- DevPathLen = *(UINT16 *) Ptr;\r
- Ptr += sizeof (UINT16);\r
- Ptr += StrSize ((UINT16 *) Ptr);\r
- DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
- if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- Ptr += DevPathLen;\r
- DevType = ((BBS_TABLE *) Ptr)->DeviceType;\r
- for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {\r
- if (DeviceType[DeviceTypeIndex] == DevType) {\r
- break;\r
- }\r
- }\r
- if (DeviceTypeIndex < DeviceTypeCount) {\r
- //\r
- // We don't want to process twice for a device type\r
- //\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- DeviceType[DeviceTypeCount] = DevType;\r
- DeviceTypeCount++;\r
-\r
- Status = BdsSetBootPriority4SameTypeDev (\r
- DevType,\r
- (UINTN) -1,\r
- LocalBbsTable,\r
- &Priority\r
- );\r
- FreePool (BootOptionVar);\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- }\r
-\r
- FreePool (DeviceType);\r
-\r
- if (BootOrder != NULL) {\r
- FreePool (BootOrder);\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
- PrintBbsTable (LocalBbsTable, BbsCount);\r
- DEBUG_CODE_END();\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Boot the legacy system with the boot option\r
-\r
- @param Option The legacy boot option which have BBS device path\r
-\r
- @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support\r
- legacy boot.\r
- @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot ().\r
-\r
-**/\r
-EFI_STATUS\r
-BdsLibDoLegacyBoot (\r
- IN BDS_COMMON_OPTION *Option\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- EFI_EVENT LegacyBootEvent;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If no LegacyBios protocol we do not support legacy boot\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Notes: if we separate the int 19, then we don't need to refresh BBS\r
- //\r
- BdsRefreshBbsTableForBoot (Option);\r
-\r
- //\r
- // Write boot to OS performance data for legacy boot.\r
- //\r
- PERF_CODE (\r
- //\r
- // Create an event to be signalled when Legacy Boot occurs to write performance data.\r
- //\r
- Status = EfiCreateEventLegacyBootEx(\r
- TPL_NOTIFY,\r
- BmEndOfBdsPerfCode,\r
- NULL,\r
- &LegacyBootEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- );\r
-\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));\r
- return LegacyBios->LegacyBoot (\r
- LegacyBios,\r
- (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
- Option->LoadOptionsSize,\r
- Option->LoadOptions\r
- );\r
-}\r
-\r
-/**\r
- Internal function to check if the input boot option is a valid EFI NV Boot####.\r
-\r
- @param OptionToCheck Boot option to be checked.\r
-\r
- @retval TRUE This boot option matches a valid EFI NV Boot####.\r
- @retval FALSE If not.\r
-\r
-**/\r
-BOOLEAN\r
-IsBootOptionValidNVVarialbe (\r
- IN BDS_COMMON_OPTION *OptionToCheck\r
- )\r
-{\r
- LIST_ENTRY TempList;\r
- BDS_COMMON_OPTION *BootOption;\r
- BOOLEAN Valid;\r
- CHAR16 OptionName[20];\r
-\r
- Valid = FALSE;\r
-\r
- InitializeListHead (&TempList);\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionToCheck->BootCurrent);\r
-\r
- BootOption = BdsLibVariableToOption (&TempList, OptionName);\r
- if (BootOption == NULL) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // If the Boot Option Number and Device Path matches, OptionToCheck matches a\r
- // valid EFI NV Boot####.\r
- //\r
- if ((OptionToCheck->BootCurrent == BootOption->BootCurrent) &&\r
- (CompareMem (OptionToCheck->DevicePath, BootOption->DevicePath, GetDevicePathSize (OptionToCheck->DevicePath)) == 0))\r
- {\r
- Valid = TRUE;\r
- }\r
-\r
- FreePool (BootOption);\r
-\r
- return Valid;\r
-}\r
-\r
-/**\r
- Check whether a USB device match the specified USB Class device path. This\r
- function follows "Load Option Processing" behavior in UEFI specification.\r
-\r
- @param UsbIo USB I/O protocol associated with the USB device.\r
- @param UsbClass The USB Class device path to match.\r
-\r
- @retval TRUE The USB device match the USB Class device path.\r
- @retval FALSE The USB device does not match the USB Class device path.\r
-\r
-**/\r
-BOOLEAN\r
-BdsMatchUsbClass (\r
- IN EFI_USB_IO_PROTOCOL *UsbIo,\r
- IN USB_CLASS_DEVICE_PATH *UsbClass\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
- EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
- UINT8 DeviceClass;\r
- UINT8 DeviceSubClass;\r
- UINT8 DeviceProtocol;\r
-\r
- if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||\r
- (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Check Vendor Id and Product Id.\r
- //\r
- Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if ((UsbClass->VendorId != 0xffff) &&\r
- (UsbClass->VendorId != DevDesc.IdVendor)) {\r
- return FALSE;\r
- }\r
-\r
- if ((UsbClass->ProductId != 0xffff) &&\r
- (UsbClass->ProductId != DevDesc.IdProduct)) {\r
- return FALSE;\r
- }\r
-\r
- DeviceClass = DevDesc.DeviceClass;\r
- DeviceSubClass = DevDesc.DeviceSubClass;\r
- DeviceProtocol = DevDesc.DeviceProtocol;\r
- if (DeviceClass == 0) {\r
- //\r
- // If Class in Device Descriptor is set to 0, use the Class, SubClass and\r
- // Protocol in Interface Descriptor instead.\r
- //\r
- Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- DeviceClass = IfDesc.InterfaceClass;\r
- DeviceSubClass = IfDesc.InterfaceSubClass;\r
- DeviceProtocol = IfDesc.InterfaceProtocol;\r
- }\r
-\r
- //\r
- // Check Class, SubClass and Protocol.\r
- //\r
- if ((UsbClass->DeviceClass != 0xff) &&\r
- (UsbClass->DeviceClass != DeviceClass)) {\r
- return FALSE;\r
- }\r
-\r
- if ((UsbClass->DeviceSubClass != 0xff) &&\r
- (UsbClass->DeviceSubClass != DeviceSubClass)) {\r
- return FALSE;\r
- }\r
-\r
- if ((UsbClass->DeviceProtocol != 0xff) &&\r
- (UsbClass->DeviceProtocol != DeviceProtocol)) {\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\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
- @param UsbIo USB I/O protocol associated with the USB device.\r
- @param UsbWwid The USB WWID device path to match.\r
-\r
- @retval TRUE The USB device match the USB WWID device path.\r
- @retval FALSE The USB device does not match the USB WWID device path.\r
-\r
-**/\r
-BOOLEAN\r
-BdsMatchUsbWwid (\r
- IN EFI_USB_IO_PROTOCOL *UsbIo,\r
- IN USB_WWID_DEVICE_PATH *UsbWwid\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
- EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
- UINT16 *LangIdTable;\r
- UINT16 TableSize;\r
- UINT16 Index;\r
- CHAR16 *CompareStr;\r
- UINTN CompareLen;\r
- CHAR16 *SerialNumberStr;\r
- UINTN Length;\r
-\r
- if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||\r
- (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP )){\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Check Vendor Id and Product Id.\r
- //\r
- Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
- if ((DevDesc.IdVendor != UsbWwid->VendorId) ||\r
- (DevDesc.IdProduct != UsbWwid->ProductId)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Check Interface Number.\r
- //\r
- Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
- if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Check Serial Number.\r
- //\r
- if (DevDesc.StrSerialNumber == 0) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Get all supported languages.\r
- //\r
- TableSize = 0;\r
- LangIdTable = NULL;\r
- Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);\r
- if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
- //\r
- CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);\r
- CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
- if (CompareStr[CompareLen - 1] == L'\0') {\r
- CompareLen--;\r
- }\r
-\r
- //\r
- // Compare serial number in each supported language.\r
- //\r
- for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {\r
- SerialNumberStr = NULL;\r
- Status = UsbIo->UsbGetStringDescriptor (\r
- UsbIo,\r
- LangIdTable[Index],\r
- DevDesc.StrSerialNumber,\r
- &SerialNumberStr\r
- );\r
- if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {\r
- continue;\r
- }\r
-\r
- Length = StrLen (SerialNumberStr);\r
- if ((Length >= CompareLen) &&\r
- (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {\r
- FreePool (SerialNumberStr);\r
- return TRUE;\r
- }\r
-\r
- FreePool (SerialNumberStr);\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Find a USB device path which match the specified short-form device path start\r
- with USB Class or USB WWID device path and load the boot file then return the\r
- image handle. If ParentDevicePath is NULL, this function will search in all USB\r
- devices of the platform. If ParentDevicePath is not NULL,this function will only\r
- search in its child devices.\r
-\r
- @param ParentDevicePath The device path of the parent.\r
- @param ShortFormDevicePath The USB Class or USB WWID device path to match.\r
-\r
- @return The image Handle if find load file from specified short-form device path\r
- or NULL if not found.\r
-\r
-**/\r
-EFI_HANDLE *\r
-BdsFindUsbDevice (\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ShortFormDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN UsbIoHandleCount;\r
- EFI_HANDLE *UsbIoHandleBuffer;\r
- EFI_DEVICE_PATH_PROTOCOL *UsbIoDevicePath;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- UINTN Index;\r
- UINTN ParentSize;\r
- UINTN Size;\r
- EFI_HANDLE ImageHandle;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *NextDevicePath;\r
-\r
- FullDevicePath = NULL;\r
- ImageHandle = NULL;\r
-\r
- //\r
- // Get all UsbIo Handles.\r
- //\r
- UsbIoHandleCount = 0;\r
- UsbIoHandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiUsbIoProtocolGuid,\r
- NULL,\r
- &UsbIoHandleCount,\r
- &UsbIoHandleBuffer\r
- );\r
- if (EFI_ERROR (Status) || (UsbIoHandleCount == 0) || (UsbIoHandleBuffer == NULL)) {\r
- return NULL;\r
- }\r
-\r
- ParentSize = (ParentDevicePath == NULL) ? 0 : GetDevicePathSize (ParentDevicePath);\r
- for (Index = 0; Index < UsbIoHandleCount; Index++) {\r
- //\r
- // Get the Usb IO interface.\r
- //\r
- Status = gBS->HandleProtocol(\r
- UsbIoHandleBuffer[Index],\r
- &gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- UsbIoDevicePath = DevicePathFromHandle (UsbIoHandleBuffer[Index]);\r
- if (UsbIoDevicePath == NULL) {\r
- continue;\r
- }\r
-\r
- if (ParentDevicePath != NULL) {\r
- //\r
- // Compare starting part of UsbIoHandle's device path with ParentDevicePath.\r
- //\r
- Size = GetDevicePathSize (UsbIoDevicePath);\r
- if ((Size < ParentSize) ||\r
- (CompareMem (UsbIoDevicePath, ParentDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0)) {\r
- continue;\r
- }\r
- }\r
-\r
- if (BdsMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ShortFormDevicePath) ||\r
- BdsMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ShortFormDevicePath)) {\r
- //\r
- // Try to find if there is the boot file in this DevicePath\r
- //\r
- NextDevicePath = NextDevicePathNode (ShortFormDevicePath);\r
- if (!IsDevicePathEnd (NextDevicePath)) {\r
- FullDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePath);\r
- //\r
- // Connect the full device path, so that Simple File System protocol\r
- // could be installed for this USB device.\r
- //\r
- BdsLibConnectDevicePath (FullDevicePath);\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
- Status = gBS->LoadImage (\r
- TRUE,\r
- gImageHandle,\r
- FullDevicePath,\r
- NULL,\r
- 0,\r
- &ImageHandle\r
- );\r
- FreePool (FullDevicePath);\r
- } else {\r
- FullDevicePath = UsbIoDevicePath;\r
- Status = EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // If we didn't find an image directly, we need to try as if it is a removable device boot option\r
- // and load the image according to the default boot behavior for removable device.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // check if there is a bootable removable media could be found in this device path ,\r
- // and get the bootable media handle\r
- //\r
- Handle = BdsLibGetBootableHandle(UsbIoDevicePath);\r
- if (Handle == NULL) {\r
- continue;\r
- }\r
- //\r
- // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
- // machinename is ia32, ia64, x64, ...\r
- //\r
- FullDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
- if (FullDevicePath != NULL) {\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
- Status = gBS->LoadImage (\r
- TRUE,\r
- gImageHandle,\r
- FullDevicePath,\r
- NULL,\r
- 0,\r
- &ImageHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // The DevicePath failed, and it's not a valid\r
- // removable media device.\r
- //\r
- continue;\r
- }\r
- } else {\r
- continue;\r
- }\r
- }\r
- break;\r
- }\r
- }\r
-\r
- FreePool (UsbIoHandleBuffer);\r
- return ImageHandle;\r
-}\r
-\r
-/**\r
- Expand USB Class or USB WWID device path node to be full device path of a USB\r
- device in platform then load the boot file on this full device path and return the\r
- image handle.\r
-\r
- This function support following 4 cases:\r
- 1) Boot Option device path starts with a USB Class or USB WWID device path,\r
- and there is no Media FilePath device path in the end.\r
- In this case, it will follow Removable Media Boot Behavior.\r
- 2) Boot Option device path starts with a USB Class or USB WWID device path,\r
- and ended with Media FilePath device path.\r
- 3) Boot Option device path starts with a full device path to a USB Host Controller,\r
- contains a USB Class or USB WWID device path node, while not ended with Media\r
- FilePath device path. In this case, it will follow Removable Media Boot Behavior.\r
- 4) Boot Option device path starts with a full device path to a USB Host Controller,\r
- contains a USB Class or USB WWID device path node, and ended with Media\r
- FilePath device path.\r
-\r
- @param DevicePath The Boot Option device path.\r
-\r
- @return The image handle of boot file, or NULL if there is no boot file found in\r
- the specified USB Class or USB WWID device path.\r
-\r
-**/\r
-EFI_HANDLE *\r
-BdsExpandUsbShortFormDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_HANDLE *ImageHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *ShortFormDevicePath;\r
-\r
- //\r
- // Search for USB Class or USB WWID device path node.\r
- //\r
- ShortFormDevicePath = NULL;\r
- ImageHandle = NULL;\r
- TempDevicePath = DevicePath;\r
- while (!IsDevicePathEnd (TempDevicePath)) {\r
- if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
- ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) ||\r
- (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) {\r
- ShortFormDevicePath = TempDevicePath;\r
- break;\r
- }\r
- TempDevicePath = NextDevicePathNode (TempDevicePath);\r
- }\r
-\r
- if (ShortFormDevicePath == NULL) {\r
- //\r
- // No USB Class or USB WWID device path node found, do nothing.\r
- //\r
- return NULL;\r
- }\r
-\r
- if (ShortFormDevicePath == DevicePath) {\r
- //\r
- // Boot Option device path starts with USB Class or USB WWID device path.\r
- //\r
- ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath);\r
- if (ImageHandle == NULL) {\r
- //\r
- // Failed to find a match in existing devices, connect the short form USB\r
- // device path and try again.\r
- //\r
- BdsLibConnectUsbDevByShortFormDP (0xff, ShortFormDevicePath);\r
- ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath);\r
- }\r
- } else {\r
- //\r
- // Boot Option device path contains USB Class or USB WWID device path node.\r
- //\r
-\r
- //\r
- // Prepare the parent device path for search.\r
- //\r
- TempDevicePath = DuplicateDevicePath (DevicePath);\r
- ASSERT (TempDevicePath != NULL);\r
- SetDevicePathEndNode (((UINT8 *) TempDevicePath) + ((UINTN) ShortFormDevicePath - (UINTN) DevicePath));\r
-\r
- //\r
- // The USB Host Controller device path is already in Boot Option device path\r
- // and USB Bus driver already support RemainingDevicePath starts with USB\r
- // Class or USB WWID device path, so just search in existing USB devices and\r
- // doesn't perform ConnectController here.\r
- //\r
- ImageHandle = BdsFindUsbDevice (TempDevicePath, ShortFormDevicePath);\r
- FreePool (TempDevicePath);\r
- }\r
-\r
- return ImageHandle;\r
-}\r
-\r
-/**\r
- Process the boot option follow the UEFI specification and\r
- special treat the legacy boot option with BBS_DEVICE_PATH.\r
-\r
- @param Option The boot option need to be processed\r
- @param DevicePath The device path which describe where to load the\r
- boot image or the legacy BBS device path to boot\r
- the legacy OS\r
- @param ExitDataSize The size of exit data.\r
- @param ExitData Data returned when Boot image failed.\r
-\r
- @retval EFI_SUCCESS Boot from the input boot option successfully.\r
- @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibBootViaBootOption (\r
- IN BDS_COMMON_OPTION *Option,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- OUT UINTN *ExitDataSize,\r
- OUT CHAR16 **ExitData OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_STATUS StatusLogo;\r
- EFI_HANDLE Handle;\r
- EFI_HANDLE ImageHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
- EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;\r
- LIST_ENTRY TempBootLists;\r
- EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
-\r
- Status = EFI_SUCCESS;\r
- *ExitDataSize = 0;\r
- *ExitData = NULL;\r
-\r
- //\r
- // If it's Device Path that starts with a hard drive path, append it with the front part to compose a\r
- // full device path\r
- //\r
- WorkingDevicePath = NULL;\r
- if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
- (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {\r
- WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (\r
- (HARDDRIVE_DEVICE_PATH *)DevicePath\r
- );\r
- if (WorkingDevicePath != NULL) {\r
- DevicePath = WorkingDevicePath;\r
- }\r
- }\r
-\r
- //\r
- // Set Boot Current\r
- //\r
- if (IsBootOptionValidNVVarialbe (Option)) {\r
- //\r
- // For a temporary boot (i.e. a boot by selected a EFI Shell using "Boot From File"), Boot Current is actually not valid.\r
- // In this case, "BootCurrent" is not created.\r
- // Only create the BootCurrent variable when it points to a valid Boot#### variable.\r
- //\r
- SetVariableAndReportStatusCodeOnError (\r
- L"BootCurrent",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof (UINT16),\r
- &Option->BootCurrent\r
- );\r
- }\r
-\r
- //\r
- // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
- //\r
- EfiSignalEventReadyToBoot();\r
-\r
- //\r
- // Report Status Code to indicate ReadyToBoot event was signalled\r
- //\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));\r
-\r
- //\r
- // Expand USB Class or USB WWID device path node to be full device path of a USB\r
- // device in platform then load the boot file on this full device path and get the\r
- // image handle.\r
- //\r
- ImageHandle = BdsExpandUsbShortFormDevicePath (DevicePath);\r
-\r
- //\r
- // 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
- BdsSetMemoryTypeInformationVariable ();\r
-\r
- //\r
- // By expanding the USB Class or WWID device path, the ImageHandle has returnned.\r
- // Here get the ImageHandle for the non USB class or WWID device path.\r
- //\r
- if (ImageHandle == NULL) {\r
- ASSERT (Option->DevicePath != NULL);\r
- if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
- (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
- ) {\r
- //\r
- // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
- //\r
- return BdsLibDoLegacyBoot (Option);\r
- }\r
-\r
- //\r
- // If the boot option point to Internal FV shell, make sure it is valid\r
- //\r
- Status = BdsLibUpdateFvFileDevicePath (&DevicePath, PcdGetPtr(PcdShellFile));\r
- if (!EFI_ERROR(Status)) {\r
- if (Option->DevicePath != NULL) {\r
- FreePool(Option->DevicePath);\r
- }\r
- Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
- ASSERT(Option->DevicePath != NULL);\r
- CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
- //\r
- // Update the shell boot option\r
- //\r
- InitializeListHead (&TempBootLists);\r
- BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
-\r
- //\r
- // free the temporary device path created by BdsLibUpdateFvFileDevicePath()\r
- //\r
- FreePool (DevicePath);\r
- DevicePath = Option->DevicePath;\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
-\r
- if (Option->Description == NULL) {\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting from unknown device path\n"));\r
- } else {\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
- }\r
-\r
- DEBUG_CODE_END();\r
-\r
- //\r
- // Report status code for OS Loader LoadImage.\r
- //\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
- Status = gBS->LoadImage (\r
- TRUE,\r
- gImageHandle,\r
- DevicePath,\r
- NULL,\r
- 0,\r
- &ImageHandle\r
- );\r
-\r
- //\r
- // If we didn't find an image directly, we need to try as if it is a removable device boot option\r
- // and load the image according to the default boot behavior for removable device.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // check if there is a bootable removable media could be found in this device path ,\r
- // and get the bootable media handle\r
- //\r
- Handle = BdsLibGetBootableHandle(DevicePath);\r
- if (Handle != NULL) {\r
- //\r
- // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
- // machinename is ia32, ia64, x64, ...\r
- //\r
- FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
- if (FilePath != NULL) {\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
- Status = gBS->LoadImage (\r
- TRUE,\r
- gImageHandle,\r
- FilePath,\r
- NULL,\r
- 0,\r
- &ImageHandle\r
- );\r
- }\r
- }\r
- }\r
- }\r
- //\r
- // Provide the image with it's load options\r
- //\r
- if ((ImageHandle == NULL) || (EFI_ERROR(Status))) {\r
- //\r
- // Report Status Code 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
- goto Done;\r
- }\r
-\r
- Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (Option->LoadOptionsSize != 0) {\r
- ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
- ImageInfo->LoadOptions = Option->LoadOptions;\r
- }\r
-\r
- //\r
- // Clean to NULL because the image is loaded directly from the firmwares boot manager.\r
- //\r
- ImageInfo->ParentHandle = NULL;\r
-\r
- //\r
- // Before calling the image, enable the Watchdog Timer for\r
- // the 5 Minute period\r
- //\r
- gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
-\r
- //\r
- // Write boot to OS performance data for UEFI boot\r
- //\r
- PERF_CODE (\r
- BmEndOfBdsPerfCode (NULL, NULL);\r
- );\r
-\r
- //\r
- // Report status code for OS Loader StartImage.\r
- //\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));\r
-\r
- Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Report Status Code 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
- }\r
-\r
- //\r
- // Clear the Watchdog Timer after the image returns\r
- //\r
- gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
-\r
-Done:\r
- //\r
- // Set Logo status invalid after trying one boot option\r
- //\r
- BootLogo = NULL;\r
- StatusLogo = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
- if (!EFI_ERROR (StatusLogo) && (BootLogo != NULL)) {\r
- BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r
- }\r
-\r
- //\r
- // Clear Boot Current\r
- // Deleting variable with current implementation shouldn't fail.\r
- //\r
- gRT->SetVariable (\r
- L"BootCurrent",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- 0,\r
- NULL\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Expand a device path that starts with a hard drive media device path node to be a\r
- full device path that includes the full hardware path to the device. We need\r
- to do this so it can be booted. As an optimization the front match (the part point\r
- to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable\r
- so a connect all is not required on every boot. All successful history device path\r
- which point to partition node (the front part) will be saved.\r
-\r
- @param HardDriveDevicePath EFI Device Path to boot, if it starts with a hard\r
- drive media device path.\r
- @return A Pointer to the full device path or NULL if a valid Hard Drive devic path\r
- cannot be found.\r
-\r
-**/\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EFIAPI\r
-BdsExpandPartitionPartialDevicePathToFull (\r
- IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN BlockIoHandleCount;\r
- EFI_HANDLE *BlockIoBuffer;\r
- EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UINTN Index;\r
- UINTN InstanceNum;\r
- EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
- UINTN CachedDevicePathSize;\r
- BOOLEAN DeviceExist;\r
- BOOLEAN NeedAdjust;\r
- EFI_DEVICE_PATH_PROTOCOL *Instance;\r
- UINTN Size;\r
-\r
- FullDevicePath = NULL;\r
- //\r
- // Check if there is prestore HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable.\r
- // If exist, search the front path which point to partition node in the variable instants.\r
- // If fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, reconnect all and search in all system\r
- //\r
- GetVariable2 (\r
- HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
- &gHdBootDevicePathVariablGuid,\r
- (VOID **) &CachedDevicePath,\r
- &CachedDevicePathSize\r
- );\r
-\r
- //\r
- // Delete the invalid HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable.\r
- //\r
- if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) {\r
- FreePool (CachedDevicePath);\r
- CachedDevicePath = NULL;\r
- Status = gRT->SetVariable (\r
- HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
- &gHdBootDevicePathVariablGuid,\r
- 0,\r
- 0,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- if (CachedDevicePath != NULL) {\r
- TempNewDevicePath = CachedDevicePath;\r
- DeviceExist = FALSE;\r
- NeedAdjust = FALSE;\r
- do {\r
- //\r
- // Check every instance of the variable\r
- // First, check whether the instance contain the partition node, which is needed for distinguishing multi\r
- // partial partition boot option. Second, check whether the instance could be connected.\r
- //\r
- Instance = GetNextDevicePathInstance (&TempNewDevicePath, &Size);\r
- if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {\r
- //\r
- // Connect the device path instance, the device path point to hard drive media device path node\r
- // e.g. ACPI() /PCI()/ATA()/Partition()\r
- //\r
- Status = BdsLibConnectDevicePath (Instance);\r
- if (!EFI_ERROR (Status)) {\r
- DeviceExist = TRUE;\r
- break;\r
- }\r
- }\r
- //\r
- // Come here means the first instance is not matched\r
- //\r
- NeedAdjust = TRUE;\r
- FreePool(Instance);\r
- } while (TempNewDevicePath != NULL);\r
-\r
- if (DeviceExist) {\r
- //\r
- // Find the matched device path.\r
- // Append the file path information from the boot option and return the fully expanded device path.\r
- //\r
- DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
- FullDevicePath = AppendDevicePath (Instance, DevicePath);\r
-\r
- //\r
- // Adjust the HD_BOOT_DEVICE_PATH_VARIABLE_NAME instances sequence if the matched one is not first one.\r
- //\r
- if (NeedAdjust) {\r
- //\r
- // First delete the matched instance.\r
- //\r
- TempNewDevicePath = CachedDevicePath;\r
- CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, Instance );\r
- FreePool (TempNewDevicePath);\r
-\r
- //\r
- // Second, append the remaining path after the matched instance\r
- //\r
- TempNewDevicePath = CachedDevicePath;\r
- CachedDevicePath = AppendDevicePathInstance (Instance, CachedDevicePath );\r
- FreePool (TempNewDevicePath);\r
- //\r
- // Save the matching Device Path so we don't need to do a connect all next time\r
- // Failure to set the variable only impacts the performance when next time expanding the short-form device path.\r
- //\r
- Status = gRT->SetVariable (\r
- HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
- &gHdBootDevicePathVariablGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- GetDevicePathSize (CachedDevicePath),\r
- CachedDevicePath\r
- );\r
- }\r
-\r
- FreePool (Instance);\r
- FreePool (CachedDevicePath);\r
- return FullDevicePath;\r
- }\r
- }\r
-\r
- //\r
- // If we get here we fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, and now we need\r
- // to search all devices in the system for a matched partition\r
- //\r
- BdsLibConnectAllDriversToAllControllers ();\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
- if (EFI_ERROR (Status) || BlockIoHandleCount == 0 || BlockIoBuffer == NULL) {\r
- //\r
- // If there was an error or there are no device handles that support\r
- // the BLOCK_IO Protocol, then return.\r
- //\r
- return NULL;\r
- }\r
- //\r
- // Loop through all the device handles that support the BLOCK_IO Protocol\r
- //\r
- for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
-\r
- Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
- if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
- continue;\r
- }\r
-\r
- if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {\r
- //\r
- // Find the matched partition device path\r
- //\r
- DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
- FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
-\r
- //\r
- // Save the matched partition device path in HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable\r
- //\r
- if (CachedDevicePath != NULL) {\r
- //\r
- // Save the matched partition device path as first instance of HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable\r
- //\r
- if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {\r
- TempNewDevicePath = CachedDevicePath;\r
- CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);\r
- FreePool(TempNewDevicePath);\r
- }\r
-\r
- if (CachedDevicePath != NULL) {\r
- TempNewDevicePath = CachedDevicePath;\r
- CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
- FreePool(TempNewDevicePath);\r
- } else {\r
- CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
- }\r
-\r
- //\r
- // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
- // If the user try to boot many OS in different HDs or partitions, in theory,\r
- // the HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable maybe become larger and larger.\r
- //\r
- InstanceNum = 0;\r
- ASSERT (CachedDevicePath != NULL);\r
- TempNewDevicePath = CachedDevicePath;\r
- while (!IsDevicePathEnd (TempNewDevicePath)) {\r
- TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
- //\r
- // Parse one instance\r
- //\r
- while (!IsDevicePathEndType (TempNewDevicePath)) {\r
- TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
- }\r
- InstanceNum++;\r
- //\r
- // If the CachedDevicePath variable contain too much instance, only remain 12 instances.\r
- //\r
- if (InstanceNum >= 12) {\r
- SetDevicePathEndNode (TempNewDevicePath);\r
- break;\r
- }\r
- }\r
- } else {\r
- CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
- }\r
-\r
- //\r
- // Save the matching Device Path so we don't need to do a connect all next time\r
- // Failure to set the variable only impacts the performance when next time expanding the short-form device path.\r
- //\r
- Status = gRT->SetVariable (\r
- HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
- &gHdBootDevicePathVariablGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- GetDevicePathSize (CachedDevicePath),\r
- CachedDevicePath\r
- );\r
-\r
- break;\r
- }\r
- }\r
-\r
- if (CachedDevicePath != NULL) {\r
- FreePool (CachedDevicePath);\r
- }\r
- if (BlockIoBuffer != NULL) {\r
- FreePool (BlockIoBuffer);\r
- }\r
- return FullDevicePath;\r
-}\r
-\r
-/**\r
- Check whether there is a instance in BlockIoDevicePath, which contain multi device path\r
- instances, has the same partition node with HardDriveDevicePath device path\r
-\r
- @param BlockIoDevicePath Multi device path instances which need to check\r
- @param HardDriveDevicePath A device path which starts with a hard drive media\r
- device path.\r
-\r
- @retval TRUE There is a matched device path instance.\r
- @retval FALSE There is no matched device path instance.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-MatchPartitionDevicePathNode (\r
- IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,\r
- IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
- )\r
-{\r
- HARDDRIVE_DEVICE_PATH *TmpHdPath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- BOOLEAN Match;\r
- EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePathNode;\r
-\r
- if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Make PreviousDevicePath == the device path node before the end node\r
- //\r
- DevicePath = BlockIoDevicePath;\r
- BlockIoHdDevicePathNode = NULL;\r
-\r
- //\r
- // find the partition device path node\r
- //\r
- while (!IsDevicePathEnd (DevicePath)) {\r
- if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
- (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
- ) {\r
- BlockIoHdDevicePathNode = DevicePath;\r
- break;\r
- }\r
-\r
- DevicePath = NextDevicePathNode (DevicePath);\r
- }\r
-\r
- if (BlockIoHdDevicePathNode == NULL) {\r
- return FALSE;\r
- }\r
- //\r
- // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
- //\r
- TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;\r
- Match = FALSE;\r
-\r
- //\r
- // Check for the match\r
- //\r
- if ((TmpHdPath->MBRType == HardDriveDevicePath->MBRType) &&\r
- (TmpHdPath->SignatureType == HardDriveDevicePath->SignatureType)) {\r
- switch (TmpHdPath->SignatureType) {\r
- case SIGNATURE_TYPE_GUID:\r
- Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)HardDriveDevicePath->Signature);\r
- break;\r
- case SIGNATURE_TYPE_MBR:\r
- Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == ReadUnaligned32((UINT32 *)(&(HardDriveDevicePath->Signature[0]))));\r
- break;\r
- default:\r
- Match = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- return Match;\r
-}\r
-\r
-/**\r
- Delete the boot option associated with the handle passed in.\r
-\r
- @param Handle The handle which present the device path to create\r
- boot option\r
-\r
- @retval EFI_SUCCESS Delete the boot option success\r
- @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
- @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
- @retval Other Error return value from SetVariable()\r
-\r
-**/\r
-EFI_STATUS\r
-BdsLibDeleteOptionFromHandle (\r
- IN EFI_HANDLE Handle\r
- )\r
-{\r
- UINT16 *BootOrder;\r
- UINT8 *BootOptionVar;\r
- UINTN BootOrderSize;\r
- UINTN BootOptionSize;\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
- UINTN DevicePathSize;\r
- UINTN OptionDevicePathSize;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
- UINT8 *TempPtr;\r
-\r
- Status = EFI_SUCCESS;\r
- BootOrder = NULL;\r
- BootOrderSize = 0;\r
-\r
- //\r
- // Check "BootOrder" variable, if no, means there is no any boot order.\r
- //\r
- BootOrder = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\r
- if (BootOrder == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Convert device handle to device path protocol instance\r
- //\r
- DevicePath = DevicePathFromHandle (Handle);\r
- if (DevicePath == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
- DevicePathSize = GetDevicePathSize (DevicePath);\r
-\r
- //\r
- // Loop all boot order variable and find the matching device path\r
- //\r
- Index = 0;\r
- while (Index < BootOrderSize / sizeof (UINT16)) {\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
- BootOptionVar = BdsLibGetVariableAndSize (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
-\r
- if (BootOptionVar == NULL) {\r
- FreePool (BootOrder);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (!ValidateOption(BootOptionVar, BootOptionSize)) {\r
- BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
- FreePool (BootOptionVar);\r
- Index++;\r
- continue;\r
- }\r
-\r
- TempPtr = BootOptionVar;\r
- TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
- TempPtr += StrSize ((CHAR16 *) TempPtr);\r
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
- OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
-\r
- //\r
- // Check whether the device path match\r
- //\r
- if ((OptionDevicePathSize == DevicePathSize) &&\r
- (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {\r
- BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
- FreePool (BootOptionVar);\r
- break;\r
- }\r
-\r
- FreePool (BootOptionVar);\r
- Index++;\r
- }\r
-\r
- //\r
- // Adjust number of boot option for "BootOrder" variable.\r
- //\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- //\r
- // Shrinking variable with existing variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FreePool (BootOrder);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Delete all invalid EFI boot options.\r
-\r
- @retval EFI_SUCCESS Delete all invalid boot option success\r
- @retval EFI_NOT_FOUND Variable "BootOrder" is not found\r
- @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
- @retval Other Error return value from SetVariable()\r
-\r
-**/\r
-EFI_STATUS\r
-BdsDeleteAllInvalidEfiBootOption (\r
- VOID\r
- )\r
-{\r
- UINT16 *BootOrder;\r
- UINT8 *BootOptionVar;\r
- UINTN BootOrderSize;\r
- UINTN BootOptionSize;\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN Index2;\r
- UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
- UINT8 *TempPtr;\r
- CHAR16 *Description;\r
- BOOLEAN Corrupted;\r
-\r
- Status = EFI_SUCCESS;\r
- BootOrder = NULL;\r
- Description = NULL;\r
- OptionDevicePath = NULL;\r
- BootOrderSize = 0;\r
- Corrupted = FALSE;\r
-\r
- //\r
- // Check "BootOrder" variable firstly, this variable hold the number of boot options\r
- //\r
- BootOrder = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\r
- if (NULL == BootOrder) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- Index = 0;\r
- while (Index < BootOrderSize / sizeof (UINT16)) {\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
- BootOptionVar = BdsLibGetVariableAndSize (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
- if (NULL == BootOptionVar) {\r
- FreePool (BootOrder);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (!ValidateOption(BootOptionVar, BootOptionSize)) {\r
- Corrupted = TRUE;\r
- } else {\r
- TempPtr = BootOptionVar;\r
- TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
- Description = (CHAR16 *) TempPtr;\r
- TempPtr += StrSize ((CHAR16 *) TempPtr);\r
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
-\r
- //\r
- // Skip legacy boot option (BBS boot device)\r
- //\r
- if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&\r
- (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {\r
- FreePool (BootOptionVar);\r
- Index++;\r
- continue;\r
- }\r
- }\r
-\r
- if (Corrupted || !BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) {\r
- //\r
- // Delete this invalid boot option "Boot####"\r
- //\r
- Status = gRT->SetVariable (\r
- BootOption,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- 0,\r
- NULL\r
- );\r
- //\r
- // Deleting variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
- //\r
- // Mark this boot option in boot order as deleted\r
- //\r
- BootOrder[Index] = 0xffff;\r
- Corrupted = FALSE;\r
- }\r
-\r
- FreePool (BootOptionVar);\r
- Index++;\r
- }\r
-\r
- //\r
- // Adjust boot order array\r
- //\r
- Index2 = 0;\r
- for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
- if (BootOrder[Index] != 0xffff) {\r
- BootOrder[Index2] = BootOrder[Index];\r
- Index2 ++;\r
- }\r
- }\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- Index2 * sizeof (UINT16),\r
- BootOrder\r
- );\r
- //\r
- // Shrinking variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FreePool (BootOrder);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- 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
-BdsLibEnumerateAllBootOption (\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
-\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
-\r
- //\r
- // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.\r
- //\r
- NonBlockNumber = 0;\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- NULL,\r
- &NumberFileSystemHandles,\r
- &FileSystemHandles\r
- );\r
- for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
- Status = gBS->HandleProtocol (\r
- FileSystemHandles[Index],\r
- &gEfiBlockIoProtocolGuid,\r
- (VOID **) &BlkIo\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Skip if the file system handle supports a BlkIo protocol,\r
- //\r
- continue;\r
- }\r
-\r
- //\r
- // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
- // machinename is ia32, ia64, x64, ...\r
- //\r
- Hdr.Union = &HdrData;\r
- NeedDelete = TRUE;\r
- Status = BdsLibGetImageHeader (\r
- FileSystemHandles[Index],\r
- EFI_REMOVABLE_MEDIA_FILE_NAME,\r
- &DosHeader,\r
- Hdr\r
- );\r
- if (!EFI_ERROR (Status) &&\r
- EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
- Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
- NeedDelete = FALSE;\r
- }\r
-\r
- if (NeedDelete) {\r
- //\r
- // No such file or the file is not a EFI application, delete this boot option\r
- //\r
- BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
- } else {\r
- if (NonBlockNumber != 0) {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);\r
- } else {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));\r
- }\r
- BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
- NonBlockNumber++;\r
- }\r
- }\r
-\r
- if (NumberFileSystemHandles != 0) {\r
- FreePool (FileSystemHandles);\r
- }\r
-\r
- //\r
- // Parse Network Boot Device\r
- //\r
- NumOfLoadFileHandles = 0;\r
- //\r
- // Search Load File protocol for PXE boot option.\r
- //\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiLoadFileProtocolGuid,\r
- NULL,\r
- &NumOfLoadFileHandles,\r
- &LoadFileHandles\r
- );\r
-\r
- for (Index = 0; Index < NumOfLoadFileHandles; Index++) {\r
- if (Index != 0) {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), Index);\r
- } else {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)));\r
- }\r
- BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);\r
- }\r
-\r
- if (NumOfLoadFileHandles != 0) {\r
- FreePool (LoadFileHandles);\r
- }\r
-\r
- //\r
- // Check if we have on flash shell\r
- //\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- NULL,\r
- &FvHandleCount,\r
- &FvHandleBuffer\r
- );\r
- for (Index = 0; Index < FvHandleCount; Index++) {\r
- gBS->HandleProtocol (\r
- FvHandleBuffer[Index],\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) &Fv\r
- );\r
-\r
- Status = Fv->ReadFile (\r
- Fv,\r
- PcdGetPtr(PcdShellFile),\r
- NULL,\r
- &Size,\r
- &Type,\r
- &Attributes,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Skip if no shell file in the FV\r
- //\r
- continue;\r
- }\r
- //\r
- // Build the shell boot option\r
- //\r
- BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
- }\r
-\r
- if (FvHandleCount != 0) {\r
- FreePool (FvHandleBuffer);\r
- }\r
- //\r
- // Make sure every boot only have one time\r
- // boot device enumerate\r
- //\r
- Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
- mEnumBootDevice = TRUE;\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Build the boot option with the handle parsed in\r
-\r
- @param Handle The handle which present the device path to create\r
- boot option\r
- @param BdsBootOptionList The header of the link list which indexed all\r
- current boot options\r
- @param String The description of the boot option.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsLibBuildOptionFromHandle (\r
- IN EFI_HANDLE Handle,\r
- IN LIST_ENTRY *BdsBootOptionList,\r
- IN CHAR16 *String\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- DevicePath = DevicePathFromHandle (Handle);\r
-\r
- //\r
- // Create and register new boot option\r
- //\r
- BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");\r
-}\r
-\r
-\r
-/**\r
- Build the on flash shell boot option with the handle parsed in.\r
-\r
- @param Handle The handle which present the device path to create\r
- on flash shell boot option\r
- @param BdsBootOptionList The header of the link list which indexed all\r
- current boot options\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsLibBuildOptionFromShell (\r
- IN EFI_HANDLE Handle,\r
- IN OUT LIST_ENTRY *BdsBootOptionList\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
-\r
- DevicePath = DevicePathFromHandle (Handle);\r
-\r
- //\r
- // Build the shell device path\r
- //\r
- EfiInitializeFwVolDevicepathNode (&ShellNode, PcdGetPtr(PcdShellFile));\r
-\r
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
-\r
- //\r
- // Create and register the shell boot option\r
- //\r
- BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
-\r
-}\r
-\r
-/**\r
- Boot from the UEFI spec defined "BootNext" variable.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsLibBootNext (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 *BootNext;\r
- UINTN BootNextSize;\r
- CHAR16 Buffer[20];\r
- BDS_COMMON_OPTION *BootOption;\r
- LIST_ENTRY TempList;\r
- UINTN ExitDataSize;\r
- CHAR16 *ExitData;\r
-\r
- //\r
- // Init the boot option name buffer and temp link list\r
- //\r
- InitializeListHead (&TempList);\r
- ZeroMem (Buffer, sizeof (Buffer));\r
-\r
- BootNext = BdsLibGetVariableAndSize (\r
- L"BootNext",\r
- &gEfiGlobalVariableGuid,\r
- &BootNextSize\r
- );\r
-\r
- //\r
- // Clear the boot next variable first\r
- //\r
- if (BootNext != NULL) {\r
- Status = gRT->SetVariable (\r
- L"BootNext",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- 0,\r
- NULL\r
- );\r
- //\r
- // Deleting variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Start to build the boot option and try to boot\r
- //\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
- BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
- ASSERT (BootOption != NULL);\r
- BdsLibConnectDevicePath (BootOption->DevicePath);\r
- BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
- FreePool(BootOption);\r
- FreePool(BootNext);\r
- }\r
-\r
-}\r
-\r
-/**\r
- Return the bootable media handle.\r
- First, check the device is connected\r
- Second, check whether the device path point to a device which support SimpleFileSystemProtocol,\r
- Third, detect the the default boot file in the Media, and return the removable Media handle.\r
-\r
- @param DevicePath Device Path to a bootable device\r
-\r
- @return The bootable media handle. If the media on the DevicePath is not bootable, NULL will return.\r
-\r
-**/\r
-EFI_HANDLE\r
-EFIAPI\r
-BdsLibGetBootableHandle (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
- EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
- EFI_HANDLE Handle;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- VOID *Buffer;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- UINTN Size;\r
- UINTN TempSize;\r
- EFI_HANDLE ReturnHandle;\r
- EFI_HANDLE *SimpleFileSystemHandles;\r
-\r
- UINTN NumberSimpleFileSystemHandles;\r
- UINTN Index;\r
- EFI_IMAGE_DOS_HEADER DosHeader;\r
- EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
-\r
- UpdatedDevicePath = DevicePath;\r
-\r
- //\r
- // Enter to critical section to protect the acquired BlockIo instance\r
- // from getting released due to the USB mass storage hotplug event\r
- //\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- //\r
- // Check whether the device is connected\r
- //\r
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,\r
- //\r
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly\r
- //\r
- UpdatedDevicePath = DevicePath;\r
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
- gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
- }\r
- } else {\r
- //\r
- // For removable device boot option, its contained device path only point to the removable device handle,\r
- // should make sure all its children handles (its child partion or media handles) are created and connected.\r
- //\r
- gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
- //\r
- // Get BlockIo protocol and check removable attribute\r
- //\r
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Issue a dummy read to the device to check for media change.\r
- // When the removable media is changed, any Block IO read/write will\r
- // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
- // returned. After the Block IO protocol is reinstalled, subsequent\r
- // Block IO read/write will success.\r
- //\r
- Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
- if (Buffer != NULL) {\r
- BlockIo->ReadBlocks (\r
- BlockIo,\r
- BlockIo->Media->MediaId,\r
- 0,\r
- BlockIo->Media->BlockSize,\r
- Buffer\r
- );\r
- FreePool(Buffer);\r
- }\r
- }\r
-\r
- //\r
- // Detect the the default boot file from removable Media\r
- //\r
-\r
- //\r
- // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus\r
- // Try to locate the USB node device path first, if fail then use its previous PCI node to search\r
- //\r
- DupDevicePath = DuplicateDevicePath (DevicePath);\r
- ASSERT (DupDevicePath != NULL);\r
-\r
- UpdatedDevicePath = DupDevicePath;\r
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
- //\r
- // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node\r
- // Acpi()/Pci()/Usb() --> Acpi()/Pci()\r
- //\r
- if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {\r
- //\r
- // Remove the usb node, let the device path only point to PCI node\r
- //\r
- SetDevicePathEndNode (UpdatedDevicePath);\r
- UpdatedDevicePath = DupDevicePath;\r
- } else {\r
- UpdatedDevicePath = DevicePath;\r
- }\r
-\r
- //\r
- // Get the device path size of boot option\r
- //\r
- Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
- ReturnHandle = NULL;\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- NULL,\r
- &NumberSimpleFileSystemHandles,\r
- &SimpleFileSystemHandles\r
- );\r
- for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
- //\r
- // Get the device path size of SimpleFileSystem handle\r
- //\r
- TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
- TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
- //\r
- // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path\r
- //\r
- if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {\r
- //\r
- // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
- // machinename is ia32, ia64, x64, ...\r
- //\r
- Hdr.Union = &HdrData;\r
- Status = BdsLibGetImageHeader (\r
- SimpleFileSystemHandles[Index],\r
- EFI_REMOVABLE_MEDIA_FILE_NAME,\r
- &DosHeader,\r
- Hdr\r
- );\r
- if (!EFI_ERROR (Status) &&\r
- EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
- Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
- ReturnHandle = SimpleFileSystemHandles[Index];\r
- break;\r
- }\r
- }\r
- }\r
-\r
- FreePool(DupDevicePath);\r
-\r
- if (SimpleFileSystemHandles != NULL) {\r
- FreePool(SimpleFileSystemHandles);\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return ReturnHandle;\r
-}\r
-\r
-/**\r
- Check to see if the network cable is plugged in. If the DevicePath is not\r
- connected it will be connected.\r
-\r
- @param DevicePath Device Path to check\r
-\r
- @retval TRUE DevicePath points to an Network that is connected\r
- @retval FALSE DevicePath does not point to a bootable network\r
-\r
-**/\r
-BOOLEAN\r
-BdsLibNetworkBootWithMediaPresent (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
- EFI_HANDLE Handle;\r
- EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
- BOOLEAN MediaPresent;\r
- UINT32 InterruptStatus;\r
-\r
- MediaPresent = FALSE;\r
-\r
- UpdatedDevicePath = DevicePath;\r
- //\r
- // Locate Load File Protocol for PXE boot option first\r
- //\r
- Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Device not present so see if we need to connect it\r
- //\r
- Status = BdsLibConnectDevicePath (DevicePath);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // This one should work after we did the connect\r
- //\r
- Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Failed to open SNP from this handle, try to get SNP from parent handle\r
- //\r
- UpdatedDevicePath = DevicePathFromHandle (Handle);\r
- if (UpdatedDevicePath != NULL) {\r
- Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // SNP handle found, get SNP from it\r
- //\r
- Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &Snp);\r
- }\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- if (Snp->Mode->MediaPresentSupported) {\r
- if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
- //\r
- // Invoke Snp->GetStatus() to refresh the media status\r
- //\r
- Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
-\r
- //\r
- // In case some one else is using the SNP check to see if it's connected\r
- //\r
- MediaPresent = Snp->Mode->MediaPresent;\r
- } else {\r
- //\r
- // No one is using SNP so we need to Start and Initialize so\r
- // MediaPresent will be valid.\r
- //\r
- Status = Snp->Start (Snp);\r
- if (!EFI_ERROR (Status)) {\r
- Status = Snp->Initialize (Snp, 0, 0);\r
- if (!EFI_ERROR (Status)) {\r
- MediaPresent = Snp->Mode->MediaPresent;\r
- Snp->Shutdown (Snp);\r
- }\r
- Snp->Stop (Snp);\r
- }\r
- }\r
- } else {\r
- MediaPresent = TRUE;\r
- }\r
- }\r
- }\r
-\r
- return MediaPresent;\r
-}\r
-\r
-/**\r
- For a bootable Device path, return its boot type.\r
-\r
- @param DevicePath The bootable device Path to check\r
-\r
- @retval BDS_EFI_MEDIA_HD_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node\r
- which subtype is MEDIA_HARDDRIVE_DP\r
- @retval BDS_EFI_MEDIA_CDROM_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node\r
- which subtype is MEDIA_CDROM_DP\r
- @retval BDS_EFI_ACPI_FLOPPY_BOOT If given device path contains ACPI_DEVICE_PATH type device path node\r
- which HID is floppy device.\r
- @retval BDS_EFI_MESSAGE_ATAPI_BOOT 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 BDS_EFI_MESSAGE_SCSI_BOOT 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 BDS_EFI_MESSAGE_USB_DEVICE_BOOT 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 BDS_EFI_MESSAGE_MISC_BOOT If the device path not contains any media device path node, and\r
- its last device path node point to a message device path node.\r
- @retval BDS_LEGACY_BBS_BOOT If given device path contains BBS_DEVICE_PATH type device path node.\r
- @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path not point to a media and message device,\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-BdsGetBootTypeFromDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- ACPI_HID_DEVICE_PATH *Acpi;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
- UINT32 BootType;\r
-\r
- if (NULL == DevicePath) {\r
- return BDS_EFI_UNSUPPORT;\r
- }\r
-\r
- TempDevicePath = DevicePath;\r
-\r
- while (!IsDevicePathEndType (TempDevicePath)) {\r
- switch (DevicePathType (TempDevicePath)) {\r
- case BBS_DEVICE_PATH:\r
- return BDS_LEGACY_BBS_BOOT;\r
- case MEDIA_DEVICE_PATH:\r
- if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {\r
- return BDS_EFI_MEDIA_HD_BOOT;\r
- } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {\r
- return BDS_EFI_MEDIA_CDROM_BOOT;\r
- }\r
- break;\r
- case ACPI_DEVICE_PATH:\r
- Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;\r
- if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {\r
- return BDS_EFI_ACPI_FLOPPY_BOOT;\r
- }\r
- break;\r
- case MESSAGING_DEVICE_PATH:\r
- //\r
- // Get the last device path node\r
- //\r
- LastDeviceNode = NextDevicePathNode (TempDevicePath);\r
- if (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {\r
- //\r
- // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),\r
- // skip it\r
- //\r
- LastDeviceNode = NextDevicePathNode (LastDeviceNode);\r
- }\r
- //\r
- // if the device path not only point to driver device, it is not a messaging device path,\r
- //\r
- if (!IsDevicePathEndType (LastDeviceNode)) {\r
- break;\r
- }\r
-\r
- switch (DevicePathSubType (TempDevicePath)) {\r
- case MSG_ATAPI_DP:\r
- BootType = BDS_EFI_MESSAGE_ATAPI_BOOT;\r
- break;\r
-\r
- case MSG_USB_DP:\r
- BootType = BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
- break;\r
-\r
- case MSG_SCSI_DP:\r
- BootType = BDS_EFI_MESSAGE_SCSI_BOOT;\r
- break;\r
-\r
- case MSG_SATA_DP:\r
- BootType = BDS_EFI_MESSAGE_SATA_BOOT;\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
- BootType = BDS_EFI_MESSAGE_MAC_BOOT;\r
- break;\r
-\r
- default:\r
- BootType = BDS_EFI_MESSAGE_MISC_BOOT;\r
- break;\r
- }\r
- return BootType;\r
-\r
- default:\r
- break;\r
- }\r
- TempDevicePath = NextDevicePathNode (TempDevicePath);\r
- }\r
-\r
- return BDS_EFI_UNSUPPORT;\r
-}\r
-\r
-/**\r
- Check whether the Device path in a boot option point to a valid bootable device,\r
- And if CheckMedia is true, check the device is ready to boot now.\r
-\r
- @param DevPath the Device path in a boot option\r
- @param CheckMedia if true, check the device is ready to boot now.\r
-\r
- @retval TRUE the Device path is valid\r
- @retval FALSE the Device path is invalid .\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-BdsLibIsValidEFIBootOptDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath,\r
- IN BOOLEAN CheckMedia\r
- )\r
-{\r
- return BdsLibIsValidEFIBootOptDevicePathExt (DevPath, CheckMedia, NULL);\r
-}\r
-\r
-/**\r
- Check whether the Device path in a boot option point to a valid bootable device,\r
- And if CheckMedia is true, check the device is ready to boot now.\r
- If Description is not NULL and the device path point to a fixed BlockIo\r
- device, check the description whether conflict with other auto-created\r
- boot options.\r
-\r
- @param DevPath the Device path in a boot option\r
- @param CheckMedia if true, check the device is ready to boot now.\r
- @param Description the description in a boot option\r
-\r
- @retval TRUE the Device path is valid\r
- @retval FALSE the Device path is invalid .\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-BdsLibIsValidEFIBootOptDevicePathExt (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevPath,\r
- IN BOOLEAN CheckMedia,\r
- IN CHAR16 *Description\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
-\r
- TempDevicePath = DevPath;\r
- LastDeviceNode = DevPath;\r
-\r
- //\r
- // Check if it's a valid boot option for network boot device.\r
- // Check if there is EfiLoadFileProtocol installed.\r
- // If yes, that means there is a boot option for network.\r
- //\r
- Status = gBS->LocateDevicePath (\r
- &gEfiLoadFileProtocolGuid,\r
- &TempDevicePath,\r
- &Handle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Device not present so see if we need to connect it\r
- //\r
- TempDevicePath = DevPath;\r
- BdsLibConnectDevicePath (TempDevicePath);\r
- Status = gBS->LocateDevicePath (\r
- &gEfiLoadFileProtocolGuid,\r
- &TempDevicePath,\r
- &Handle\r
- );\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- if (!IsDevicePathEnd (TempDevicePath)) {\r
- //\r
- // LoadFile protocol is not installed on handle with exactly the same DevPath\r
- //\r
- return FALSE;\r
- }\r
-\r
- if (CheckMedia) {\r
- //\r
- // Test if it is ready to boot now\r
- //\r
- if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
- return TRUE;\r
- }\r
- } else {\r
- return TRUE;\r
- }\r
- }\r
-\r
- //\r
- // If the boot option point to a file, it is a valid EFI boot option,\r
- // and assume it is ready to boot now\r
- //\r
- while (!IsDevicePathEnd (TempDevicePath)) {\r
- //\r
- // If there is USB Class or USB WWID device path node, treat it as valid EFI\r
- // Boot Option. BdsExpandUsbShortFormDevicePath () will be used to expand it\r
- // to full device path.\r
- //\r
- if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
- ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) ||\r
- (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) {\r
- return TRUE;\r
- }\r
-\r
- LastDeviceNode = TempDevicePath;\r
- TempDevicePath = NextDevicePathNode (TempDevicePath);\r
- }\r
- if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&\r
- (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {\r
- return TRUE;\r
- }\r
-\r
- //\r
- // Check if it's a valid boot option for internal FV application\r
- //\r
- if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {\r
- //\r
- // If the boot option point to internal FV application, make sure it is valid\r
- //\r
- TempDevicePath = DevPath;\r
- Status = BdsLibUpdateFvFileDevicePath (\r
- &TempDevicePath,\r
- EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode)\r
- );\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return TRUE;\r
- } else {\r
- if (Status == EFI_SUCCESS) {\r
- FreePool (TempDevicePath);\r
- }\r
- return FALSE;\r
- }\r
- }\r
-\r
- //\r
- // If the boot option point to a blockIO device:\r
- // if it is a removable blockIo device, it is valid.\r
- // if it is a fixed blockIo device, check its description confliction.\r
- //\r
- TempDevicePath = DevPath;\r
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Device not present so see if we need to connect it\r
- //\r
- Status = BdsLibConnectDevicePath (DevPath);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Try again to get the Block Io protocol after we did the connect\r
- //\r
- TempDevicePath = DevPath;\r
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
- if (!EFI_ERROR (Status)) {\r
- if (CheckMedia) {\r
- //\r
- // Test if it is ready to boot now\r
- //\r
- if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
- return TRUE;\r
- }\r
- } else {\r
- return TRUE;\r
- }\r
- }\r
- } else {\r
- //\r
- // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,\r
- //\r
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
- if (!EFI_ERROR (Status)) {\r
- if (CheckMedia) {\r
- //\r
- // Test if it is ready to boot now\r
- //\r
- if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
- return TRUE;\r
- }\r
- } else {\r
- return TRUE;\r
- }\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- According to a file guild, check a Fv file device path is valid. If it is invalid,\r
- try to return the valid device path.\r
- FV address maybe changes for memory layout adjust from time to time, use this function\r
- could promise the Fv file device path is right.\r
-\r
- @param DevicePath on input, the Fv file device path need to check on\r
- output, the updated valid Fv file device path\r
- @param FileGuid the Fv file guild\r
-\r
- @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid\r
- parameter\r
- @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file\r
- guild at all\r
- @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it is\r
- valid\r
- @retval EFI_SUCCESS has successfully updated the invalid DevicePath,\r
- and return the updated device path in DevicePath\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibUpdateFvFileDevicePath (\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,\r
- IN EFI_GUID *FileGuid\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
- EFI_STATUS Status;\r
- EFI_GUID *GuidPoint;\r
- UINTN Index;\r
- UINTN FvHandleCount;\r
- EFI_HANDLE *FvHandleBuffer;\r
- EFI_FV_FILETYPE Type;\r
- UINTN Size;\r
- EFI_FV_FILE_ATTRIBUTES Attributes;\r
- UINT32 AuthenticationStatus;\r
- BOOLEAN FindFvFile;\r
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
- EFI_HANDLE FoundFvHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
-\r
- if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- if (FileGuid == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Check whether the device path point to the default the input Fv file\r
- //\r
- TempDevicePath = *DevicePath;\r
- LastDeviceNode = TempDevicePath;\r
- while (!IsDevicePathEnd (TempDevicePath)) {\r
- LastDeviceNode = TempDevicePath;\r
- TempDevicePath = NextDevicePathNode (TempDevicePath);\r
- }\r
- GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (\r
- (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode\r
- );\r
- if (GuidPoint == NULL) {\r
- //\r
- // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
- if (!CompareGuid (GuidPoint, FileGuid)) {\r
- //\r
- // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Check whether the input Fv file device path is valid\r
- //\r
- TempDevicePath = *DevicePath;\r
- FoundFvHandle = NULL;\r
- Status = gBS->LocateDevicePath (\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- &TempDevicePath,\r
- &FoundFvHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->HandleProtocol (\r
- FoundFvHandle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) &Fv\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
- //\r
- Status = Fv->ReadFile (\r
- Fv,\r
- FileGuid,\r
- NULL,\r
- &Size,\r
- &Type,\r
- &Attributes,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Look for the input wanted FV file in current FV\r
- // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV\r
- //\r
- FindFvFile = FALSE;\r
- FoundFvHandle = NULL;\r
- Status = gBS->HandleProtocol (\r
- gImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **) &LoadedImage\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->HandleProtocol (\r
- LoadedImage->DeviceHandle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) &Fv\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = Fv->ReadFile (\r
- Fv,\r
- FileGuid,\r
- NULL,\r
- &Size,\r
- &Type,\r
- &Attributes,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- FindFvFile = TRUE;\r
- FoundFvHandle = LoadedImage->DeviceHandle;\r
- }\r
- }\r
- }\r
- //\r
- // Second, if fail to find, try to enumerate all FV\r
- //\r
- if (!FindFvFile) {\r
- FvHandleBuffer = NULL;\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- NULL,\r
- &FvHandleCount,\r
- &FvHandleBuffer\r
- );\r
- for (Index = 0; Index < FvHandleCount; Index++) {\r
- gBS->HandleProtocol (\r
- FvHandleBuffer[Index],\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) &Fv\r
- );\r
-\r
- Status = Fv->ReadFile (\r
- Fv,\r
- FileGuid,\r
- NULL,\r
- &Size,\r
- &Type,\r
- &Attributes,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Skip if input Fv file not in the FV\r
- //\r
- continue;\r
- }\r
- FindFvFile = TRUE;\r
- FoundFvHandle = FvHandleBuffer[Index];\r
- break;\r
- }\r
-\r
- if (FvHandleBuffer != NULL) {\r
- FreePool (FvHandleBuffer);\r
- }\r
- }\r
-\r
- if (FindFvFile) {\r
- //\r
- // Build the shell device path\r
- //\r
- NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
- EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
- NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
- ASSERT (NewDevicePath != NULL);\r
- *DevicePath = NewDevicePath;\r
- return EFI_SUCCESS;\r
- }\r
- return EFI_NOT_FOUND;\r
-}\r