There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
	
		
			
				
	
	
		
			1537 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1537 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This function deal with the legacy boot option, it create, delete
 | |
|   and manage the legacy boot option, all legacy boot option is getting from
 | |
|   the legacy BBS table.
 | |
| 
 | |
| Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "InternalLegacyBm.h"
 | |
| 
 | |
| #define  LEGACY_BM_BOOT_DESCRIPTION_LENGTH  32
 | |
| 
 | |
| /**
 | |
|   Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport
 | |
|   function to export two function pointer.
 | |
| 
 | |
|   @param ImageHandle     The image handle.
 | |
|   @param SystemTable     The system table.
 | |
| 
 | |
|   @retval EFI_SUCCESS    The legacy boot manager library is initialized correctly.
 | |
|   @return Other value if failed to initialize the legacy boot manager library.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootManagerLibConstructor (
 | |
|   IN EFI_HANDLE                            ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE                      *SystemTable
 | |
| )
 | |
| {
 | |
|   EfiBootManagerRegisterLegacyBootSupport (
 | |
|     LegacyBmRefreshAllBootOption,
 | |
|     LegacyBmBoot
 | |
|     );
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the device type from the input legacy device path.
 | |
| 
 | |
|   @param DevicePath     The legacy device path.
 | |
| 
 | |
|   @retval               The legacy device type.
 | |
| **/
 | |
| UINT16
 | |
| LegacyBmDeviceType (
 | |
|   EFI_DEVICE_PATH_PROTOCOL *DevicePath
 | |
|   )
 | |
| {
 | |
|   ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) &&
 | |
|           (DevicePathSubType (DevicePath) == BBS_BBS_DP));
 | |
|   return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate the BbsEntry base on the Boot Priority info in the BbsEntry.
 | |
| 
 | |
|   @param BbsEntry       The input bbs entry info.
 | |
| 
 | |
|   @retval TRUE          The BbsEntry is valid.
 | |
|   @retval FALSE         The BbsEntry is invalid.
 | |
| **/
 | |
| BOOLEAN
 | |
| LegacyBmValidBbsEntry (
 | |
|   IN BBS_TABLE   *BbsEntry
 | |
|   )
 | |
