+++ /dev/null
-/** @file\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
-Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "InternalLegacyBm.h"\r
-\r
-#define LEGACY_BM_BOOT_DESCRIPTION_LENGTH 32\r
-\r
-/**\r
- Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport\r
- function to export two function pointer.\r
-\r
- @param ImageHandle The image handle.\r
- @param SystemTable The system table.\r
-\r
- @retval EFI_SUCCESS The legacy boot manager library is initialized correctly.\r
- @return Other value if failed to initialize the legacy boot manager library.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-LegacyBootManagerLibConstructor (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
-)\r
-{\r
- EfiBootManagerRegisterLegacyBootSupport (\r
- LegacyBmRefreshAllBootOption,\r
- LegacyBmBoot\r
- );\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Get the device type from the input legacy device path.\r
-\r
- @param DevicePath The legacy device path.\r
-\r
- @retval The legacy device type.\r
-**/\r
-UINT16\r
-LegacyBmDeviceType (\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) &&\r
- (DevicePathSubType (DevicePath) == BBS_BBS_DP));\r
- return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType;\r
-}\r
-\r
-/**\r
- Validate the BbsEntry base on the Boot Priority info in the BbsEntry.\r
-\r
- @param BbsEntry The input bbs entry info.\r
-\r
- @retval TRUE The BbsEntry is valid.\r
- @retval FALSE The BbsEntry is invalid.\r
-**/\r
-BOOLEAN\r
-LegacyBmValidBbsEntry (\r
- IN BBS_TABLE *BbsEntry\r
- )\r
-{\r
- switch (BbsEntry->BootPriority) {\r
- case BBS_IGNORE_ENTRY:\r
- case BBS_DO_NOT_BOOT_FROM:\r
- case BBS_LOWEST_PRIORITY:\r
- return FALSE;\r
- default:\r
- return TRUE;\r
- }\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
-LegacyBmBuildLegacyDevNameString (\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
- CHAR8 *StringDesc;\r
- CHAR8 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
- CHAR16 StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\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 = (CHAR8 *) (((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
- CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH);\r
- StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0;\r
- AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, ARRAY_SIZE (StringBufferU));\r
- Fmt = L"%s";\r
- Type = StringBufferU;\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
- Get the Bbs index for the input boot option.\r
-\r
- @param BootOption The input boot option info.\r
- @param BbsTable The input Bbs table.\r
- @param BbsCount The input total bbs entry number.\r
- @param BbsIndexUsed The array shows how many BBS table indexs have been used.\r
-\r
- @retval The index for the input boot option.\r
-**/\r
-UINT16\r
-LegacyBmFuzzyMatch (\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,\r
- BBS_TABLE *BbsTable,\r
- UINT16 BbsCount,\r
- BOOLEAN *BbsIndexUsed\r
- )\r
-{\r
- UINT16 Index;\r
- LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData;\r
- CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
-\r
- BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData;\r
-\r
- //\r
- // Directly check the BBS index stored in BootOption\r
- //\r
- if ((BbsData->BbsIndex < BbsCount) &&\r
- (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) {\r
- LegacyBmBuildLegacyDevNameString (\r
- &BbsTable[BbsData->BbsIndex],\r
- BbsData->BbsIndex,\r
- sizeof (Description),\r
- Description\r
- );\r
- if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) {\r
- //\r
- // If devices with the same description string are connected,\r
- // the BbsIndex of the first device is returned for the other device also.\r
- // So, check if the BbsIndex is already being used, before assigning the BbsIndex.\r
- //\r
- BbsIndexUsed[BbsData->BbsIndex] = TRUE;\r
- return BbsData->BbsIndex;\r
- }\r
- }\r
-\r
- //\r
- // BBS table could be changed (entry removed/moved)\r
- // find the correct BBS index\r
- //\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (!LegacyBmValidBbsEntry (&BbsTable[Index]) ||\r
- (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) {\r
- continue;\r
- }\r
-\r
- LegacyBmBuildLegacyDevNameString (\r
- &BbsTable[Index],\r
- Index,\r
- sizeof (Description),\r
- Description\r
- );\r
- if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) {\r
- //\r
- // If devices with the same description string are connected,\r
- // the BbsIndex of the first device is assigned for the other device also.\r
- // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex.\r
- //\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Add the corrected BbsIndex in the UsedBbsIndex Buffer\r
- //\r
- if (Index != BbsCount) {\r
- BbsIndexUsed[Index] = TRUE;\r
- }\r
-\r
- return Index;\r
-}\r
-\r
-/**\r
-\r
- Update legacy device order base on the input info.\r
-\r
- @param LegacyDevOrder Legacy device order data buffer.\r
- @param LegacyDevOrderSize Legacy device order data buffer size.\r
- @param DeviceType Device type which need to check.\r
- @param OldBbsIndex Old Bds Index.\r
- @param NewBbsIndex New Bds Index, if it is -1,means remove this option.\r
-\r
-**/\r
-VOID\r
-LegacyBmUpdateBbsIndex (\r
- LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder,\r
- UINTN *LegacyDevOrderSize,\r
- UINT16 DeviceType,\r
- UINT16 OldBbsIndex,\r
- UINT16 NewBbsIndex // Delete entry if -1\r
- )\r
-{\r
- LEGACY_DEV_ORDER_ENTRY *Entry;\r
- UINTN Index;\r
-\r
- ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) ||\r
- ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0))\r
- );\r
-\r
- for (Entry = LegacyDevOrder;\r
- Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize);\r
- Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length)\r
- ) {\r
- if (Entry->BbsType == DeviceType) {\r
- for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) {\r
- if (Entry->Data[Index] == OldBbsIndex) {\r
- if (NewBbsIndex == (UINT16) -1) {\r
- //\r
- // Delete the old entry\r
- //\r
- CopyMem (\r
- &Entry->Data[Index],\r
- &Entry->Data[Index + 1],\r
- (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1]\r
- );\r
- Entry->Length -= sizeof (UINT16);\r
- *LegacyDevOrderSize -= sizeof(UINT16);\r
- } else {\r
- Entry->Data[Index] = NewBbsIndex;\r
- }\r
- break;\r
- }\r
- }\r
- break;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Delete all the legacy boot options.\r
-\r
- @retval EFI_SUCCESS All legacy boot options are deleted.\r
-**/\r
-EFI_STATUS\r
-LegacyBmDeleteAllBootOptions (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
- UINTN BootOptionCount;\r
-\r
- BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
- for (Index = 0; Index < BootOptionCount; Index++) {\r
- if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
- (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) {\r
- Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
- //\r
- // Deleting variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- }\r
-\r
- Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- 0,\r
- 0,\r
- NULL\r
- );\r
- //\r
- // Deleting variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
-\r
- return EFI_SUCCESS;\r
-}\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
-LegacyBmDeleteAllInvalidBootOptions (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *HddInfo;\r
- BBS_TABLE *BbsTable;\r
- UINT16 BbsIndex;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN Index;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;\r
- UINTN BootOptionCount;\r
- LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder;\r
- UINTN LegacyDevOrderSize;\r
- BOOLEAN *BbsIndexUsed;\r
-\r
- HddCount = 0;\r
- BbsCount = 0;\r
- HddInfo = NULL;\r
- BbsTable = 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
- &HddInfo,\r
- &BbsCount,\r
- &BbsTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize);\r
-\r
- BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
-\r
- BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN));\r
- ASSERT (BbsIndexUsed != NULL);\r
-\r
- for (Index = 0; Index < BootOptionCount; Index++) {\r
- //\r
- // Skip non legacy boot option\r
- //\r
- if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||\r
- (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) {\r
- continue;\r
- }\r
-\r
- BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed);\r
- if (BbsIndex == BbsCount) {\r
- DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description));\r
- //\r
- // Delete entry from LegacyDevOrder\r
- //\r
- LegacyBmUpdateBbsIndex (\r
- LegacyDevOrder,\r
- &LegacyDevOrderSize,\r
- LegacyBmDeviceType (BootOption[Index].FilePath),\r
- ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
- (UINT16) -1\r
- );\r
- EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
- } else {\r
- if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) {\r
- DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description,\r
- (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex));\r
- //\r
- // Update the BBS index in LegacyDevOrder\r
- //\r
- LegacyBmUpdateBbsIndex (\r
- LegacyDevOrder,\r
- &LegacyDevOrderSize,\r
- LegacyBmDeviceType (BootOption[Index].FilePath),\r
- ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
- BbsIndex\r
- );\r
-\r
- //\r
- // Update the OptionalData in the Boot#### variable\r
- //\r
- ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex;\r
- EfiBootManagerLoadOptionToVariable (&BootOption[Index]);\r
- }\r
- }\r
- }\r
- EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
-\r
- if (LegacyDevOrder != NULL) {\r
- Status = gRT->SetVariable (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- LegacyDevOrderSize,\r
- LegacyDevOrder\r
- );\r
- //\r
- // Shrink variable with current variable implementation shouldn't fail.\r
- //\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FreePool (LegacyDevOrder);\r
- }\r
- FreePool(BbsIndexUsed);\r
- return Status;\r
-}\r
-\r
-/**\r
- Create legacy boot option.\r
-\r
- @param BootOption Ponter to the boot option which will be crated.\r
- @param BbsEntry The input bbs entry info.\r
- @param BbsIndex The BBS index.\r
-\r
- @retval EFI_SUCCESS Create legacy boot option successfully.\r
- @retval EFI_INVALID_PARAMETER Invalid input parameter.\r
-\r
-**/\r
-EFI_STATUS\r
-LegacyBmCreateLegacyBootOption (\r
- IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption,\r
- IN BBS_TABLE *BbsEntry,\r
- IN UINT16 BbsIndex\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
- CHAR8 HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
- UINTN StringLen;\r
- LEGACY_BM_BOOT_OPTION_BBS_DATA *OptionalData;\r
- BBS_BBS_DEVICE_PATH *BbsNode;\r
-\r
- if ((BootOption == NULL) || (BbsEntry == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description);\r
-\r
- //\r
- // Create the BBS device path with description string\r
- //\r
- UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString));\r
- StringLen = AsciiStrLen (HelpString);\r
- DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH);\r
- ASSERT (DevicePath != NULL);\r
-\r
- BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath;\r
- SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
- BbsNode->Header.Type = BBS_DEVICE_PATH;\r
- BbsNode->Header.SubType = BBS_BBS_DP;\r
- BbsNode->DeviceType = BbsEntry->DeviceType;\r
- CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS));\r
- CopyMem (BbsNode->String, HelpString, StringLen + 1);\r
-\r
- SetDevicePathEndNode (NextDevicePathNode (BbsNode));\r
-\r
- //\r
- // Create the OptionalData\r
- //\r
- OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA));\r
- ASSERT (OptionalData != NULL);\r
- OptionalData->BbsIndex = BbsIndex;\r
-\r
- //\r
- // Create the BootOption\r
- //\r
- Status = EfiBootManagerInitializeLoadOption (\r
- BootOption,\r
- LoadOptionNumberUnassigned,\r
- LoadOptionTypeBoot,\r
- LOAD_OPTION_ACTIVE,\r
- Description,\r
- DevicePath,\r
- (UINT8 *) OptionalData,\r
- sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)\r
- );\r
- FreePool (DevicePath);\r
- FreePool (OptionalData);\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
-LegacyBmFillDevOrderBuf (\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 (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\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
- @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
-LegacyBmCreateDevOrder (\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 (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\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 *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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 *) LegacyBmFillDevOrderBuf (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
-LegacyBmUpdateDevOrder (\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
- 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
- GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL);\r
- if (NULL == DevOrder) {\r
- return LegacyBmCreateDevOrder (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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\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
- // 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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\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
-LegacyBmSetPriorityForSameTypeDev (\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
- GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &DevOrderSize);\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
- //\r
- // In case the BBS entry isn't valid because devices were plugged or removed.\r
- //\r
- if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) {\r
- FreePool (DevOrder);\r
- return EFI_NOT_FOUND;\r
- }\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
-LegacyBmPrintBbsTable (\r
- IN BBS_TABLE *LocalBbsTable,\r
- IN UINT16 BbsCount\r
- )\r
-{\r
- UINT16 Index;\r
-\r
- DEBUG ((DEBUG_INFO, "\n"));\r
- DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
- DEBUG ((DEBUG_INFO, "=============================================\n"));\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
- continue;\r
- }\r
-\r
- DEBUG (\r
- (DEBUG_INFO,\r
- " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
- (UINTN) Index,\r
- (UINTN) LocalBbsTable[Index].BootPriority,\r
- (UINTN) LocalBbsTable[Index].Bus,\r
- (UINTN) LocalBbsTable[Index].Device,\r
- (UINTN) LocalBbsTable[Index].Function,\r
- (UINTN) LocalBbsTable[Index].Class,\r
- (UINTN) LocalBbsTable[Index].SubClass,\r
- (UINTN) LocalBbsTable[Index].DeviceType,\r
- (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags,\r
- (UINTN) LocalBbsTable[Index].BootHandlerSegment,\r
- (UINTN) LocalBbsTable[Index].BootHandlerOffset,\r
- (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),\r
- (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))\r
- );\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "\n"));\r
-}\r
-\r
-/**\r
- Set the boot priority for BBS entries based on boot option entry and boot order.\r
-\r
- @param BootOption 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
-LegacyBmRefreshBbsTableForBoot (\r
- IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\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 *DeviceType;\r
- UINTN DeviceTypeCount;\r
- UINTN DeviceTypeIndex;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *Option;\r
- UINTN OptionCount;\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
- 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
- //\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 (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
- LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
- }\r
- }\r
- //\r
- // boot priority always starts at 0\r
- //\r
- Priority = 0;\r
- if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) &&\r
- (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {\r
- //\r
- // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first.\r
- //\r
- DevType = LegacyBmDeviceType (BootOption->FilePath);\r
- BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex;\r
- Status = LegacyBmSetPriorityForSameTypeDev (\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
- Option = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot);\r
- DeviceType = AllocatePool (sizeof (UINT16) * OptionCount);\r
- ASSERT (DeviceType != NULL);\r
- DeviceType[0] = DevType;\r
- DeviceTypeCount = 1;\r
- for (Index = 0; Index < OptionCount; Index++) {\r
- if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) ||\r
- (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) {\r
- continue;\r
- }\r
-\r
- DevType = LegacyBmDeviceType (Option[Index].FilePath);\r
- for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {\r
- if (DeviceType[DeviceTypeIndex] == DevType) {\r
- break;\r
- }\r
- }\r
- if (DeviceTypeIndex < DeviceTypeCount) {\r
- //\r
- // We don't want to process twice for a device type\r
- //\r
- continue;\r
- }\r
-\r
- DeviceType[DeviceTypeCount] = DevType;\r
- DeviceTypeCount++;\r
-\r
- Status = LegacyBmSetPriorityForSameTypeDev (\r
- DevType,\r
- (UINTN) -1,\r
- LocalBbsTable,\r
- &Priority\r
- );\r
- }\r
- EfiBootManagerFreeLoadOptions (Option, OptionCount);\r
-\r
- DEBUG_CODE_BEGIN();\r
- LegacyBmPrintBbsTable (LocalBbsTable, BbsCount);\r
- DEBUG_CODE_END();\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Boot the legacy system with the boot option.\r
-\r
- @param BootOption The legacy boot option which have BBS device path\r
- On return, BootOption->Status contains the boot status.\r
- EFI_UNSUPPORTED There is no legacybios protocol, do not support\r
- legacy boot.\r
- EFI_STATUS The status of LegacyBios->LegacyBoot ().\r
-**/\r
-VOID\r
-EFIAPI\r
-LegacyBmBoot (\r
- IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If no LegacyBios protocol we do not support legacy boot\r
- //\r
- BootOption->Status = EFI_UNSUPPORTED;\r
- return;\r
- }\r
- //\r
- // Notes: if we separate the int 19, then we don't need to refresh BBS\r
- //\r
- Status = LegacyBmRefreshBbsTableForBoot (BootOption);\r
- if (EFI_ERROR (Status)) {\r
- BootOption->Status = Status;\r
- return;\r
- }\r
-\r
- BootOption->Status = LegacyBios->LegacyBoot (\r
- LegacyBios,\r
- (BBS_BBS_DEVICE_PATH *) BootOption->FilePath,\r
- BootOption->OptionalDataSize,\r
- BootOption->OptionalData\r
- );\r
-}\r
-\r
-/**\r
- This function enumerates all the legacy boot options.\r
-\r
- @param BootOptionCount Return the legacy boot option count.\r
-\r
- @retval Pointer to the legacy boot option buffer.\r
-**/\r
-EFI_BOOT_MANAGER_LOAD_OPTION *\r
-LegacyBmEnumerateAllBootOptions (\r
- UINTN *BootOptionCount\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 HddCount;\r
- UINT16 BbsCount;\r
- HDD_INFO *HddInfo;\r
- BBS_TABLE *BbsTable;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINT16 Index;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
-\r
- ASSERT (BootOptionCount != NULL);\r
-\r
- BootOptions = NULL;\r
- *BootOptionCount = 0;\r
- BbsCount = 0;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- Status = LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &HddInfo,\r
- &BbsCount,\r
- &BbsTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\r
- continue;\r
- }\r
-\r
- BootOptions = ReallocatePool (\r
- sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
- sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
- BootOptions\r
- );\r
- ASSERT (BootOptions != NULL);\r
-\r
- Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- return BootOptions;\r
-}\r
-\r
-/**\r
- Return the index of the boot option in the boot option array.\r
-\r
- The function compares the Description, FilePath, OptionalData.\r
-\r
- @param Key The input boot option which is compared with.\r
- @param Array The input boot option array.\r
- @param Count The count of the input boot options.\r
-\r
- @retval The index of the input boot option in the array.\r
-\r
-**/\r
-INTN\r
-LegacyBmFindBootOption (\r
- IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
- IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
- IN UINTN Count\r
- )\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < Count; Index++) {\r
- if ((StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
- (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
- (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
- (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {\r
- return (INTN) Index;\r
- }\r
- }\r
-\r
- return -1;\r
-}\r
-\r
-/**\r
- Refresh all legacy boot options.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-LegacyBmRefreshAllBootOption (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN RootBridgeHandleCount;\r
- EFI_HANDLE *RootBridgeHandleBuffer;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN RootBridgeIndex;\r
- UINTN Index;\r
- UINTN Flags;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
- UINTN BootOptionCount;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *ExistingBootOptions;\r
- UINTN ExistingBootOptionCount;\r
-\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- LegacyBmDeleteAllBootOptions ();\r
- return;\r
- }\r
- PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
-\r
- //\r
- // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms\r
- // to ensure the GetBbsInfo() counts all the legacy devices.\r
- //\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiPciRootBridgeIoProtocolGuid,\r
- NULL,\r
- &RootBridgeHandleCount,\r
- &RootBridgeHandleBuffer\r
- );\r
- for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r
- gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiPciIoProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- //\r
- // Start the thunk driver so that the legacy option rom gets dispatched.\r
- // Note: We don't directly call InstallPciRom because some thunk drivers\r
- // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching\r
- //\r
- Status = LegacyBios->CheckPciRom (\r
- LegacyBios,\r
- HandleBuffer[Index],\r
- NULL,\r
- NULL,\r
- &Flags\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption\r
- // Firstly delete the invalid legacy boot options,\r
- // then enumreate and save the newly appeared legacy boot options\r
- // the last step is legacy boot option special action to refresh the LegacyDevOrder variable\r
- //\r
- LegacyBmDeleteAllInvalidBootOptions ();\r
-\r
- ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot);\r
- BootOptions = LegacyBmEnumerateAllBootOptions (&BootOptionCount);\r
-\r
- for (Index = 0; Index < BootOptionCount; Index++) {\r
- if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) {\r
- Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
- DEBUG ((\r
- EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n",\r
- (UINTN) BootOptions[Index].OptionNumber,\r
- (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex,\r
- BootOptions[Index].Description,\r
- Status\r
- ));\r
- //\r
- // Continue upon failure to add boot option.\r
- //\r
- }\r
- }\r
-\r
- EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount);\r
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-\r
- //\r
- // Failure to create LegacyDevOrder variable only impacts the boot order.\r
- //\r
- LegacyBmUpdateDevOrder ();\r
-\r
- PERF_END (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
-}\r