+/**\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