| {
 | |
|   switch (BbsEntry->BootPriority) {
 | |
|     case BBS_IGNORE_ENTRY:
 | |
|     case BBS_DO_NOT_BOOT_FROM:
 | |
|     case BBS_LOWEST_PRIORITY:
 | |
|       return FALSE;
 | |
|     default:
 | |
|       return TRUE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Build Legacy Device Name String according.
 | |
| 
 | |
|   @param CurBBSEntry     BBS Table.
 | |
|   @param Index           Index.
 | |
|   @param BufSize         The buffer size.
 | |
|   @param BootString      The output string.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| LegacyBmBuildLegacyDevNameString (
 | |
|   IN  BBS_TABLE                 *CurBBSEntry,
 | |
|   IN  UINTN                     Index,
 | |
|   IN  UINTN                     BufSize,
 | |
|   OUT CHAR16                    *BootString
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Fmt;
 | |
|   CHAR16  *Type;
 | |
|   CHAR8   *StringDesc;
 | |
|   CHAR8   StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];
 | |
|   CHAR16  StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];
 | |
| 
 | |
|   switch (Index) {
 | |
|   //
 | |
|   // Primary Master
 | |
|   //
 | |
|   case 1:
 | |
|     Fmt = L"Primary Master %s";
 | |
|     break;
 | |
| 
 | |
|  //
 | |
|  // Primary Slave
 | |
|  //
 | |
|   case 2:
 | |
|     Fmt = L"Primary Slave %s";
 | |
|     break;
 | |
| 
 | |
|   //
 | |
|   // Secondary Master
 | |
|   //
 | |
|   case 3:
 | |
|     Fmt = L"Secondary Master %s";
 | |
|     break;
 | |
| 
 | |
|   //
 | |
|   // Secondary Slave
 | |
|   //
 | |
|   case 4:
 | |
|     Fmt = L"Secondary Slave %s";
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     Fmt = L"%s";
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   switch (CurBBSEntry->DeviceType) {
 | |
|   case BBS_FLOPPY:
 | |
|     Type = L"Floppy";
 | |
|     break;
 | |
| 
 | |
|   case BBS_HARDDISK:
 | |
|     Type = L"Harddisk";
 | |
|     break;
 | |
| 
 | |
|   case BBS_CDROM:
 | |
|     Type = L"CDROM";
 | |
|     break;
 | |
| 
 | |
|   case BBS_PCMCIA:
 | |
|     Type = L"PCMCIAe";
 | |
|     break;
 | |
| 
 | |
|   case BBS_USB:
 | |
|     Type = L"USB";
 | |
|     break;
 | |
| 
 | |
|   case BBS_EMBED_NETWORK:
 | |
|     Type = L"Network";
 | |
|     break;
 | |
| 
 | |
|   case BBS_BEV_DEVICE:
 | |
|     Type = L"BEVe";
 | |
|     break;
 | |
| 
 | |
|   case BBS_UNKNOWN:
 | |
|   default:
 | |
|     Type = L"Unknown";
 | |
|     break;
 | |
|   }
 | |
|   //
 | |
|   // If current BBS entry has its description then use it.
 | |
|   //
 | |
|   StringDesc = (CHAR8 *) (((UINTN) CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
 | |
|   if (NULL != StringDesc) {
 | |
|     //
 | |
|     // Only get fisrt 32 characters, this is suggested by BBS spec
 | |
|     //
 | |
|     CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH);
 | |
|     StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0;
 | |
|     AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, ARRAY_SIZE (StringBufferU));
 | |
|     Fmt   = L"%s";
 | |
|     Type  = StringBufferU;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // BbsTable 16 entries are for onboard IDE.
 | |
|   // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
 | |
|   //
 | |
|   if (Index >= 5 && Index <= 16 && (CurBBSEntry->DeviceType == BBS_HARDDISK || CurBBSEntry->DeviceType == BBS_CDROM)) {
 | |
|     Fmt = L"%s %d";
 | |
|     UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);
 | |
|   } else {
 | |
|     UnicodeSPrint (BootString, BufSize, Fmt, Type);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the Bbs index for the input boot option.
 | |
| 
 | |
|   @param BootOption     The input boot option info.
 | |
|   @param BbsTable       The input Bbs table.
 | |
|   @param BbsCount       The input total bbs entry number.
 | |
|   @param BbsIndexUsed   The array shows how many BBS table indexs have been used.
 | |
| 
 | |
|   @retval The index for the input boot option.
 | |
| **/
 | |
| UINT16
 | |
| LegacyBmFuzzyMatch (
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION   *BootOption,
 | |
|   BBS_TABLE                      *BbsTable,
 | |
|   UINT16                         BbsCount,
 | |
|   BOOLEAN                        *BbsIndexUsed
 | |
|   )
 | |
| {
 | |
|   UINT16                         Index;
 | |
|   LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData;
 | |
|   CHAR16                         Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];
 | |
| 
 | |
|   BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData;
 | |
| 
 | |
|   //
 | |
|   // Directly check the BBS index stored in BootOption
 | |
|   //
 | |
|   if ((BbsData->BbsIndex < BbsCount) &&
 | |
|       (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) {
 | |
|     LegacyBmBuildLegacyDevNameString (
 | |
|       &BbsTable[BbsData->BbsIndex],
 | |
|       BbsData->BbsIndex,
 | |
|       sizeof (Description),
 | |
|       Description
 | |
|       );
 | |
|     if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) {
 | |
|       //
 | |
|       // If devices with the same description string are connected, 
 | |
|       // the BbsIndex of the first device is returned for the other device also.
 | |
|       // So, check if the BbsIndex is already being used, before assigning the BbsIndex.
 | |
|       //
 | |
|       BbsIndexUsed[BbsData->BbsIndex] = TRUE;
 | |
|       return BbsData->BbsIndex;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // BBS table could be changed (entry removed/moved)
 | |
|   // find the correct BBS index
 | |
|   //
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&BbsTable[Index]) ||
 | |
|         (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     LegacyBmBuildLegacyDevNameString (
 | |
|       &BbsTable[Index],
 | |
|       Index,
 | |
|       sizeof (Description),
 | |
|       Description
 | |
|       );
 | |
|     if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) {
 | |
|       //
 | |
|       // If devices with the same description string are connected, 
 | |
|       // the BbsIndex of the first device is assigned for the other device also.
 | |
|       // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex.
 | |
|       //
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add the corrected BbsIndex in the UsedBbsIndex Buffer
 | |
|   //
 | |
|   if (Index != BbsCount) {
 | |
|     BbsIndexUsed[Index] = TRUE;
 | |
|   }
 | |
| 
 | |
|   return Index;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Update legacy device order base on the input info.
 | |
| 
 | |
|   @param   LegacyDevOrder     Legacy device order data buffer.
 | |
|   @param   LegacyDevOrderSize Legacy device order data buffer size.
 | |
|   @param   DeviceType         Device type which need to check.
 | |
|   @param   OldBbsIndex        Old Bds Index.
 | |
|   @param   NewBbsIndex        New Bds Index, if it is -1,means remove this option.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| LegacyBmUpdateBbsIndex (
 | |
|   LEGACY_DEV_ORDER_ENTRY   *LegacyDevOrder,
 | |
|   UINTN                    *LegacyDevOrderSize,
 | |
|   UINT16                   DeviceType,
 | |
|   UINT16                   OldBbsIndex,
 | |
|   UINT16                   NewBbsIndex // Delete entry if -1
 | |
|   )
 | |
| {
 | |
|   LEGACY_DEV_ORDER_ENTRY   *Entry;
 | |
|   UINTN                    Index;
 | |
| 
 | |
|   ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) ||
 | |
|           ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0))
 | |
|          );
 | |
| 
 | |
|   for (Entry = LegacyDevOrder; 
 | |
|        Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize);
 | |
|        Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length)
 | |
|        ) {
 | |
|     if (Entry->BbsType == DeviceType) {
 | |
|       for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) {
 | |
|         if (Entry->Data[Index] == OldBbsIndex) {
 | |
|           if (NewBbsIndex == (UINT16) -1) {
 | |
|             //
 | |
|             // Delete the old entry
 | |
|             //
 | |
|             CopyMem (
 | |
|               &Entry->Data[Index], 
 | |
|               &Entry->Data[Index + 1], 
 | |
|               (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1]
 | |
|               );
 | |
|             Entry->Length       -= sizeof (UINT16);
 | |
|             *LegacyDevOrderSize -= sizeof(UINT16);
 | |
|           } else {
 | |
|             Entry->Data[Index]   = NewBbsIndex;
 | |
|           }
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Delete all the legacy boot options.
 | |
| 
 | |
|   @retval EFI_SUCCESS            All legacy boot options are deleted.
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmDeleteAllBootOptions (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINTN                         Index;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;
 | |
|   UINTN                         BootOptionCount;
 | |
| 
 | |
|   BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
 | |
|   for (Index = 0; Index < BootOptionCount; Index++) {
 | |
|     if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&
 | |
|         (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) {
 | |
|       Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);
 | |
|       //
 | |
|       // Deleting variable with current variable implementation shouldn't fail.
 | |
|       //
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = gRT->SetVariable (
 | |
|                   VAR_LEGACY_DEV_ORDER,
 | |
|                   &gEfiLegacyDevOrderVariableGuid,
 | |
|                   0,
 | |
|                   0,
 | |
|                   NULL
 | |
|                   );
 | |
|   //
 | |
|   // Deleting variable with current variable implementation shouldn't fail.
 | |
|   //
 | |
|   ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Delete all the invalid legacy boot options.
 | |
| 
 | |
|   @retval EFI_SUCCESS             All invalide legacy boot options are deleted.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Fail to allocate necessary memory.
 | |
|   @retval EFI_NOT_FOUND           Fail to retrive variable of boot order.
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmDeleteAllInvalidBootOptions (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINT16                        HddCount;
 | |
|   UINT16                        BbsCount;
 | |
|   HDD_INFO                      *HddInfo;
 | |
|   BBS_TABLE                     *BbsTable;
 | |
|   UINT16                        BbsIndex;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL      *LegacyBios;
 | |
|   UINTN                         Index;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;
 | |
|   UINTN                         BootOptionCount;
 | |
|   LEGACY_DEV_ORDER_ENTRY        *LegacyDevOrder;
 | |
|   UINTN                         LegacyDevOrderSize;
 | |
|   BOOLEAN                       *BbsIndexUsed;
 | |
| 
 | |
|   HddCount      = 0;
 | |
|   BbsCount      = 0;
 | |
|   HddInfo       = NULL;
 | |
|   BbsTable      = NULL;
 | |
| 
 | |
|   Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = LegacyBios->GetBbsInfo (
 | |
|                          LegacyBios,
 | |
|                          &HddCount,
 | |
|                          &HddInfo,
 | |
|                          &BbsCount,
 | |
|                          &BbsTable
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize);
 | |
| 
 | |
|   BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
 | |
| 
 | |
|   BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN));
 | |
|   ASSERT (BbsIndexUsed != NULL);
 | |
| 
 | |
|   for (Index = 0; Index < BootOptionCount; Index++) {
 | |
|     //
 | |
|     // Skip non legacy boot option
 | |
|     //
 | |
|     if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||
 | |
|         (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed);
 | |
|     if (BbsIndex == BbsCount) {
 | |
|       DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description));
 | |
|       //
 | |
|       // Delete entry from LegacyDevOrder
 | |
|       //
 | |
|       LegacyBmUpdateBbsIndex (
 | |
|         LegacyDevOrder,
 | |
|         &LegacyDevOrderSize,
 | |
|         LegacyBmDeviceType (BootOption[Index].FilePath),
 | |
|         ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,
 | |
|         (UINT16) -1
 | |
|         );
 | |
|       EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);
 | |
|     } else {
 | |
|       if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) {
 | |
|         DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description,
 | |
|                 (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex));
 | |
|         //
 | |
|         // Update the BBS index in LegacyDevOrder
 | |
|         //
 | |
|         LegacyBmUpdateBbsIndex (
 | |
|           LegacyDevOrder,
 | |
|           &LegacyDevOrderSize,
 | |
|           LegacyBmDeviceType (BootOption[Index].FilePath),
 | |
|           ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,
 | |
|           BbsIndex
 | |
|           );
 | |
| 
 | |
|         //
 | |
|         // Update the OptionalData in the Boot#### variable
 | |
|         //
 | |
|         ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex;
 | |
|         EfiBootManagerLoadOptionToVariable (&BootOption[Index]);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
 | |
| 
 | |
|   if (LegacyDevOrder != NULL) {
 | |
|     Status = gRT->SetVariable (
 | |
|                     VAR_LEGACY_DEV_ORDER,
 | |
|                     &gEfiLegacyDevOrderVariableGuid,
 | |
|                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                     LegacyDevOrderSize,
 | |
|                     LegacyDevOrder
 | |
|                     );
 | |
|     //
 | |
|     // Shrink variable with current variable implementation shouldn't fail.
 | |
|     //
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     FreePool (LegacyDevOrder);
 | |
|   }
 | |
|   FreePool(BbsIndexUsed);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create legacy boot option.
 | |
| 
 | |
|   @param BootOption        Ponter to the boot option which will be crated.
 | |
|   @param BbsEntry          The input bbs entry info.
 | |
|   @param BbsIndex          The BBS index.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Create legacy boot option successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Invalid input parameter.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmCreateLegacyBootOption (
 | |
|   IN OUT EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption,
 | |
|   IN BBS_TABLE                         *BbsEntry,
 | |
|   IN UINT16                            BbsIndex
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
 | |
|   CHAR16                       Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];
 | |
|   CHAR8                        HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];
 | |
|   UINTN                        StringLen;
 | |
|   LEGACY_BM_BOOT_OPTION_BBS_DATA  *OptionalData;
 | |
|   BBS_BBS_DEVICE_PATH          *BbsNode;
 | |
| 
 | |
|   if ((BootOption == NULL) || (BbsEntry == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description);
 | |
| 
 | |
|   //
 | |
|   // Create the BBS device path with description string
 | |
|   //
 | |
|   UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString));
 | |
