--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \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
+\r
+Module Name:\r
+\r
+ BBSsupport.c\r
+\r
+Abstract:\r
+\r
+ This function deal with the legacy boot option, it create, delete\r
+ and manage the legacy boot option, all legacy boot option is getting from\r
+ the legacy BBS table.\r
+\r
+--*/\r
+\r
+#include "BBSsupport.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ END_DEVICE_PATH_LENGTH,\r
+ 0\r
+};\r
+\r
+VOID\r
+AsciiToUnicodeSize (\r
+ IN UINT8 *a,\r
+ IN UINTN Size,\r
+ OUT UINT16 *u\r
+ )\r
+/*++\r
+\r
+ Routine Description:\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
+ Arguments:\r
+\r
+ a - Pointer to input Ascii string.\r
+ Size - The number of characters to translate.\r
+ u - Pointer to output Unicode string buffer.\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN i;\r
+\r
+ i = 0;\r
+ while (a[i] != 0) {\r
+ u[i] = (CHAR16) a[i];\r
+ if (i == Size) {\r
+ break;\r
+ }\r
+\r
+ i++;\r
+ }\r
+ u[i] = 0;\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
+ UnicodeSPrint (BootString, BufSize, Fmt, Type);\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
+\r
+ Routine Description:\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
+ Arguments:\r
+\r
+ CurrentBbsEntry - Pointer to current BBS table.\r
+ CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS\r
+ Index - Index of the specified entry in BBS table.\r
+ BootOrderList - On input, the original boot order list.\r
+ On output, the new boot order list attached with the\r
+ created node.\r
+ BootOrderListSize - On input, the original size of boot order list.\r
+ - On output, the size of new boot order list.\r
+\r
+ Returns:\r
+\r
+ EFI_SUCCESS - Boot Option successfully created.\r
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.\r
+ Other - Error occurs while setting variable.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 CurrentBootOptionNo;\r
+ UINT16 BootString[10];\r
+ UINT16 BootDesc[100];\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BufferSize;\r
+ VOID *Buffer;\r
+ UINT8 *Ptr;\r
+ UINT16 CurrentBbsDevPathSize;\r
+ UINTN BootOrderIndex;\r
+ UINTN BootOrderLastIndex;\r
+ UINTN ArrayIndex;\r
+ BOOLEAN IndexNotFound;\r
+\r
+ if (NULL == (*BootOrderList)) {\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
+ 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
+ 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
+ SafeFreePool (Buffer);\r
+ Buffer = NULL;\r
+\r
+ NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+ if (NULL == NewBootOrderList) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (NULL != *BootOrderList) {\r
+ CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+ }\r
+\r
+ SafeFreePool (*BootOrderList);\r
+\r
+ BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+ NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;\r
+ *BootOrderListSize += sizeof (UINT16);\r
+ *BootOrderList = NewBootOrderList;\r
+\r
+ return Status;\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
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+ IN UINTN OptionNumber,\r
+ IN OUT UINT16 *BootOrder,\r
+ IN OUT UINTN *BootOrderSize\r
+ )\r
+{\r
+ UINT16 BootOption[100];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Index2Del;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2Del = 0;\r
+\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+ Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+ //\r
+ // adjust boot order array\r
+ //\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BootOrder[Index] == OptionNumber) {\r
+ Index2Del = Index;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+ if (Index >= Index2Del) {\r
+ BootOrder[Index] = BootOrder[Index + 1];\r
+ }\r
+ }\r
+\r
+ *BootOrderSize -= sizeof (UINT16);\r
+ }\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Delete all the invalid legacy boot options.\r
+\r
+ Arguments:\r
+\r
+ None.\r
+\r
+ Returns:\r
+\r
+ EFI_SUCCESS - All invalide legacy boot options are deleted.\r
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.\r
+ EFI_NOT_FOUND - Fail to retrive variable of boot order.\r
+ Other - Error occurs while setting variable or locating\r
+ protocol.\r
+\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 = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &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 (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
+ SafeFreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+ SafeFreePool (BootOptionVar);\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].BootPriority == BBS_LOWEST_PRIORITY)) &&\r
+ (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+ DescStringMatch) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ SafeFreePool (BootOptionVar);\r
+ //\r
+ // should delete\r
+ //\r
+ BdsDeleteBootOption (\r
+ BootOrder[Index],\r
+ BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ }\r
+\r
+ if (BootOrderSize) {\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
+ SafeFreePool (BootOrder);\r
+\r
+ return Status;\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
+ 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
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ if (BbsEntry->DeviceType != DevType) {\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ *Attribute = *(UINT32 *) BootOptionVar;\r
+ *OptionNumber = Index;\r
+ Found = TRUE;\r
+ SafeFreePool (BootOptionVar);\r
+ break;\r
+ }\r
+\r
+ return Found;\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
+ 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
+\r
+ Status = BdsCreateLegacyBootOption (\r
+ BbsItem,\r
+ DevPath,\r
+ Index,\r
+ BootOrderList,\r
+ BootOrderListSize\r
+ );\r
+ BbsItem->BootPriority = 0x00;\r
+\r
+ gBS->FreePool (DevPath);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The boot options are added successfully or they are already in boot options.\r
+ others - An error occurred when creating legacy boot options.\r
+\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, &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 (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 && (Attribute & LOAD_OPTION_ACTIVE) != 0) {\r
+ continue;\r
+ }\r
+\r
+ if (Ret) {\r
+ if (Index != BbsIndex) {\r
+ BdsDeleteBootOption (\r
+ OptionNumber,\r
+ BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ } else {\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
+ SafeFreePool (BootOrder);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+ IN BBS_TABLE *BbsTable,\r
+ IN BBS_TYPE BbsType,\r
+ IN UINTN BbsCount,\r
+ IN 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
+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
+ 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
+ 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) {\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) {\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) {\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) {\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) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ DevOrder\r
+ );\r
+ SafeFreePool (DevOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ )\r
+/*++\r
+Format of LegacyDevOrder variable:\r
+|-----------------------------------------------------------------------------------------------------------------\r
+| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...\r
+|-----------------------------------------------------------------------------------------------------------------\r
+\r
+Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.\r
+Index# is a 16 bit integer, the low byte of it stands for the index in BBS table\r
+ the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been\r
+ disabled by user.\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, &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
+ VarLegacyDevOrder,\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
+ (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)\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
+ 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].BootPriority == BBS_LOWEST_PRIORITY ||\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
+ (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)\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) {\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
+ // save it.\r
+ //\r
+ NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+ (*Idx)++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (FDCount) {\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) {\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) {\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) {\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) {\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
+\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
+ }\r
+ }\r
+ }\r
+\r
+ SafeFreePool (DevOrder);\r
+\r
+ Status = gRT->SetVariable (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ NewDevOrder\r
+ );\r
+ SafeFreePool (NewDevOrder);\r
+\r
+ return Status;\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
+DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on\r
+LocalBbsTable - BBS table instance\r
+Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot\r
+ priority can be used next time.\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
+ VarLegacyDevOrder,\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
+ SafeFreePool (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
+ //\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
+ SafeFreePool (OrigBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintBbsTable (\r
+ IN BBS_TABLE *LocalBbsTable\r
+ )\r
+{\r
+ UINT16 Idx;\r
+\r
+ DEBUG ((EFI_D_ERROR, "\n"));\r
+ DEBUG ((EFI_D_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+ DEBUG ((EFI_D_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
+ (EFI_D_ERROR,\r
+ " %02x: %04x %02x/%02x/%02x %02x/02%x %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 ((EFI_D_ERROR, "\n"));\r
+}\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, &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 && 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
+ SafeFreePool (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
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ Status = BdsSetBootPriority4SameTypeDev (\r
+ ((BBS_TABLE *) Ptr)->DeviceType,\r
+ LocalBbsTable,\r
+ &Priority\r
+ );\r
+ SafeFreePool (BootOptionVar);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (BootOrder) {\r
+ SafeFreePool (BootOrder);\r
+ }\r
+ //\r
+ // For debug\r
+ //\r
+ PrintBbsTable (LocalBbsTable);\r
+\r
+ return Status;\r
+}\r