and manage the legacy boot option, all legacy boot option is getting from\r
the legacy BBS table.\r
\r
-Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "BBSsupport.h"\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
+#pragma pack(1)\r
+typedef struct {\r
+ BBS_TABLE BbsEntry;\r
+ UINT16 BbsIndex;\r
+} LEGACY_BOOT_OPTION_BBS_DATA;\r
+#pragma pack()\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
+ Re-order the Boot Option according to the DevOrder.\r
+\r
+ The routine re-orders the Boot Option in BootOption array according to\r
+ the order specified by DevOrder.\r
+\r
+ @param DevOrder Pointer to buffer containing the BBS Index,\r
+ high 8-bit value 0xFF indicating a disabled boot option\r
+ @param DevOrderCount Count of the BBS Index\r
+ @param EnBootOption Callee allocated buffer containing the enabled Boot Option Numbers\r
+ @param EnBootOptionCount Count of the enabled Boot Option Numbers\r
+ @param DisBootOption Callee allocated buffer containing the disabled Boot Option Numbers\r
+ @param DisBootOptionCount Count of the disabled Boot Option Numbers\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) {\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
- UINT16 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
- UnicodeStrToAsciiStr ((CONST CHAR16*)&BootDesc, (CHAR8*)&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
- EndDevicePath,\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
- VAR_FLAG,\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
-BdsDeleteAllInvalidLegacyBootOptions (\r
- VOID\r
+OrderLegacyBootOption4SameType (\r
+ UINT16 *DevOrder,\r
+ UINTN DevOrderCount,\r
+ UINT16 **EnBootOption,\r
+ UINTN *EnBootOptionCount,\r
+ UINT16 **DisBootOption,\r
+ UINTN *DisBootOptionCount\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
+ EFI_STATUS Status;\r
+ UINT16 *NewBootOption;\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ UINTN Index;\r
+ UINTN StartPosition;\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
+ BDS_COMMON_OPTION *BootOption;\r
\r
- Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (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
+ CHAR16 OptionName[sizeof ("Boot####")];\r
+ UINT16 *BbsIndexArray;\r
+ UINT16 *DeviceTypeArray;\r
+ LIST_ENTRY List;\r
\r
BootOrder = BdsLibGetVariableAndSize (\r
L"BootOrder",\r
&gEfiGlobalVariableGuid,\r
&BootOrderSize\r
);\r
- if (NULL == BootOrder) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ ASSERT (BootOrder != NULL);\r
+\r
+ BbsIndexArray = AllocatePool (BootOrderSize);\r
+ DeviceTypeArray = AllocatePool (BootOrderSize);\r
+ *EnBootOption = AllocatePool (BootOrderSize);\r
+ *DisBootOption = AllocatePool (BootOrderSize);\r
+ *DisBootOptionCount = 0;\r
+ *EnBootOptionCount = 0;\r
+ Index = 0;\r
+\r
+ ASSERT (BbsIndexArray != NULL);\r
+ ASSERT (DeviceTypeArray != NULL);\r
+ ASSERT (*EnBootOption != NULL);\r
+ ASSERT (*DisBootOption != NULL);\r
+\r
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);\r
+ InitializeListHead (&List);\r
+ BootOption = BdsLibVariableToOption (&List, OptionName);\r
+ ASSERT (BootOption != NULL);\r
+\r
+ if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) {\r
+ //\r
+ // Legacy Boot Option\r
+ //\r
+ ASSERT (BootOption->LoadOptionsSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));\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
- if (BootOrder != NULL) {\r
- FreePool (BootOrder);\r
- }\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- \r
- //\r
- // Skip Non-Legacy boot options\r
- // \r
- if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
- if (BootOptionVar!= NULL) {\r
- FreePool (BootOptionVar);\r
+ DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType;\r
+ BbsIndexArray [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption->LoadOptions)->BbsIndex;\r
+ } else {\r
+ DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN;\r
+ BbsIndexArray [Index] = 0xFFFF;\r
+ }\r
+ FreePool (BootOption->DevicePath);\r
+ FreePool (BootOption->Description);\r
+ FreePool (BootOption->LoadOptions);\r
+ FreePool (BootOption);\r
+ }\r
+\r
+ //\r
+ // Record the corresponding Boot Option Numbers according to the DevOrder\r
+ // Record the EnBootOption and DisBootOption according to the DevOrder\r
+ //\r
+ StartPosition = BootOrderSize / sizeof (UINT16);\r
+ NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16));\r
+ ASSERT (NewBootOption != NULL);\r
+ while (DevOrderCount-- != 0) {\r
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) {\r
+ StartPosition = MIN (StartPosition, Index);\r
+ NewBootOption[DevOrderCount] = BootOrder[Index];\r
+\r
+ if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {\r
+ (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index];\r
+ (*DisBootOptionCount)++;\r
+ } else {\r
+ (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index];\r
+ (*EnBootOptionCount)++;\r
+ }\r
+ break;\r
}\r
- Index++;\r
- continue;\r
- }\r
-\r
- //\r
- // Check if BBS Description String is changed\r
- //\r
- DescStringMatch = FALSE;\r
-\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
- 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
+ // Overwrite the old BootOption\r
//\r
- if (BootOrderSize != 0) {\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- VAR_FLAG,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- } else {\r
- EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
- }\r
-\r
- if (BootOrder != NULL) {\r
- FreePool (BootOrder);\r
- }\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 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
-BdsFindLegacyBootOptionByDevType (\r
- IN UINT16 *BootOrder,\r
- IN UINTN BootOptionNum,\r
- IN UINT16 DevType,\r
- OUT UINT32 *Attribute,\r
- OUT UINT16 *BbsIndex,\r
- OUT UINTN *OptionNumber\r
- )\r
-{\r
- UINTN Index;\r
- UINTN BootOrderIndex;\r
- UINT16 BootOption[100];\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 (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
- Index = (UINTN) BootOrder[BootOrderIndex];\r
- UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", 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 (BbsEntry->DeviceType != DevType) {\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- *Attribute = *(UINT32 *) BootOptionVar;\r
- *OptionNumber = 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
+ CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));\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
- // Create device path node.\r
+ // Changing content without increasing its size with current variable implementation shouldn't fail.\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
- EndDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
- );\r
- if (NULL == DevPath) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ ASSERT_EFI_ERROR (Status);\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
+ FreePool (NewBootOption);\r
+ FreePool (DeviceTypeArray);\r
+ FreePool (BbsIndexArray);\r
+ FreePool (BootOrder);\r
}\r
\r
/**\r
+ Group the legacy boot options in the BootOption.\r
\r
- Add the legacy boot options from BBS table if they do not exist.\r
+ The routine assumes the boot options in the beginning that covers all the device\r
+ types are ordered properly and re-position the following boot options just after\r
+ the corresponding boot options with the same device type.\r
+ For example:\r
+ 1. Input = [Harddisk1 CdRom2 Efi1 Harddisk0 CdRom0 CdRom1 Harddisk2 Efi0]\r
+ Assuming [Harddisk1 CdRom2 Efi1] is ordered properly\r
+ Output = [Harddisk1 Harddisk0 Harddisk2 CdRom2 CdRom0 CdRom1 Efi1 Efi0]\r
\r
- @retval EFI_SUCCESS The boot options are added successfully \r
- or they are already in boot options.\r
+ 2. Input = [Efi1 Efi0 CdRom1 Harddisk0 Harddisk1 Harddisk2 CdRom0 CdRom2]\r
+ Assuming [Efi1 Efi0 CdRom1 Harddisk0] is ordered properly\r
+ Output = [Efi1 Efi0 CdRom1 CdRom0 CdRom2 Harddisk0 Harddisk1 Harddisk2]\r
\r
**/\r
-EFI_STATUS\r
-BdsAddNonExistingLegacyBootOptions (\r
+VOID\r
+GroupMultipleLegacyBootOption4SameType (\r
VOID\r
)\r
{\r
- UINT16 *BootOrder;\r
- UINTN BootOrderSize;\r
- EFI_STATUS Status;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *LocalHddInfo;\r
- BBS_TABLE *LocalBbsTable;\r
- UINT16 BbsIndex;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN Index;\r
- UINT32 Attribute;\r
- UINTN OptionNumber;\r
- BOOLEAN Ret;\r
-\r
- BootOrder = NULL;\r
- HddCount = 0;\r
- BbsCount = 0;\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\r
-\r
- Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (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
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN DeviceIndex;\r
+ UINTN DeviceTypeIndex[7];\r
+ UINTN *NextIndex;\r
+ UINT16 OptionNumber;\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ CHAR16 OptionName[sizeof ("Boot####")];\r
+ BDS_COMMON_OPTION *BootOption;\r
+ LIST_ENTRY List;\r
+\r
+ SetMem (DeviceTypeIndex, sizeof (DeviceTypeIndex), 0xff);\r
\r
BootOrder = BdsLibGetVariableAndSize (\r
L"BootOrder",\r
&gEfiGlobalVariableGuid,\r
&BootOrderSize\r
);\r
- if (NULL == BootOrder) {\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
- Ret = BdsFindLegacyBootOptionByDevType (\r
- BootOrder,\r
- BootOrderSize / sizeof (UINT16),\r
- LocalBbsTable[Index].DeviceType,\r
- &Attribute,\r
- &BbsIndex,\r
- &OptionNumber\r
- );\r
- if (Ret) {\r
- continue;\r
- }\r
-\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
- break;\r
- }\r
- }\r
-\r
- if (BootOrderSize > 0) {\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- VAR_FLAG,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
- } else {\r
- EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
- }\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 EfiLegacyDevOrderGuid is\r
- set correctly.\r
- @return Other value if the set of EFI variable fails. Check gRT->SetVariable\r
- for detailed information.\r
-\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
- UINT8 *DevOrder;\r
- UINT8 *Ptr;\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
- Ptr = 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
-\r
- Ptr = DevOrder;\r
-\r
- *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
- Ptr += sizeof (BBS_TYPE);\r
- *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
- if (FDCount != 0) {\r
- Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
- }\r
-\r
- *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
- Ptr += sizeof (BBS_TYPE);\r
- *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
- if (HDCount != 0) {\r
- Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
- }\r
-\r
- *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
- Ptr += sizeof (BBS_TYPE);\r
- *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
- if (CDCount != 0) {\r
- Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
- }\r
-\r
- *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
- Ptr += sizeof (BBS_TYPE);\r
- *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
- if (NETCount != 0) {\r
- Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
- }\r
-\r
- *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
- Ptr += sizeof (BBS_TYPE);\r
- *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
- if (BEVCount != 0) {\r
- Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
- }\r
-\r
- //\r
- // Save device order for legacy boot device to variable.\r
- //\r
- Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &EfiLegacyDevOrderGuid,\r
- VAR_FLAG,\r
- TotalSize,\r
- DevOrder\r
- );\r
- FreePool (DevOrder);\r
-\r
- return Status;\r
-}\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
-\r
-**/\r
-EFI_STATUS\r
-BdsUpdateLegacyDevOrder (\r
- VOID\r
- )\r
-{\r
- UINT8 *DevOrder;\r
- UINT8 *NewDevOrder;\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
- UINT8 *Ptr;\r
- UINT8 *NewPtr;\r
- UINT16 *NewFDPtr;\r
- UINT16 *NewHDPtr;\r
- UINT16 *NewCDPtr;\r
- UINT16 *NewNETPtr;\r
- UINT16 *NewBEVPtr;\r
- UINT16 *NewDevPtr;\r
- UINT16 Length;\r
- UINT16 Tmp;\r
- UINTN FDIndex;\r
- UINTN HDIndex;\r
- UINTN CDIndex;\r
- UINTN NETIndex;\r
- UINTN BEVIndex;\r
-\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\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 = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (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
- DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
- VAR_LEGACY_DEV_ORDER,\r
- &EfiLegacyDevOrderGuid,\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
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);\r
+ InitializeListHead (&List);\r
+ BootOption = BdsLibVariableToOption (&List, OptionName);\r
+ ASSERT (BootOption != NULL);\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
- NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);\r
- NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
- NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
- NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
- NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
-\r
- //\r
- // copy FD\r
- //\r
- Ptr = DevOrder;\r
- NewPtr = NewDevOrder;\r
- *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
- Ptr += sizeof (BBS_TYPE);\r
- NewPtr += sizeof (BBS_TYPE);\r
- Length = *((UINT16 *) Ptr);\r
- *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
-\r
- for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
- ) {\r
- Ptr += sizeof (UINT16);\r
- continue;\r
- }\r
-\r
- NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
- FDIndex++;\r
- Ptr += sizeof (UINT16);\r
- }\r
- //\r
- // copy HD\r
- //\r
- NewPtr = (UINT8 *) NewHDPtr - HeaderSize;\r
- *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
- Ptr += sizeof (BBS_TYPE);\r
- NewPtr += sizeof (BBS_TYPE);\r
- Length = *((UINT16 *) Ptr);\r
- *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
-\r
- for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
- ) {\r
- Ptr += sizeof (UINT16);\r
- continue;\r
- }\r
-\r
- NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
- HDIndex++;\r
- Ptr += sizeof (UINT16);\r
- }\r
- //\r
- // copy CD\r
- //\r
- NewPtr = (UINT8 *) NewCDPtr - HeaderSize;\r
- *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
- Ptr += sizeof (BBS_TYPE);\r
- NewPtr += sizeof (BBS_TYPE);\r
- Length = *((UINT16 *) Ptr);\r
- *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
-\r
- for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
- ) {\r
- Ptr += sizeof (UINT16);\r
- continue;\r
- }\r
-\r
- NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
- CDIndex++;\r
- Ptr += sizeof (UINT16);\r
- }\r
- //\r
- // copy NET\r
- //\r
- NewPtr = (UINT8 *) NewNETPtr - HeaderSize;\r
- *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
- Ptr += sizeof (BBS_TYPE);\r
- NewPtr += sizeof (BBS_TYPE);\r
- Length = *((UINT16 *) Ptr);\r
- *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
-\r
- for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
- ) {\r
- Ptr += sizeof (UINT16);\r
- continue;\r
- }\r
-\r
- NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
- NETIndex++;\r
- Ptr += sizeof (UINT16);\r
- }\r
- //\r
- // copy BEV\r
- //\r
- NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;\r
- *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
- Ptr += sizeof (BBS_TYPE);\r
- NewPtr += sizeof (BBS_TYPE);\r
- Length = *((UINT16 *) Ptr);\r
- *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
- Ptr += sizeof (UINT16);\r
-\r
- for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
- if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
- LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
- LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
- ) {\r
- Ptr += sizeof (UINT16);\r
- continue;\r
- }\r
-\r
- NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
- BEVIndex++;\r
- Ptr += sizeof (UINT16);\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
- 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 != 0) {\r
- for (Index2 = 0; Index2 < *Idx; Index2++) {\r
- if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
- break;\r
- }\r
- }\r
+ if ((DevicePathType (BootOption->DevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (BootOption->DevicePath) == BBS_BBS_DP)) {\r
+ //\r
+ // Legacy Boot Option\r
+ //\r
+ ASSERT ((((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF) < ARRAY_SIZE (DeviceTypeIndex));\r
+ NextIndex = &DeviceTypeIndex[((BBS_BBS_DEVICE_PATH *) BootOption->DevicePath)->DeviceType & 0xF];\r
\r
- if (Index2 == *Idx) {\r
+ if (*NextIndex == (UINTN) -1) {\r
//\r
- // Index2 == *Idx means we didn't find Index\r
- // so Index is a new appeared device's index in BBS table\r
- // save it.\r
+ // *NextIndex is the Index in BootOrder to put the next Option Number for the same type\r
//\r
- NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
- (*Idx)++;\r
- }\r
- }\r
- }\r
-\r
- if (FDCount != 0) {\r
- //\r
- // Just to make sure that disabled indexes are all at the end of the array\r
- //\r
- for (Index = 0; Index < FDIndex - 1; Index++) {\r
- if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
- continue;\r
- }\r
-\r
- for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
- if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
- Tmp = NewFDPtr[Index];\r
- NewFDPtr[Index] = NewFDPtr[Index2];\r
- NewFDPtr[Index2] = Tmp;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (HDCount != 0) {\r
- //\r
- // Just to make sure that disabled indexes are all at the end of the array\r
- //\r
- for (Index = 0; Index < HDIndex - 1; Index++) {\r
- if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
- continue;\r
- }\r
-\r
- for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
- if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
- Tmp = NewHDPtr[Index];\r
- NewHDPtr[Index] = NewHDPtr[Index2];\r
- NewHDPtr[Index2] = Tmp;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (CDCount != 0) {\r
- //\r
- // Just to make sure that disabled indexes are all at the end of the array\r
- //\r
- for (Index = 0; Index < CDIndex - 1; Index++) {\r
- if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
- continue;\r
- }\r
-\r
- for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
- if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
- Tmp = NewCDPtr[Index];\r
- NewCDPtr[Index] = NewCDPtr[Index2];\r
- NewCDPtr[Index2] = Tmp;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (NETCount != 0) {\r
- //\r
- // Just to make sure that disabled indexes are all at the end of the array\r
- //\r
- for (Index = 0; Index < NETIndex - 1; Index++) {\r
- if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
- continue;\r
- }\r
-\r
- for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
- if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
- Tmp = NewNETPtr[Index];\r
- NewNETPtr[Index] = NewNETPtr[Index2];\r
- NewNETPtr[Index2] = Tmp;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (BEVCount!= 0) {\r
- //\r
- // Just to make sure that disabled indexes are all at the end of the array\r
- //\r
- for (Index = 0; Index < BEVIndex - 1; Index++) {\r
- if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
- continue;\r
- }\r
+ *NextIndex = Index + 1;\r
+ } else {\r
+ //\r
+ // insert the current boot option before *NextIndex, causing [*Next .. Index] shift right one position\r
+ //\r
+ OptionNumber = BootOrder[Index];\r
+ CopyMem (&BootOrder[*NextIndex + 1], &BootOrder[*NextIndex], (Index - *NextIndex) * sizeof (UINT16));\r
+ BootOrder[*NextIndex] = OptionNumber;\r
\r
- for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
- if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
- Tmp = NewBEVPtr[Index];\r
- NewBEVPtr[Index] = NewBEVPtr[Index2];\r
- NewBEVPtr[Index2] = Tmp;\r
- break;\r
+ //\r
+ // Update the DeviceTypeIndex array to reflect the right shift operation\r
+ //\r
+ for (DeviceIndex = 0; DeviceIndex < ARRAY_SIZE (DeviceTypeIndex); DeviceIndex++) {\r
+ if (DeviceTypeIndex[DeviceIndex] != (UINTN) -1 && DeviceTypeIndex[DeviceIndex] >= *NextIndex) {\r
+ DeviceTypeIndex[DeviceIndex]++;\r
+ }\r
}\r
}\r
}\r
+ FreePool (BootOption->DevicePath);\r
+ FreePool (BootOption->Description);\r
+ FreePool (BootOption->LoadOptions);\r
+ FreePool (BootOption);\r
}\r
\r
- FreePool (DevOrder);\r
-\r
Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &EfiLegacyDevOrderGuid,\r
- VAR_FLAG,\r
- TotalSize,\r
- NewDevOrder\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ BootOrderSize,\r
+ BootOrder\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 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
-\r
-**/\r
-EFI_STATUS\r
-BdsSetBootPriority4SameTypeDev (\r
- IN UINT16 DeviceType,\r
- IN OUT BBS_TABLE *LocalBbsTable,\r
- IN OUT UINT16 *Priority\r
- )\r
-{\r
- UINT8 *DevOrder;\r
-\r
- UINT8 *OrigBuffer;\r
- UINT16 *DevIndex;\r
- UINTN DevOrderSize;\r
- UINTN DevCount;\r
- UINTN Index;\r
-\r
- DevOrder = BdsLibGetVariableAndSize (\r
- VAR_LEGACY_DEV_ORDER,\r
- &EfiLegacyDevOrderGuid,\r
- &DevOrderSize\r
- );\r
- if (NULL == DevOrder) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- OrigBuffer = DevOrder;\r
- while (DevOrder < OrigBuffer + DevOrderSize) {\r
- if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
- break;\r
- }\r
-\r
- DevOrder += sizeof (BBS_TYPE);\r
- DevOrder += *(UINT16 *) DevOrder;\r
- }\r
-\r
- if (DevOrder >= OrigBuffer + DevOrderSize) {\r
- FreePool (OrigBuffer);\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- DevOrder += sizeof (BBS_TYPE);\r
- DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
- DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));\r
//\r
- // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+ // Changing content without increasing its size with current variable implementation shouldn't fail.\r
//\r
- for (Index = 0; Index < DevCount; Index++) {\r
- if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
- //\r
- // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
- //\r
- } else {\r
- LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
- (*Priority)++;\r
- }\r
- }\r
-\r
- FreePool (OrigBuffer);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Print the BBS Table.\r
-\r
- @param LocalBbsTable The BBS table.\r
-\r
-**/\r
-VOID\r
-PrintBbsTable (\r
- IN BBS_TABLE *LocalBbsTable\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 < MAX_BBS_ENTRIES; 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
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (BootOrder);\r
}\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
- @return status of BdsSetBootPriority4SameTypeDev()\r
-**/\r
-EFI_STATUS\r
-BdsRefreshBbsTableForBoot (\r
- IN BDS_COMMON_OPTION *Entry\r
- )\r
-{\r
- EFI_STATUS Status;\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
- UINT16 BootOption[100];\r
- UINT8 *Ptr;\r
- UINT16 DevPathLen;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
-\r
- HddCount = 0;\r
- BbsCount = 0;\r
- LocalHddInfo = NULL;\r
- LocalBbsTable = NULL;\r
- DevType = BBS_UNKNOWN;\r
-\r
- Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (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
- Status = BdsSetBootPriority4SameTypeDev (\r
- DevType,\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 = (UINT16 *) BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderSize\r
- );\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
- if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
- //\r
- // We don't want to process twice for a device type\r
- //\r
- FreePool (BootOptionVar);\r
- continue;\r
- }\r
-\r
- Status = BdsSetBootPriority4SameTypeDev (\r
- ((BBS_TABLE *) Ptr)->DeviceType,\r
- LocalBbsTable,\r
- &Priority\r
- );\r
- FreePool (BootOptionVar);\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- }\r
-\r
- if (BootOrder != NULL) {\r
- FreePool (BootOrder);\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
- PrintBbsTable (LocalBbsTable);\r
- DEBUG_CODE_END();\r
- \r
- return Status;\r
-}\r