|   StringLen = AsciiStrLen (HelpString);
 | |
|   DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH);
 | |
|   ASSERT (DevicePath != NULL);
 | |
| 
 | |
|   BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath;
 | |
|   SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
 | |
|   BbsNode->Header.Type    = BBS_DEVICE_PATH;
 | |
|   BbsNode->Header.SubType = BBS_BBS_DP;
 | |
|   BbsNode->DeviceType     = BbsEntry->DeviceType;
 | |
|   CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS));
 | |
|   CopyMem (BbsNode->String, HelpString, StringLen + 1);
 | |
| 
 | |
|   SetDevicePathEndNode (NextDevicePathNode (BbsNode));
 | |
| 
 | |
|   //
 | |
|   // Create the OptionalData
 | |
|   //
 | |
|   OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA));
 | |
|   ASSERT (OptionalData != NULL);
 | |
|   OptionalData->BbsIndex = BbsIndex;
 | |
| 
 | |
|   //
 | |
|   // Create the BootOption
 | |
|   //
 | |
|   Status = EfiBootManagerInitializeLoadOption (
 | |
|              BootOption,
 | |
|              LoadOptionNumberUnassigned,
 | |
|              LoadOptionTypeBoot,
 | |
|              LOAD_OPTION_ACTIVE,
 | |
|              Description,
 | |
|              DevicePath,
 | |
|              (UINT8 *) OptionalData,
 | |
|              sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)
 | |
|              );
 | |
|   FreePool (DevicePath);
 | |
|   FreePool (OptionalData);
 | |
|   
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Fill the device order buffer.
 | |
| 
 | |
|   @param BbsTable        The BBS table.
 | |
|   @param BbsType         The BBS Type.
 | |
|   @param BbsCount        The BBS Count.
 | |
|   @param Buf             device order buffer.
 | |
| 
 | |
|   @return The device order buffer.
 | |
| 
 | |
| **/
 | |
| UINT16 *
 | |
| LegacyBmFillDevOrderBuf (
 | |
|   IN BBS_TABLE                    *BbsTable,
 | |
|   IN BBS_TYPE                     BbsType,
 | |
|   IN UINTN                        BbsCount,
 | |
|   OUT UINT16                      *Buf
 | |
|   )
 | |
| {
 | |
|   UINTN Index;
 | |
| 
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (BbsTable[Index].DeviceType != BbsType) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     *Buf = (UINT16) (Index & 0xFF);
 | |
|     Buf++;
 | |
|   }
 | |
| 
 | |
|   return Buf;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create the device order buffer.
 | |
| 
 | |
|   @param BbsTable        The BBS table.
 | |
|   @param BbsCount        The BBS Count.
 | |
| 
 | |
|   @retval EFI_SUCCES             The buffer is created and the EFI variable named 
 | |
|                                  VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is
 | |
|                                  set correctly.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Memmory or storage is not enough.
 | |
|   @retval EFI_DEVICE_ERROR       Fail to add the device order into EFI variable fail
 | |
|                                  because of hardware error.
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmCreateDevOrder (
 | |
|   IN BBS_TABLE                  *BbsTable,
 | |
|   IN UINT16                     BbsCount
 | |
|   )
 | |
| {
 | |
|   UINTN                       Index;
 | |
|   UINTN                       FDCount;
 | |
|   UINTN                       HDCount;
 | |
|   UINTN                       CDCount;
 | |
|   UINTN                       NETCount;
 | |
|   UINTN                       BEVCount;
 | |
|   UINTN                       TotalSize;
 | |
|   UINTN                       HeaderSize;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   FDCount     = 0;
 | |
|   HDCount     = 0;
 | |
|   CDCount     = 0;
 | |
|   NETCount    = 0;
 | |
|   BEVCount    = 0;
 | |
|   TotalSize   = 0;
 | |
|   HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);
 | |
|   DevOrder    = NULL;
 | |
|   Status      = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // Count all boot devices
 | |
|   //
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     switch (BbsTable[Index].DeviceType) {
 | |
|     case BBS_FLOPPY:
 | |
|       FDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_HARDDISK:
 | |
|       HDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_CDROM:
 | |
|       CDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_EMBED_NETWORK:
 | |
|       NETCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_BEV_DEVICE:
 | |
|       BEVCount++;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
 | |
|   TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
 | |
|   TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
 | |
|   TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
 | |
|   TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
 | |
| 
 | |
|   //
 | |
|   // Create buffer to hold all boot device order
 | |
|   //
 | |
|   DevOrder = AllocateZeroPool (TotalSize);
 | |
|   if (NULL == DevOrder) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   DevOrderPtr          = DevOrder;
 | |
| 
 | |
|   DevOrderPtr->BbsType = BBS_FLOPPY;
 | |
|   DevOrderPtr->Length  = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));
 | |
|   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);
 | |
| 
 | |
|   DevOrderPtr->BbsType = BBS_HARDDISK;
 | |
|   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
 | |
|   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);
 | |
|   
 | |
|   DevOrderPtr->BbsType = BBS_CDROM;
 | |
|   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
 | |
|   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);
 | |
|   
 | |
|   DevOrderPtr->BbsType = BBS_EMBED_NETWORK;
 | |
|   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
 | |
|   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);
 | |
| 
 | |
|   DevOrderPtr->BbsType = BBS_BEV_DEVICE;
 | |
|   DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
 | |
|   DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);
 | |
| 
 | |
|   ASSERT (TotalSize == ((UINTN) DevOrderPtr - (UINTN) DevOrder));
 | |
| 
 | |
|   //
 | |
|   // Save device order for legacy boot device to variable.
 | |
|   //
 | |
|   Status = gRT->SetVariable (
 | |
|                   VAR_LEGACY_DEV_ORDER,
 | |
|                   &gEfiLegacyDevOrderVariableGuid,
 | |
|                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                   TotalSize,
 | |
|                   DevOrder
 | |
|                   );
 | |
|   FreePool (DevOrder);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Add the legacy boot devices from BBS table into 
 | |
|   the legacy device boot order.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The boot devices are added successfully.
 | |
|   @retval EFI_NOT_FOUND         The legacy boot devices are not found.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Memmory or storage is not enough.
 | |
|   @retval EFI_DEVICE_ERROR      Fail to add the legacy device boot order into EFI variable
 | |
|                                 because of hardware error.
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmUpdateDevOrder (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *NewDevOrder;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *Ptr;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *NewPtr;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;
 | |
|   EFI_STATUS                  Status;
 | |
|   UINT16                      HddCount;
 | |
|   UINT16                      BbsCount;
 | |
|   HDD_INFO                    *LocalHddInfo;
 | |
|   BBS_TABLE                   *LocalBbsTable;
 | |
|   UINTN                       Index;
 | |
|   UINTN                       Index2;
 | |
|   UINTN                       *Idx;
 | |
|   UINTN                       FDCount;
 | |
|   UINTN                       HDCount;
 | |
|   UINTN                       CDCount;
 | |
|   UINTN                       NETCount;
 | |
|   UINTN                       BEVCount;
 | |
|   UINTN                       TotalSize;
 | |
|   UINTN                       HeaderSize;
 | |
|   UINT16                      *NewFDPtr;
 | |
|   UINT16                      *NewHDPtr;
 | |
|   UINT16                      *NewCDPtr;
 | |
|   UINT16                      *NewNETPtr;
 | |
|   UINT16                      *NewBEVPtr;
 | |
|   UINT16                      *NewDevPtr;
 | |
|   UINTN                       FDIndex;
 | |
|   UINTN                       HDIndex;
 | |
|   UINTN                       CDIndex;
 | |
|   UINTN                       NETIndex;
 | |
|   UINTN                       BEVIndex;
 | |
| 
 | |
|   Idx           = NULL;
 | |
|   FDCount       = 0;
 | |
|   HDCount       = 0;
 | |
|   CDCount       = 0;
 | |
|   NETCount      = 0;
 | |
|   BEVCount      = 0;
 | |
|   TotalSize     = 0;
 | |
|   HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);
 | |
|   FDIndex       = 0;
 | |
|   HDIndex       = 0;
 | |
|   CDIndex       = 0;
 | |
|   NETIndex      = 0;
 | |
|   BEVIndex      = 0;
 | |
|   NewDevPtr     = NULL;
 | |
| 
 | |
|   Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = LegacyBios->GetBbsInfo (
 | |
|                          LegacyBios,
 | |
|                          &HddCount,
 | |
|                          &LocalHddInfo,
 | |
|                          &BbsCount,
 | |
|                          &LocalBbsTable
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL);
 | |
|   if (NULL == DevOrder) {
 | |
|     return LegacyBmCreateDevOrder (LocalBbsTable, BbsCount);
 | |
|   }
 | |
|   //
 | |
|   // First we figure out how many boot devices with same device type respectively
 | |
|   //
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     switch (LocalBbsTable[Index].DeviceType) {
 | |
|     case BBS_FLOPPY:
 | |
|       FDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_HARDDISK:
 | |
|       HDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_CDROM:
 | |
|       CDCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_EMBED_NETWORK:
 | |
|       NETCount++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_BEV_DEVICE:
 | |
|       BEVCount++;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
 | |
|   TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
 | |
|   TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
 | |
|   TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
 | |
|   TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
 | |
| 
 | |
|   NewDevOrder = AllocateZeroPool (TotalSize);
 | |
|   if (NULL == NewDevOrder) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // copy FD
 | |
|   //
 | |
|   Ptr             = DevOrder;
 | |
|   NewPtr          = NewDevOrder;
 | |
|   NewPtr->BbsType = Ptr->BbsType;
 | |
|   NewPtr->Length  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
 | |
|   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||
 | |
|         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY
 | |
|         ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NewPtr->Data[FDIndex] = Ptr->Data[Index];
 | |
|     FDIndex++;
 | |
|   }
 | |
|   NewFDPtr = NewPtr->Data;
 | |
| 
 | |
|   //
 | |
|   // copy HD
 | |
|   //
 | |
|   Ptr             = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
 | |
|   NewPtr          = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
 | |
|   NewPtr->BbsType = Ptr->BbsType;
 | |
|   NewPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
 | |
|   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||
 | |
|         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK
 | |
|         ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NewPtr->Data[HDIndex] = Ptr->Data[Index];
 | |
|     HDIndex++;
 | |
|   }
 | |
|   NewHDPtr = NewPtr->Data;
 | |
| 
 | |
|   //
 | |
|   // copy CD
 | |
|   //
 | |
|   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
 | |
|   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
 | |
|   NewPtr->BbsType = Ptr->BbsType;
 | |
|   NewPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
 | |
|   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||
 | |
|         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM
 | |
|         ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NewPtr->Data[CDIndex] = Ptr->Data[Index];
 | |
|     CDIndex++;
 | |
|   }
 | |
|   NewCDPtr = NewPtr->Data;
 | |
| 
 | |
|   //
 | |
|   // copy NET
 | |
|   //
 | |
|   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
 | |
|   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
 | |
|   NewPtr->BbsType = Ptr->BbsType;
 | |
|   NewPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
 | |
|   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||
 | |
|         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK
 | |
|         ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NewPtr->Data[NETIndex] = Ptr->Data[Index];
 | |
|     NETIndex++;
 | |
|   }
 | |
|   NewNETPtr = NewPtr->Data;
 | |
|   
 | |
|   //
 | |
|   // copy BEV
 | |
|   //
 | |
|   Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);
 | |
|   NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);
 | |
|   NewPtr->BbsType = Ptr->BbsType;
 | |
|   NewPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
 | |
|   for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||
 | |
|         LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE
 | |
|         ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NewPtr->Data[BEVIndex] = Ptr->Data[Index];
 | |
|     BEVIndex++;
 | |
|   }
 | |
|   NewBEVPtr = NewPtr->Data;
 | |
| 
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     switch (LocalBbsTable[Index].DeviceType) {
 | |
|     case BBS_FLOPPY:
 | |
|       Idx       = &FDIndex;
 | |
|       NewDevPtr = NewFDPtr;
 | |
|       break;
 | |
| 
 | |
|     case BBS_HARDDISK:
 | |
|       Idx       = &HDIndex;
 | |
|       NewDevPtr = NewHDPtr;
 | |
|       break;
 | |
| 
 | |
|     case BBS_CDROM:
 | |
|       Idx       = &CDIndex;
 | |
|       NewDevPtr = NewCDPtr;
 | |
|       break;
 | |
| 
 | |
|     case BBS_EMBED_NETWORK:
 | |
|       Idx       = &NETIndex;
 | |
|       NewDevPtr = NewNETPtr;
 | |
|       break;
 | |
| 
 | |
|     case BBS_BEV_DEVICE:
 | |
|       Idx       = &BEVIndex;
 | |
|       NewDevPtr = NewBEVPtr;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       Idx = NULL;
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // at this point we have copied those valid indexes to new buffer
 | |
|     // and we should check if there is any new appeared boot device
 | |
|     //
 | |
|     if (Idx != NULL) {
 | |
|       for (Index2 = 0; Index2 < *Idx; Index2++) {
 | |
|         if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (Index2 == *Idx) {
 | |
|         //
 | |
|         // Index2 == *Idx means we didn't find Index
 | |
|         // so Index is a new appeared device's index in BBS table
 | |
|         // insert it before disabled indexes.
 | |
|         //
 | |
|         for (Index2 = 0; Index2 < *Idx; Index2++) {
 | |
|           if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));
 | |
|         NewDevPtr[Index2] = (UINT16) (Index & 0xFF);
 | |
|         (*Idx)++;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool (DevOrder);
 | |
| 
 | |
|   Status = gRT->SetVariable (
 | |
|                   VAR_LEGACY_DEV_ORDER,
 | |
|                   &gEfiLegacyDevOrderVariableGuid,
 | |
|                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                   TotalSize,
 | |
|                   NewDevOrder
 | |
|                   );
 | |
|   FreePool (NewDevOrder);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set Boot Priority for specified device type.
 | |
| 
 | |
|   @param DeviceType      The device type.
 | |
|   @param BbsIndex        The BBS index to set the highest priority. Ignore when -1.
 | |
|   @param LocalBbsTable   The BBS table.
 | |
|   @param Priority        The prority table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The function completes successfully.
 | |
|   @retval EFI_NOT_FOUND         Failed to find device.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Failed to get the efi variable of device order.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmSetPriorityForSameTypeDev (
 | |
|   IN UINT16                                              DeviceType,
 | |
|   IN UINTN                                               BbsIndex,
 | |
|   IN OUT BBS_TABLE                                       *LocalBbsTable,
 | |
|   IN OUT UINT16                                          *Priority
 | |
|   )
 | |
| {
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;
 | |
|   UINTN                       DevOrderSize;
 | |
|   UINTN                       Index;
 | |
| 
 | |
|   GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &DevOrderSize);
 | |
|   if (NULL == DevOrder) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   DevOrderPtr = DevOrder;
 | |
|   while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {
 | |
|     if (DevOrderPtr->BbsType == DeviceType) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);
 | |
|   }
 | |
| 
 | |
|   if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {
 | |
|     FreePool (DevOrder);
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if (BbsIndex != (UINTN) -1) {
 | |
|     //
 | |
|     // In case the BBS entry isn't valid because devices were plugged or removed.
 | |
|     //
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) {
 | |
|       FreePool (DevOrder);
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
|     LocalBbsTable[BbsIndex].BootPriority = *Priority;
 | |
|     (*Priority)++;
 | |
|   }
 | |
|   //
 | |
|   // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
 | |
|   //
 | |
|   for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {
 | |
|     if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {
 | |
|       //
 | |
|       // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
 | |
|       //
 | |
|     } else if (DevOrderPtr->Data[Index] != BbsIndex) {
 | |
|       LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;
 | |
|       (*Priority)++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool (DevOrder);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Print the BBS Table.
 | |
| 
 | |
|   @param LocalBbsTable   The BBS table.
 | |
|   @param BbsCount        The count of entry in BBS table.
 | |
| **/
 | |
| VOID
 | |
| LegacyBmPrintBbsTable (
 | |
|   IN BBS_TABLE  *LocalBbsTable,
 | |
|   IN UINT16     BbsCount
 | |
|   )
 | |
| {
 | |
|   UINT16  Index;
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "\n"));
 | |
|   DEBUG ((DEBUG_INFO, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
 | |
|   DEBUG ((DEBUG_INFO, "=============================================\n"));
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DEBUG (
 | |
|       (DEBUG_INFO,
 | |
|       " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
 | |
|       (UINTN) Index,
 | |
|       (UINTN) LocalBbsTable[Index].BootPriority,
 | |
|       (UINTN) LocalBbsTable[Index].Bus,
 | |
|       (UINTN) LocalBbsTable[Index].Device,
 | |
|       (UINTN) LocalBbsTable[Index].Function,
 | |
|       (UINTN) LocalBbsTable[Index].Class,
 | |
|       (UINTN) LocalBbsTable[Index].SubClass,
 | |
|       (UINTN) LocalBbsTable[Index].DeviceType,
 | |
|       (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags,
 | |
|       (UINTN) LocalBbsTable[Index].BootHandlerSegment,
 | |
|       (UINTN) LocalBbsTable[Index].BootHandlerOffset,
 | |
|       (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),
 | |
|       (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "\n"));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the boot priority for BBS entries based on boot option entry and boot order.
 | |
| 
 | |
|   @param  BootOption            The boot option is to be checked for refresh BBS table.
 | |
|   
 | |
|   @retval EFI_SUCCESS           The boot priority for BBS entries is refreshed successfully.
 | |
|   @retval EFI_NOT_FOUND         BBS entries can't be found.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Failed to get the legacy device boot order.
 | |
| **/
 | |
| EFI_STATUS
 | |
| LegacyBmRefreshBbsTableForBoot (
 | |
|   IN EFI_BOOT_MANAGER_LOAD_OPTION        *BootOption
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINT16                        BbsIndex;
 | |
|   UINT16                        HddCount;
 | |
|   UINT16                        BbsCount;
 | |
|   HDD_INFO                      *LocalHddInfo;
 | |
|   BBS_TABLE                     *LocalBbsTable;
 | |
|   UINT16                        DevType;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL      *LegacyBios;
 | |
|   UINTN                         Index;
 | |
|   UINT16                        Priority;
 | |
|   UINT16                        *DeviceType;
 | |
|   UINTN                         DeviceTypeCount;
 | |
|   UINTN                         DeviceTypeIndex;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION  *Option;
 | |
|   UINTN                         OptionCount;
 | |
| 
 | |
|   HddCount      = 0;
 | |
|   BbsCount      = 0;
 | |
|   LocalHddInfo  = NULL;
 | |
|   LocalBbsTable = NULL;
 | |
|   DevType       = BBS_UNKNOWN;
 | |
| 
 | |
|   Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = LegacyBios->GetBbsInfo (
 | |
|                          LegacyBios,
 | |
|                          &HddCount,
 | |
|                          &LocalHddInfo,
 | |
|                          &BbsCount,
 | |
|                          &LocalBbsTable
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
 | |
|   // We will set them according to the settings setup by user
 | |
|   //
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {
 | |
|       LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // boot priority always starts at 0
 | |
|   //
 | |
|   Priority = 0;  
 | |
|   if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) &&
 | |
|       (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {
 | |
|     //
 | |
|     // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first.
 | |
|     //
 | |
|     DevType  = LegacyBmDeviceType (BootOption->FilePath);
 | |
|     BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex;
 | |
|     Status = LegacyBmSetPriorityForSameTypeDev (
 | |
|                DevType,
 | |
|                BbsIndex,
 | |
|                LocalBbsTable,
 | |
|                &Priority
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // we have to set the boot priority for other BBS entries with different device types
 | |
|   //
 | |
|   Option          = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot);
 | |
|   DeviceType      = AllocatePool (sizeof (UINT16) * OptionCount);
 | |
|   ASSERT (DeviceType != NULL);
 | |
|   DeviceType[0]   = DevType;
 | |
|   DeviceTypeCount = 1;
 | |
|   for (Index = 0; Index < OptionCount; Index++) {
 | |
|     if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) ||
 | |
|         (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) {
 | |
|       continue;
 | |
|     }
 | |
|     
 | |
|     DevType = LegacyBmDeviceType (Option[Index].FilePath);
 | |
|     for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {
 | |
|       if (DeviceType[DeviceTypeIndex] == DevType) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (DeviceTypeIndex < DeviceTypeCount) {
 | |
|       //
 | |
|       // We don't want to process twice for a device type
 | |
|       //
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DeviceType[DeviceTypeCount] = DevType;
 | |
|     DeviceTypeCount++;
 | |
| 
 | |
|     Status = LegacyBmSetPriorityForSameTypeDev (
 | |
|                DevType,
 | |
|                (UINTN) -1,
 | |
|                LocalBbsTable,
 | |
|                &Priority
 | |
|                );
 | |
|   }
 | |
|   EfiBootManagerFreeLoadOptions (Option, OptionCount);
 | |
| 
 | |
|   DEBUG_CODE_BEGIN();
 | |
|     LegacyBmPrintBbsTable (LocalBbsTable, BbsCount);
 | |
|   DEBUG_CODE_END();
 | |
|   
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Boot the legacy system with the boot option.
 | |
| 
 | |
|   @param  BootOption The legacy boot option which have BBS device path
 | |
|                      On return, BootOption->Status contains the boot status.
 | |
|                      EFI_UNSUPPORTED    There is no legacybios protocol, do not support
 | |
|                                         legacy boot.
 | |
|                      EFI_STATUS         The status of LegacyBios->LegacyBoot ().
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| LegacyBmBoot (
 | |
|   IN  EFI_BOOT_MANAGER_LOAD_OPTION           *BootOption
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // If no LegacyBios protocol we do not support legacy boot
 | |
|     //
 | |
|     BootOption->Status = EFI_UNSUPPORTED;
 | |
|     return;
 | |
|   }
 | |
|   //
 | |
|   // Notes: if we separate the int 19, then we don't need to refresh BBS
 | |
|   //
 | |
|   Status = LegacyBmRefreshBbsTableForBoot (BootOption);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     BootOption->Status = Status;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   BootOption->Status = LegacyBios->LegacyBoot (
 | |
|                                      LegacyBios,
 | |
|                                      (BBS_BBS_DEVICE_PATH *) BootOption->FilePath,
 | |
|                                      BootOption->OptionalDataSize,
 | |
|                                      BootOption->OptionalData
 | |
|                                      );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function enumerates all the legacy boot options.
 | |
| 
 | |
|   @param BootOptionCount   Return the legacy boot option count.
 | |
| 
 | |
|   @retval    Pointer to the legacy boot option buffer.
 | |
| **/
 | |
| EFI_BOOT_MANAGER_LOAD_OPTION *
 | |
| LegacyBmEnumerateAllBootOptions (
 | |
|   UINTN                         *BootOptionCount
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINT16                        HddCount;
 | |
|   UINT16                        BbsCount;
 | |
|   HDD_INFO                      *HddInfo;
 | |
|   BBS_TABLE                     *BbsTable;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL      *LegacyBios;
 | |
|   UINT16                        Index;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
 | |
| 
 | |
|   ASSERT (BootOptionCount != NULL);
 | |
| 
 | |
|   BootOptions      = NULL;
 | |
|   *BootOptionCount = 0;
 | |
|   BbsCount         = 0;
 | |
| 
 | |
|   Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   Status = LegacyBios->GetBbsInfo (
 | |
|                          LegacyBios,
 | |
|                          &HddCount,
 | |
|                          &HddInfo,
 | |
|                          &BbsCount,
 | |
|                          &BbsTable
 | |
|                          );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < BbsCount; Index++) {
 | |
|     if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     BootOptions = ReallocatePool (
 | |
|                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
 | |
|                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
 | |
|                     BootOptions
 | |
|                     );
 | |
|     ASSERT (BootOptions != NULL);
 | |
| 
 | |
|     Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   return BootOptions;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the index of the boot option in the boot option array.
 | |
| 
 | |
|   The function compares the Description, FilePath, OptionalData.
 | |
| 
 | |
|   @param Key         The input boot option which is compared with.
 | |
|   @param Array       The input boot option array.
 | |
|   @param Count       The count of the input boot options.
 | |
| 
 | |
|   @retval  The index of the input boot option in the array.
 | |
| 
 | |
| **/
 | |
| INTN
 | |
| LegacyBmFindBootOption (
 | |
|   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
 | |
|   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
 | |
|   IN UINTN                              Count
 | |
|   )
 | |
| {
 | |
|   UINTN                             Index;
 | |
| 
 | |
|   for (Index = 0; Index < Count; Index++) {
 | |
|     if ((StrCmp (Key->Description, Array[Index].Description) == 0) &&
 | |
|         (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
 | |
|         (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
 | |
|         (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
 | |
|       return (INTN) Index;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Refresh all legacy boot options.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| LegacyBmRefreshAllBootOption (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                 Status;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL                   *LegacyBios;
 | |
|   UINTN                                      RootBridgeHandleCount;
 | |
|   EFI_HANDLE                                 *RootBridgeHandleBuffer;
 | |
|   UINTN                                      HandleCount;
 | |
|   EFI_HANDLE                                 *HandleBuffer;
 | |
|   UINTN                                      RootBridgeIndex;
 | |
|   UINTN                                      Index;
 | |
|   UINTN                                      Flags;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION               *BootOptions;
 | |
|   UINTN                                      BootOptionCount;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION               *ExistingBootOptions;
 | |
|   UINTN                                      ExistingBootOptionCount;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     LegacyBmDeleteAllBootOptions ();
 | |
|     return;
 | |
|   }
 | |
|   PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0);
 | |
| 
 | |
|   //
 | |
|   // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms 
 | |
|   // to ensure the GetBbsInfo() counts all the legacy devices.
 | |
|   //
 | |
|   gBS->LocateHandleBuffer (
 | |
|          ByProtocol,
 | |
|          &gEfiPciRootBridgeIoProtocolGuid,
 | |
|          NULL,
 | |
|          &RootBridgeHandleCount,
 | |
|          &RootBridgeHandleBuffer
 | |
|          );
 | |
|   for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
 | |
|     gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
 | |
|     gBS->LocateHandleBuffer (
 | |
|            ByProtocol,
 | |
|            &gEfiPciIoProtocolGuid,
 | |
|            NULL,
 | |
|            &HandleCount,
 | |
|            &HandleBuffer
 | |
|            );
 | |
|     for (Index = 0; Index < HandleCount; Index++) {
 | |
|       //
 | |
|       // Start the thunk driver so that the legacy option rom gets dispatched.
 | |
|       // Note: We don't directly call InstallPciRom because some thunk drivers 
 | |
|       // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching
 | |
|       //
 | |
|       Status = LegacyBios->CheckPciRom (
 | |
|                              LegacyBios,
 | |
|                              HandleBuffer[Index],
 | |
|                              NULL,
 | |
|                              NULL,
 | |
|                              &Flags
 | |
|                              );
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption
 | |
|   // Firstly delete the invalid legacy boot options,
 | |
|   // then enumreate and save the newly appeared legacy boot options
 | |
|   // the last step is legacy boot option special action to refresh the LegacyDevOrder variable
 | |
|   //
 | |
|   LegacyBmDeleteAllInvalidBootOptions ();
 | |
| 
 | |
|   ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot);
 | |
|   BootOptions         = LegacyBmEnumerateAllBootOptions   (&BootOptionCount);
 | |
| 
 | |
|   for (Index = 0; Index < BootOptionCount; Index++) {
 | |
|     if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) {
 | |
|       Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);
 | |
|       DEBUG ((
 | |
|         EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n",
 | |
|         (UINTN) BootOptions[Index].OptionNumber,
 | |
|         (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex,
 | |
|         BootOptions[Index].Description,
 | |
|         Status
 | |
|         ));
 | |
|       //
 | |
|       // Continue upon failure to add boot option.
 | |
|       //
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount);
 | |
|   EfiBootManagerFreeLoadOptions (BootOptions,         BootOptionCount);
 | |
| 
 | |
|   //
 | |
|   // Failure to create LegacyDevOrder variable only impacts the boot order.
 | |
|   //
 | |
|   LegacyBmUpdateDevOrder ();
 | |
| 
 | |
|   PERF_END   (NULL, "LegacyBootOptionEnum", "BDS", 0);
 | |
| }
 |