The LegacyBootMaintUiLib depends on the LegacyBootManagerLib to realize its functionality, the LegacyBootManagerLib may initialize after LegacyBootMaintUiLib, so the functionality of LegacyBootMaintUiLib may be incorrect. Now we fix this issue by executing the related codes when opening the legacy forminstead in its the constructor function. Because when opening the legacy form, the LegacyBootManagerLib must have been initialized. Cc: Liming Gao <liming.gao@intel.com> Cc: Eric Dong <eric.dong@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			1509 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1509 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Legacy Boot Maintainence UI implementation.
 | |
| 
 | |
| Copyright (c) 2004 - 2016, 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 "LegacyBootMaintUi.h"
 | |
| 
 | |
| LEGACY_BOOT_OPTION_CALLBACK_DATA  *mLegacyBootOptionPrivate;
 | |
| EFI_GUID  mLegacyBootOptionGuid     = LEGACY_BOOT_OPTION_FORMSET_GUID;
 | |
| CHAR16    mLegacyBootStorageName[]  = L"LegacyBootData";
 | |
| BBS_TYPE  mBbsType[] = {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_NETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN};
 | |
| BOOLEAN   mFirstEnterLegacyForm = FALSE;
 | |
| 
 | |
| 
 | |
| ///
 | |
| /// Legacy FD Info from LegacyBios.GetBbsInfo()
 | |
| ///
 | |
| LEGACY_MENU_OPTION      LegacyFDMenu = {
 | |
|   LEGACY_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Legacy HD Info from LegacyBios.GetBbsInfo()
 | |
| ///
 | |
| LEGACY_MENU_OPTION      LegacyHDMenu = {
 | |
|   LEGACY_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Legacy CD Info from LegacyBios.GetBbsInfo()
 | |
| ///
 | |
| LEGACY_MENU_OPTION      LegacyCDMenu = {
 | |
|   LEGACY_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Legacy NET Info from LegacyBios.GetBbsInfo()
 | |
| ///
 | |
| LEGACY_MENU_OPTION      LegacyNETMenu = {
 | |
|   LEGACY_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Legacy NET Info from LegacyBios.GetBbsInfo()
 | |
| ///
 | |
| LEGACY_MENU_OPTION      LegacyBEVMenu = {
 | |
|   LEGACY_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| 
 | |
| VOID                *mLegacyStartOpCodeHandle = NULL;
 | |
| VOID                *mLegacyEndOpCodeHandle = NULL;
 | |
| EFI_IFR_GUID_LABEL  *mLegacyStartLabel = NULL;
 | |
| EFI_IFR_GUID_LABEL  *mLegacyEndLabel = NULL;
 | |
| 
 | |
| 
 | |
| HII_VENDOR_DEVICE_PATH  mLegacyBootOptionHiiVendorDevicePath = {
 | |
|   {
 | |
|     {
 | |
|       HARDWARE_DEVICE_PATH,
 | |
|       HW_VENDOR_DP,
 | |
|       {
 | |
|         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
 | |
|         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | |
|       }
 | |
|     }, 
 | |
|     { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } }
 | |
|   },
 | |
|   {
 | |
|     END_DEVICE_PATH_TYPE,
 | |
|     END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | |
|     { 
 | |
|       (UINT8) (END_DEVICE_PATH_LENGTH),
 | |
|       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetLegacyOptions (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Base on the L"LegacyDevOrder" variable to build the current order data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetLegacyOptionsOrder (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Re-order the Boot Option according to the DevOrder.
 | |
| 
 | |
|   The routine re-orders the Boot Option in BootOption array according to
 | |
|   the order specified by DevOrder.
 | |
| 
 | |
|   @param DevOrder           Pointer to buffer containing the BBS Index,
 | |
|                             high 8-bit value 0xFF indicating a disabled boot option
 | |
|   @param DevOrderCount      Count of the BBS Index
 | |
|   @param EnBootOption       Callee allocated buffer containing the enabled Boot Option Numbers
 | |
|   @param EnBootOptionCount  Count of the enabled Boot Option Numbers
 | |
|   @param DisBootOption      Callee allocated buffer containing the disabled Boot Option Numbers
 | |
|   @param DisBootOptionCount Count of the disabled Boot Option Numbers
 | |
| 
 | |
|   @return EFI_SUCCESS       The function completed successfully.
 | |
|   @retval other             Contain some error, details see  the status return by gRT->SetVariable.
 | |
| **/
 | |
| EFI_STATUS
 | |
| OrderLegacyBootOption4SameType (
 | |
|   UINT16                   *DevOrder,
 | |
|   UINTN                    DevOrderCount,
 | |
|   UINT16                   **EnBootOption,
 | |
|   UINTN                    *EnBootOptionCount,
 | |
|   UINT16                   **DisBootOption,
 | |
|   UINTN                    *DisBootOptionCount
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   UINT16                   *NewBootOption;
 | |
|   UINT16                   *BootOrder;
 | |
|   UINTN                    BootOrderSize;
 | |
|   UINTN                    Index;
 | |
|   UINTN                    StartPosition;
 | |
|   
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION    BootOption;
 | |
|   
 | |
|   CHAR16                           OptionName[sizeof ("Boot####")];
 | |
|   UINT16                   *BbsIndexArray;
 | |
|   UINT16                   *DeviceTypeArray;
 | |
| 
 | |
|   GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize);
 | |
|   ASSERT (BootOrder != NULL);
 | |
| 
 | |
|   BbsIndexArray       = AllocatePool (BootOrderSize);
 | |
|   DeviceTypeArray     = AllocatePool (BootOrderSize);
 | |
|   *EnBootOption       = AllocatePool (BootOrderSize);
 | |
|   *DisBootOption      = AllocatePool (BootOrderSize);
 | |
|   *DisBootOptionCount = 0;
 | |
|   *EnBootOptionCount  = 0;
 | |
|   Index               = 0;
 | |
|   Status              = EFI_SUCCESS;
 | |
| 
 | |
|   ASSERT (BbsIndexArray != NULL);
 | |
|   ASSERT (DeviceTypeArray != NULL);
 | |
|   ASSERT (*EnBootOption != NULL);
 | |
|   ASSERT (*DisBootOption != NULL);
 | |
| 
 | |
|   for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
 | |
|   
 | |
|     UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]);
 | |
|     Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     
 | |
|     if ((DevicePathType (BootOption.FilePath) == BBS_DEVICE_PATH) &&
 | |
|         (DevicePathSubType (BootOption.FilePath) == BBS_BBS_DP)) {
 | |
|       //
 | |
|       // Legacy Boot Option
 | |
|       //
 | |
|       ASSERT (BootOption.OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));
 | |
| 
 | |
|       DeviceTypeArray[Index] = ((BBS_BBS_DEVICE_PATH *) BootOption.FilePath)->DeviceType;
 | |
|       BbsIndexArray  [Index] = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption.OptionalData)->BbsIndex;
 | |
|     } else {
 | |
|       DeviceTypeArray[Index] = BBS_TYPE_UNKNOWN;
 | |
|       BbsIndexArray  [Index] = 0xFFFF;
 | |
|     }
 | |
|     EfiBootManagerFreeLoadOption (&BootOption);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Record the corresponding Boot Option Numbers according to the DevOrder
 | |
|   // Record the EnBootOption and DisBootOption according to the DevOrder
 | |
|   //
 | |
|   StartPosition = BootOrderSize / sizeof (UINT16);
 | |
|   NewBootOption = AllocatePool (DevOrderCount * sizeof (UINT16));
 | |
|   ASSERT (NewBootOption != NULL);
 | |
|   while (DevOrderCount-- != 0) {
 | |
|     for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
 | |
|       if (BbsIndexArray[Index] == (DevOrder[DevOrderCount] & 0xFF)) {
 | |
|         StartPosition = MIN (StartPosition, Index);
 | |
|         NewBootOption[DevOrderCount] = BootOrder[Index];
 | |
|         
 | |
|         if ((DevOrder[DevOrderCount] & 0xFF00) == 0xFF00) {
 | |
|           (*DisBootOption)[*DisBootOptionCount] = BootOrder[Index];
 | |
|           (*DisBootOptionCount)++;
 | |
|         } else {
 | |
|           (*EnBootOption)[*EnBootOptionCount] = BootOrder[Index];
 | |
|           (*EnBootOptionCount)++;
 | |
|         }
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Overwrite the old BootOption
 | |
|   //
 | |
|   CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount + *EnBootOptionCount) * sizeof (UINT16));
 | |
|   Status = gRT->SetVariable (
 | |
|                   L"BootOrder",
 | |
|                   &gEfiGlobalVariableGuid,
 | |
|                   VAR_FLAG,
 | |
|                   BootOrderSize,
 | |
|                   BootOrder
 | |
|                   );
 | |
| 
 | |
|   FreePool (NewBootOption);
 | |
|   FreePool (DeviceTypeArray);
 | |
|   FreePool (BbsIndexArray);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable
 | |
|   is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid
 | |
|   is also updated.
 | |
| 
 | |
|   @param NVMapData   The data for egacy BBS boot.
 | |
| 
 | |
|   @return EFI_SUCCESS           The function completed successfully.
 | |
|   @retval EFI_NOT_FOUND         If L"LegacyDevOrder" and gEfiLegacyDevOrderVariableGuid EFI Variable can not be found.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Fail to allocate memory resource
 | |
|   @retval other                 Contain some error, details see  the status return by gRT->SetVariable.
 | |
| **/
 | |
| EFI_STATUS
 | |
| UpdateBBSOption (
 | |
|   IN LEGACY_BOOT_NV_DATA            *NVMapData
 | |
|   )
 | |
| {
 | |
|   UINTN                       Index;
 | |
|   UINTN                       Index2;
 | |
|   UINTN                       CurrentType;
 | |
|   VOID                        *BootOptionVar;
 | |
|   CHAR16                      VarName[100];
 | |
|   UINTN                       OptionSize;
 | |
|   EFI_STATUS                  Status;
 | |
|   UINT32                      *Attribute;
 | |
|   LEGACY_MENU_OPTION          *OptionMenu;
 | |
|   UINT16                      *LegacyDev;
 | |
|   UINT16                      *InitialLegacyDev;
 | |
|   UINT8                       *VarData;
 | |
|   UINTN                       VarSize;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
 | |
|   UINT8                       *OriginalPtr;
 | |
|   UINT8                       *DisMap;
 | |
|   UINTN                       Pos;
 | |
|   UINTN                       Bit;
 | |
|   UINT16                      *NewOrder;
 | |
|   UINT16                      Tmp;
 | |
|   UINT16                      *EnBootOption;
 | |
|   UINTN                       EnBootOptionCount;
 | |
|   UINT16                      *DisBootOption;
 | |
|   UINTN                       DisBootOptionCount;
 | |
|   UINTN                       BufferSize;
 | |
|   
 | |
| 
 | |
|   DisMap              = NULL;
 | |
|   NewOrder            = NULL;
 | |
|   CurrentType         = 0;
 | |
|   EnBootOption        = NULL;
 | |
|   DisBootOption       = NULL;
 | |
| 
 | |
|   
 | |
|   DisMap  = mLegacyBootOptionPrivate->MaintainMapData->DisableMap;
 | |
|   Status  = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // Update the Variable "LegacyDevOrder"
 | |
|   //
 | |
|   GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize);
 | |
|   if (VarData == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   OriginalPtr = VarData;
 | |
| 
 | |
|   while (mBbsType[CurrentType] != BBS_UNKNOWN) {
 | |
|     switch (mBbsType[CurrentType]) {
 | |
|     case BBS_FLOPPY:
 | |
|       OptionMenu            = (LEGACY_MENU_OPTION *) &LegacyFDMenu;
 | |
|       LegacyDev             = NVMapData->LegacyFD;
 | |
|       InitialLegacyDev     = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD;
 | |
|       BufferSize            = sizeof (NVMapData->LegacyFD);
 | |
|       break;
 | |
| 
 | |
|     case BBS_HARDDISK:
 | |
|       OptionMenu            = (LEGACY_MENU_OPTION *) &LegacyHDMenu;
 | |
|       LegacyDev             = NVMapData->LegacyHD;
 | |
|       InitialLegacyDev     = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD;
 | |
| 
 | |
|       BufferSize            = sizeof (NVMapData->LegacyHD);
 | |
|       break;
 | |
| 
 | |
|     case BBS_CDROM:
 | |
|       OptionMenu            = (LEGACY_MENU_OPTION *) &LegacyCDMenu;
 | |
|       LegacyDev             = NVMapData->LegacyCD;
 | |
|       InitialLegacyDev     = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD;
 | |
|       BufferSize            = sizeof (NVMapData->LegacyCD);
 | |
|       break;
 | |
| 
 | |
|     case BBS_EMBED_NETWORK:
 | |
|       OptionMenu            = (LEGACY_MENU_OPTION *) &LegacyNETMenu;
 | |
|       LegacyDev             = NVMapData->LegacyNET;
 | |
|       InitialLegacyDev     = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET;
 | |
|       BufferSize            = sizeof (NVMapData->LegacyNET);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ASSERT (mBbsType[CurrentType] == BBS_BEV_DEVICE);
 | |
|       OptionMenu            = (LEGACY_MENU_OPTION *) &LegacyBEVMenu;
 | |
|       LegacyDev             = NVMapData->LegacyBEV;
 | |
|       InitialLegacyDev     = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV;
 | |
|       BufferSize            = sizeof (NVMapData->LegacyBEV);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check whether has value changed.
 | |
|     //
 | |
|     if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) == 0) {
 | |
|       CurrentType++;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     DevOrder    = (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr;
 | |
|     while (VarData < OriginalPtr + VarSize) {
 | |
|       if (DevOrder->BbsType == mBbsType[CurrentType]) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       VarData += sizeof (BBS_TYPE) + DevOrder->Length;
 | |
|       DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;
 | |
|     }
 | |
| 
 | |
|     if (VarData >= OriginalPtr + VarSize) {
 | |
|       FreePool (OriginalPtr);
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length));
 | |
|     if (NewOrder == NULL) {
 | |
|       FreePool (OriginalPtr);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
 | |
|       if (0xFF == LegacyDev[Index]) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       NewOrder[Index] = LegacyDev[Index];
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Only the enable/disable state of each boot device with same device type can be changed,
 | |
|     // so we can count on the index information in DevOrder.
 | |
|     // DisMap bit array is the only reliable source to check a device's en/dis state,
 | |
|     // so we use DisMap to set en/dis state of each item in NewOrder array
 | |
|     //
 | |
|     for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
 | |
|       Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF);
 | |
|       Pos = Tmp / 8;
 | |
|       Bit = 7 - (Tmp % 8);
 | |
|       if ((DisMap[Pos] & (1 << Bit)) != 0) {
 | |
|         NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
 | |
|         Index++;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     CopyMem (
 | |
|       DevOrder->Data,
 | |
|       NewOrder,
 | |
|       DevOrder->Length - sizeof (DevOrder->Length)
 | |
|       );
 | |
|     FreePool (NewOrder);
 | |
| 
 | |
|     //
 | |
|     // Update BootOrder and Boot####.Attribute
 | |
|     //
 | |
|     // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order
 | |
|     //
 | |
|     ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1);
 | |
| 
 | |
|     Status = OrderLegacyBootOption4SameType (
 | |
|       DevOrder->Data,
 | |
|       DevOrder->Length / sizeof (UINT16) - 1,
 | |
|       &EnBootOption,
 | |
|       &EnBootOptionCount,
 | |
|       &DisBootOption,
 | |
|       &DisBootOptionCount
 | |
|       );
 | |
|      if (EFI_ERROR(Status)) {
 | |
|        goto Fail;
 | |
|      }
 | |
| 
 | |
|     //
 | |
|     // 2. Deactivate the DisBootOption and activate the EnBootOption
 | |
|     //
 | |
|     for (Index = 0; Index < DisBootOptionCount; Index++) {
 | |
|       UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]);
 | |
|       GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize);
 | |
|       if (BootOptionVar != NULL) {
 | |
|         Attribute   = (UINT32 *) BootOptionVar;
 | |
|         *Attribute &= ~LOAD_OPTION_ACTIVE;
 | |
| 
 | |
|         Status = gRT->SetVariable (
 | |
|                         VarName,
 | |
|                         &gEfiGlobalVariableGuid,
 | |
|                         VAR_FLAG,
 | |
|                         OptionSize,
 | |
|                         BootOptionVar
 | |
|                         );
 | |
| 
 | |
|         FreePool (BootOptionVar);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     for (Index = 0; Index < EnBootOptionCount; Index++) {
 | |
|       UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]);
 | |
|       GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSize);
 | |
|       if (BootOptionVar != NULL) {
 | |
|         Attribute   = (UINT32 *) BootOptionVar;
 | |
|         *Attribute |= LOAD_OPTION_ACTIVE;
 | |
| 
 | |
|         Status = gRT->SetVariable (
 | |
|                         VarName,
 | |
|                         &gEfiGlobalVariableGuid,
 | |
|                         VAR_FLAG,
 | |
|                         OptionSize,
 | |
|                         BootOptionVar
 | |
|                         );
 | |
| 
 | |
|         FreePool (BootOptionVar);
 | |
|       }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     FreePool (EnBootOption);
 | |
|     FreePool (DisBootOption);
 | |
| 
 | |
|     CurrentType++;
 | |
|   }
 | |
|   
 | |
|   Status = gRT->SetVariable (
 | |
|                   VAR_LEGACY_DEV_ORDER,
 | |
|                   &gEfiLegacyDevOrderVariableGuid,
 | |
|                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                   VarSize,
 | |
|                   OriginalPtr
 | |
|                   );
 | |
| 
 | |
| Fail:
 | |
|   if (EnBootOption != NULL) {
 | |
|     FreePool (EnBootOption);
 | |
|   }
 | |
| 
 | |
|   if (DisBootOption != NULL) {
 | |
|     FreePool (DisBootOption);
 | |
|   }
 | |
| 
 | |
|   FreePool (OriginalPtr);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function allows a caller to extract the current configuration for one
 | |
|   or more named elements from the target driver.
 | |
| 
 | |
| 
 | |
|   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
 | |
|   @param Progress        On return, points to a character in the Request string.
 | |
|                          Points to the string's null terminator if request was successful.
 | |
|                          Points to the most recent '&' before the first failing name/value
 | |
|                          pair (or the beginning of the string if the failure is in the
 | |
|                          first name/value pair) if the request was not successful.
 | |
|   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
 | |
|                          has all values filled in for the names in the Request string.
 | |
|                          String to be allocated by the called function.
 | |
| 
 | |
|   @retval  EFI_SUCCESS            The Results is filled with the requested values.
 | |
|   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
 | |
|   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
 | |
|   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootOptionExtractConfig (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN  CONST EFI_STRING                       Request,
 | |
|   OUT EFI_STRING                             *Progress,
 | |
|   OUT EFI_STRING                             *Results
 | |
|   )
 | |
| {
 | |
|   if (Progress == NULL || Results == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   *Progress = Request;
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function processes the results of changes in configuration.
 | |
| 
 | |
| 
 | |
|   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
 | |
|   @param Progress        A pointer to a string filled in with the offset of the most
 | |
|                          recent '&' before the first failing name/value pair (or the
 | |
|                          beginning of the string if the failure is in the first
 | |
|                          name/value pair) or the terminating NULL if all was successful.
 | |
| 
 | |
|   @retval  EFI_SUCCESS            The Results is processed successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
 | |
|   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootOptionRouteConfig (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN  CONST EFI_STRING                       Configuration,
 | |
|   OUT       EFI_STRING                       *Progress
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
 | |
|   LEGACY_BOOT_NV_DATA             *CurrentNVMapData;
 | |
|   UINTN                           BufferSize;
 | |
| 
 | |
| 
 | |
|   if (Configuration == NULL || Progress == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check routing data in <ConfigHdr>.
 | |
|   // Note: there is no name for Name/Value storage, only GUID will be checked
 | |
|   //
 | |
|   if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacyBootStorageName)) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEfiHiiConfigRoutingProtocolGuid, 
 | |
|                   NULL, 
 | |
|                   (VOID **) &ConfigRouting
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
 | |
|   //
 | |
|   CurrentNVMapData = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData;
 | |
|   Status = ConfigRouting->ConfigToBlock (
 | |
|                             ConfigRouting,
 | |
|                             Configuration,
 | |
|                             (UINT8 *) CurrentNVMapData,
 | |
|                             &BufferSize,
 | |
|                             Progress
 | |
|                             );
 | |
|   ASSERT_EFI_ERROR (Status);    
 | |
| 
 | |
|   Status = UpdateBBSOption (CurrentNVMapData);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Refresh the global UpdateData structure.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| RefreshLegacyUpdateData (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Free current updated date
 | |
|   //
 | |
|   if (mLegacyStartOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle);
 | |
|   }
 | |
|   if (mLegacyEndOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create new OpCode Handle
 | |
|   //
 | |
|   mLegacyStartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   mLegacyEndOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the start opcode
 | |
|   //
 | |
|   mLegacyStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
 | |
|                                          mLegacyStartOpCodeHandle,
 | |
|                                          &gEfiIfrTianoGuid,
 | |
|                                          NULL,
 | |
|                                          sizeof (EFI_IFR_GUID_LABEL)
 | |
|                                          );
 | |
|   mLegacyStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
| 
 | |
|   mLegacyStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID;
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the start opcode
 | |
|   //
 | |
|   mLegacyEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
 | |
|                                          mLegacyEndOpCodeHandle,
 | |
|                                          &gEfiIfrTianoGuid,
 | |
|                                          NULL,
 | |
|                                          sizeof (EFI_IFR_GUID_LABEL)
 | |
|                                          );
 | |
|   mLegacyEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
| 
 | |
|   mLegacyEndLabel->Number = FORM_BOOT_LEGACY_LABEL_END;
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the Menu Entry from the list in Menu Entry List.
 | |
| 
 | |
|   If MenuNumber is great or equal to the number of Menu
 | |
|   Entry in the list, then ASSERT.
 | |
| 
 | |
|   @param MenuOption      The Menu Entry List to read the menu entry.
 | |
|   @param MenuNumber      The index of Menu Entry.
 | |
| 
 | |
|   @return The Menu Entry.
 | |
| 
 | |
| **/
 | |
| LEGACY_MENU_ENTRY *
 | |
| GetMenuEntry (
 | |
|   LEGACY_MENU_OPTION      *MenuOption,
 | |
|   UINTN                   MenuNumber
 | |
|   )
 | |
| {
 | |
|   LEGACY_MENU_ENTRY   *NewMenuEntry;
 | |
|   UINTN               Index;
 | |
|   LIST_ENTRY          *List;
 | |
| 
 | |
|   ASSERT (MenuNumber < MenuOption->MenuNumber);
 | |
| 
 | |
|   List = MenuOption->Head.ForwardLink;
 | |
|   for (Index = 0; Index < MenuNumber; Index++) {
 | |
|     List = List->ForwardLink;
 | |
|   }
 | |
| 
 | |
|   NewMenuEntry = CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SIGNATURE);
 | |
| 
 | |
|   return NewMenuEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create string tokens for a menu from its help strings and display strings
 | |
|   
 | |
|   @param HiiHandle          Hii Handle of the package to be updated.
 | |
|   @param MenuOption         The Menu whose string tokens need to be created
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| CreateLegacyMenuStringToken (
 | |
|   IN EFI_HII_HANDLE                   HiiHandle,
 | |
|   IN LEGACY_MENU_OPTION               *MenuOption
 | |
|   )
 | |
| {
 | |
|   LEGACY_MENU_ENTRY *NewMenuEntry;
 | |
|   UINTN             Index;
 | |
| 
 | |
|   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
 | |
|     NewMenuEntry = GetMenuEntry (MenuOption, Index);
 | |
| 
 | |
|     NewMenuEntry->DisplayStringToken = HiiSetString (
 | |
|                                          HiiHandle,
 | |
|                                          0,
 | |
|                                          NewMenuEntry->DisplayString,
 | |
|                                          NULL
 | |
|                                          );
 | |
| 
 | |
|     if (NULL == NewMenuEntry->HelpString) {
 | |
|       NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
 | |
|     } else {
 | |
|       NewMenuEntry->HelpStringToken = HiiSetString (
 | |
|                                         HiiHandle,
 | |
|                                         0,
 | |
|                                         NewMenuEntry->HelpString,
 | |
|                                         NULL
 | |
|                                         );
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a dynamic page so that Legacy Device boot order
 | |
|   can be set for specified device type.
 | |
| 
 | |
|   @param UpdatePageId    The form ID. It also spefies the legacy device type.
 | |
| 
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateLegacyDeviceOrderPage (
 | |
|   IN UINT16                           UpdatePageId
 | |
|   )
 | |
| {
 | |
|   LEGACY_MENU_OPTION          *OptionMenu;
 | |
|   LEGACY_MENU_ENTRY           *NewMenuEntry;
 | |
|   EFI_STRING_ID               StrRef;
 | |
|   EFI_STRING_ID               StrRefHelp;
 | |
|   UINT16                      *Default;
 | |
|   UINT16                      Index;
 | |
|   UINT16                      Key;
 | |
|   CHAR16                      String[100];
 | |
|   CHAR16                      *TypeStr;
 | |
|   CHAR16                      *TypeStrHelp;
 | |
|   CHAR16                      *FormTitle;
 | |
|   VOID                        *OptionsOpCodeHandle;
 | |
|   VOID                        *DefaultOpCodeHandle;
 | |
| 
 | |
|   Key         = 0;
 | |
|   StrRef      = 0;
 | |
|   StrRefHelp  = 0;
 | |
|   OptionMenu  = NULL;
 | |
|   TypeStr     = NULL;
 | |
|   TypeStrHelp = NULL;
 | |
|   Default     = NULL;
 | |
| 
 | |
|   RefreshLegacyUpdateData();
 | |
| 
 | |
|   //
 | |
|   // Create oneof option list
 | |
|   //
 | |
|   switch (UpdatePageId) {
 | |
|   case FORM_FLOPPY_BOOT_ID:
 | |
|     OptionMenu  = (LEGACY_MENU_OPTION *) &LegacyFDMenu;
 | |
|     Key         = (UINT16) LEGACY_FD_QUESTION_ID;
 | |
|     TypeStr     = STR_FLOPPY;
 | |
|     TypeStrHelp = STR_FLOPPY_HELP;
 | |
|     FormTitle   = STR_FLOPPY_TITLE;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyFD;
 | |
|     break;
 | |
| 
 | |
|   case FORM_HARDDISK_BOOT_ID:
 | |
|     OptionMenu  = (LEGACY_MENU_OPTION *) &LegacyHDMenu;
 | |
|     Key         = (UINT16) LEGACY_HD_QUESTION_ID;
 | |
|     TypeStr     = STR_HARDDISK;
 | |
|     TypeStrHelp = STR_HARDDISK_HELP;
 | |
|     FormTitle   = STR_HARDDISK_TITLE;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyHD;
 | |
|     break;
 | |
| 
 | |
|   case FORM_CDROM_BOOT_ID:
 | |
|     OptionMenu  = (LEGACY_MENU_OPTION *) &LegacyCDMenu;
 | |
|     Key         = (UINT16) LEGACY_CD_QUESTION_ID;
 | |
|     TypeStr     = STR_CDROM;
 | |
|     TypeStrHelp = STR_CDROM_HELP;
 | |
|     FormTitle   = STR_CDROM_TITLE;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyCD;
 | |
|     break;
 | |
| 
 | |
|   case FORM_NET_BOOT_ID:
 | |
|     OptionMenu  = (LEGACY_MENU_OPTION *) &LegacyNETMenu;
 | |
|     Key         = (UINT16) LEGACY_NET_QUESTION_ID;
 | |
|     TypeStr     = STR_NET;
 | |
|     TypeStrHelp = STR_NET_HELP;
 | |
|     FormTitle   = STR_NET_TITLE;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyNET;
 | |
|     break;
 | |
| 
 | |
|   case FORM_BEV_BOOT_ID:
 | |
|     OptionMenu  = (LEGACY_MENU_OPTION *) &LegacyBEVMenu;
 | |
|     Key         = (UINT16) LEGACY_BEV_QUESTION_ID;
 | |
|     TypeStr     = STR_BEV;
 | |
|     TypeStrHelp = STR_BEV_HELP;
 | |
|     FormTitle   = STR_BEV_TITLE;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData.LegacyBEV;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));
 | |
|     return;
 | |
|   }
 | |
|   
 | |
|   HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDER_CHANGE_PROMPT), FormTitle, NULL);
 | |
| 
 | |
|   CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, OptionMenu);
 | |
| 
 | |
|   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   ASSERT (OptionsOpCodeHandle != NULL);
 | |
| 
 | |
| 
 | |
|   for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
 | |
|     NewMenuEntry = GetMenuEntry (OptionMenu, Index);
 | |
|     //
 | |
|     // Create OneOf for each legacy device
 | |
|     //
 | |
|     HiiCreateOneOfOptionOpCode (
 | |
|       OptionsOpCodeHandle,
 | |
|       NewMenuEntry->DisplayStringToken,
 | |
|       0,
 | |
|       EFI_IFR_TYPE_NUM_SIZE_16,
 | |
|       ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create OneOf for item "Disabled"
 | |
|   //
 | |
|   HiiCreateOneOfOptionOpCode (
 | |
|     OptionsOpCodeHandle,
 | |
|     STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE),
 | |
|     0,
 | |
|     EFI_IFR_TYPE_NUM_SIZE_16,
 | |
|     0xFF
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Create oneof tag here for FD/HD/CD #1 #2
 | |
|   //
 | |
|   for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
 | |
|     DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|     ASSERT (DefaultOpCodeHandle != NULL);
 | |
| 
 | |
|     HiiCreateDefaultOpCode (
 | |
|       DefaultOpCodeHandle, 
 | |
|       EFI_HII_DEFAULT_CLASS_STANDARD, 
 | |
|       EFI_IFR_TYPE_NUM_SIZE_16, 
 | |
|       *Default++
 | |
|       );
 | |
|   
 | |
|     //
 | |
|     // Create the string for oneof tag
 | |
|     //
 | |
|     UnicodeSPrint (String, sizeof (String), TypeStr, Index);
 | |
|     StrRef = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);
 | |
| 
 | |
|     UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);
 | |
|     StrRefHelp = HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, String, NULL);
 | |
| 
 | |
|     HiiCreateOneOfOpCode (
 | |
|       mLegacyStartOpCodeHandle,
 | |
|       (EFI_QUESTION_ID) (Key + Index),
 | |
|       VARSTORE_ID_LEGACY_BOOT,
 | |
|       (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET),
 | |
|       StrRef,
 | |
|       StrRefHelp,
 | |
|       EFI_IFR_FLAG_CALLBACK,
 | |
|       EFI_IFR_NUMERIC_SIZE_2,
 | |
|       OptionsOpCodeHandle,
 | |
|       DefaultOpCodeHandle //NULL //
 | |
|       );
 | |
|       
 | |
|     HiiFreeOpCodeHandle (DefaultOpCodeHandle);
 | |
|   }
 | |
| 
 | |
|   HiiUpdateForm (
 | |
|     mLegacyBootOptionPrivate->HiiHandle,
 | |
|     &mLegacyBootOptionGuid,
 | |
|     LEGACY_ORDER_CHANGE_FORM_ID,
 | |
|     mLegacyStartOpCodeHandle, 
 | |
|     mLegacyEndOpCodeHandle   
 | |
|     );
 | |
| 
 | |
|   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Adjust question value when one question value has been changed.
 | |
| 
 | |
|   @param QuestionId    The question id for the value changed question.
 | |
|   @param Value         The value for the changed question.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| AdjustOptionValue (
 | |
|   IN  UINT16                                 QuestionId,
 | |
|   IN  EFI_IFR_TYPE_VALUE                     *Value
 | |
|   )
 | |
| {
 | |
|   UINTN                       Number;
 | |
|   UINT16                      *Default;
 | |
|   LEGACY_BOOT_NV_DATA         *CurrentNVMap;
 | |
|   UINT16                      *CurrentVal;
 | |
|   UINTN                       Index;
 | |
|   UINTN                       Index2;
 | |
|   UINTN                       Index3;
 | |
|   UINTN                       NewValuePos;
 | |
|   UINTN                       OldValue;
 | |
|   UINTN                       NewValue;
 | |
|   UINT8                       *DisMap;
 | |
|   UINTN                       Pos;
 | |
|   UINTN                       Bit;
 | |
| 
 | |
|   Number = 0;
 | |
|   CurrentVal = 0;
 | |
|   Default = NULL;
 | |
|   NewValue = 0;
 | |
|   NewValuePos = 0;
 | |
|   OldValue = 0;
 | |
| 
 | |
|   //
 | |
|   // Update Select FD/HD/CD/NET/BEV Order Form
 | |
|   //
 | |
|   ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER));
 | |
| 
 | |
|   CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData;
 | |
|   HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap);
 | |
|   DisMap  = mLegacyBootOptionPrivate->MaintainMapData->DisableMap;
 | |
| 
 | |
|   if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) {
 | |
|     Number      = (UINT16) LegacyFDMenu.MenuNumber;
 | |
|     CurrentVal  = CurrentNVMap->LegacyFD;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD;
 | |
|   } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) {
 | |
|     Number      = (UINT16) LegacyHDMenu.MenuNumber;
 | |
|     CurrentVal  = CurrentNVMap->LegacyHD;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD;
 | |
|   } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) {
 | |
|     Number      = (UINT16) LegacyCDMenu.MenuNumber;
 | |
|     CurrentVal  = CurrentNVMap->LegacyCD;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD;
 | |
|   } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) {
 | |
|     Number      = (UINT16) LegacyNETMenu.MenuNumber;
 | |
|     CurrentVal  = CurrentNVMap->LegacyNET;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET;
 | |
|   } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) {
 | |
|     Number      = (UINT16) LegacyBEVMenu.MenuNumber;
 | |
|     CurrentVal  = CurrentNVMap->LegacyBEV;
 | |
|     Default     = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   //  First, find the different position
 | |
|   //  if there is change, it should be only one
 | |
|   //
 | |
|   for (Index = 0; Index < Number; Index++) {
 | |
|     if (CurrentVal[Index] != Default[Index]) {
 | |
|       OldValue  = Default[Index];
 | |
|       NewValue  = CurrentVal[Index];
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Index != Number) {
 | |
|     //
 | |
|     // there is change, now process
 | |
|     //
 | |
|     if (0xFF == NewValue) {
 | |
|       //
 | |
|       // This item will be disable
 | |
|       // Just move the items behind this forward to overlap it
 | |
|       //
 | |
|       Pos = OldValue / 8;
 | |
|       Bit = 7 - (OldValue % 8);
 | |
|       DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
 | |
|       for (Index2 = Index; Index2 < Number - 1; Index2++) {
 | |
|         CurrentVal[Index2] = CurrentVal[Index2 + 1];
 | |
|       }
 | |
| 
 | |
|       CurrentVal[Index2] = 0xFF;
 | |
|     } else {
 | |
|       for (Index2 = 0; Index2 < Number; Index2++) {
 | |
|         if (Index2 == Index) {
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         if (Default[Index2] == NewValue) {
 | |
|           //
 | |
|           // If NewValue is in OldLegacyDev array
 | |
|           // remember its old position
 | |
|           //
 | |
|           NewValuePos = Index2;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (Index2 != Number) {
 | |
|         //
 | |
|         // We will change current item to an existing item
 | |
|         // (It's hard to describe here, please read code, it's like a cycle-moving)
 | |
|         //
 | |
|         for (Index2 = NewValuePos; Index2 != Index;) {
 | |
|           if (NewValuePos < Index) {
 | |
|             CurrentVal[Index2] = Default[Index2 + 1];
 | |
|             Index2++;
 | |
|           } else {
 | |
|             CurrentVal[Index2] = Default[Index2 - 1];
 | |
|             Index2--;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         //
 | |
|         // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
 | |
|         // so we should modify DisMap to reflect the change
 | |
|         //
 | |
|         Pos = NewValue / 8;
 | |
|         Bit = 7 - (NewValue % 8);
 | |
|         DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
 | |
|         if (0xFF != OldValue) {
 | |
|           //
 | |
|           // Because NewValue is a item that was disabled before
 | |
|           // so after changing the OldValue should be disabled
 | |
|           // actually we are doing a swap of enable-disable states of two items
 | |
|           //
 | |
|           Pos = OldValue / 8;
 | |
|           Bit = 7 - (OldValue % 8);
 | |
|           DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // To prevent DISABLE appears in the middle of the list
 | |
|     // we should perform a re-ordering
 | |
|     //
 | |
|     Index3 = Index;
 | |
|     Index = 0;
 | |
|     while (Index < Number) {
 | |
|       if (0xFF != CurrentVal[Index]) {
 | |
|         Index++;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       Index2 = Index;
 | |
|       Index2++;
 | |
|       while (Index2 < Number) {
 | |
|         if (0xFF != CurrentVal[Index2]) {
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Index2++;
 | |
|       }
 | |
| 
 | |
|       if (Index2 < Number) {
 | |
|         CurrentVal[Index]   = CurrentVal[Index2];
 | |
|         CurrentVal[Index2]  = 0xFF;
 | |
|       }
 | |
| 
 | |
|       Index++;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Return correct question value.
 | |
|     //
 | |
|     Value->u16 = CurrentVal[Index3];
 | |
|     CopyMem (Default, CurrentVal, sizeof (UINT16) * Number);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Pass changed uncommitted data back to Form Browser
 | |
|   //
 | |
|   HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This call back function is registered with Boot Manager formset.
 | |
|   When user selects a boot option, this call back function will
 | |
|   be triggered. The boot option is saved for later processing.
 | |
| 
 | |
| 
 | |
|   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param Action          Specifies the type of action taken by the browser.
 | |
|   @param QuestionId      A unique value which is sent to the original exporting driver
 | |
|                          so that it can identify the type of data to expect.
 | |
|   @param Type            The type of value for the question.
 | |
|   @param Value           A pointer to the data being sent to the original exporting driver.
 | |
|   @param ActionRequest   On return, points to the action requested by the callback function.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The callback successfully handled the action.
 | |
|   @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootOptionCallback (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN  EFI_BROWSER_ACTION                     Action,
 | |
|   IN  EFI_QUESTION_ID                        QuestionId,
 | |
|   IN  UINT8                                  Type,
 | |
|   IN  EFI_IFR_TYPE_VALUE                     *Value,
 | |
|   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
 | |
|   )
 | |
| {
 | |
|   if (Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_FORM_OPEN) {
 | |
|     //
 | |
|     // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open.
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if ((Value == NULL) || (ActionRequest == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
 | |
|     if (QuestionId == FORM_FLOPPY_BOOT_ID) {
 | |
|       if (!mFirstEnterLegacyForm) {
 | |
|         //
 | |
|         // The leagcyBootMaintUiLib depends on the LegacyBootManagerLib to realize its functionality.
 | |
|         // We need to do the leagcy boot options related actions after the LegacyBootManagerLib has been initialized.
 | |
|         // Opening the legacy menus is the appropriate time that the LegacyBootManagerLib has already been initialized.
 | |
|         //
 | |
|         mFirstEnterLegacyForm = TRUE;
 | |
|         GetLegacyOptions ();
 | |
|         GetLegacyOptionsOrder ();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | |
|     switch (QuestionId) {
 | |
|     case FORM_FLOPPY_BOOT_ID:
 | |
|     case FORM_HARDDISK_BOOT_ID:
 | |
|     case FORM_CDROM_BOOT_ID:
 | |
|     case FORM_NET_BOOT_ID:
 | |
|     case FORM_BEV_BOOT_ID:
 | |
|       UpdateLegacyDeviceOrderPage (QuestionId);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | |
|     if ((Value == NULL) || (ActionRequest == NULL)) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) {
 | |
|       AdjustOptionValue(QuestionId, Value);
 | |
|     }
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Create a menu entry by given menu type.
 | |
| 
 | |
|   @param MenuType        The Menu type to be created.
 | |
| 
 | |
|   @retval NULL           If failed to create the menu.
 | |
|   @return the new menu entry.
 | |
| 
 | |
| **/
 | |
| LEGACY_MENU_ENTRY *
 | |
| CreateMenuEntry (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   LEGACY_MENU_ENTRY *MenuEntry;
 | |
| 
 | |
|   //
 | |
|   // Create new menu entry
 | |
|   //
 | |
|   MenuEntry = AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY));
 | |
|   if (MenuEntry == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   MenuEntry->VariableContext = AllocateZeroPool (sizeof (LEGACY_DEVICE_CONTEXT));
 | |
|   if (MenuEntry->VariableContext == NULL) {
 | |
|     FreePool (MenuEntry);
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   MenuEntry->Signature        = LEGACY_MENU_ENTRY_SIGNATURE;
 | |
|   return MenuEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Base on the L"LegacyDevOrder" variable to build the current order data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetLegacyOptionsOrder (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN                       VarSize;
 | |
|   UINT8                       *VarData;
 | |
|   UINT8                       *VarTmp;
 | |
|   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
 | |
|   UINT16                      *LegacyDev;
 | |
|   UINTN                       Index;
 | |
|   LEGACY_MENU_OPTION          *OptionMenu;
 | |
|   UINT16                      VarDevOrder;
 | |
|   UINTN                       Pos;
 | |
|   UINTN                       Bit;
 | |
|   UINT8                       *DisMap;
 | |
|   UINTN                       TotalLength;
 | |
| 
 | |
|   LegacyDev = NULL;
 | |
|   OptionMenu = NULL;
 | |
| 
 | |
|   DisMap = ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMap, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap));
 | |
| 
 | |
|   //
 | |
|   // Get Device Order from variable
 | |
|   //
 | |
|   GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &VarData, &VarSize);
 | |
|   VarTmp = VarData;
 | |
|   if (NULL != VarData) {
 | |
|     DevOrder    = (LEGACY_DEV_ORDER_ENTRY *) VarData;
 | |
|     while (VarData < VarTmp + VarSize) {
 | |
|       switch (DevOrder->BbsType) {
 | |
|       case BBS_FLOPPY:
 | |
|         LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyFD;
 | |
|         OptionMenu = &LegacyFDMenu;
 | |
|         break;
 | |
|       
 | |
|       case BBS_HARDDISK:
 | |
|         LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyHD;
 | |
|         OptionMenu = &LegacyHDMenu;
 | |
|         break;
 | |
|       
 | |
|       case BBS_CDROM:
 | |
|         LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyCD;
 | |
|         OptionMenu = &LegacyCDMenu;
 | |
|         break;
 | |
|       
 | |
|       case BBS_EMBED_NETWORK:
 | |
|         LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyNET;
 | |
|         OptionMenu = &LegacyNETMenu;
 | |
|         break;
 | |
|       
 | |
|       case BBS_BEV_DEVICE:
 | |
|         LegacyDev = mLegacyBootOptionPrivate->MaintainMapData->InitialNvData.LegacyBEV;
 | |
|         OptionMenu = &LegacyBEVMenu;
 | |
|         break;
 | |
|       
 | |
|       case BBS_UNKNOWN:
 | |
|       default:
 | |
|         ASSERT (FALSE);
 | |
|         DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n"));
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Create oneof tag here for FD/HD/CD #1 #2
 | |
|       //
 | |
|       for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
 | |
|         TotalLength = sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16);
 | |
|         VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + TotalLength);
 | |
| 
 | |
|         if (0xFF00 == (VarDevOrder & 0xFF00)) {
 | |
|           LegacyDev[Index]  = 0xFF;
 | |
|           Pos               = (VarDevOrder & 0xFF) / 8;
 | |
|           Bit               = 7 - ((VarDevOrder & 0xFF) % 8);
 | |
|           DisMap[Pos]       = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
 | |
|         } else {
 | |
|           LegacyDev[Index] = VarDevOrder & 0xFF;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       VarData ++;
 | |
|       VarData += *(UINT16 *) VarData;
 | |
|       DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));
 | |
|   CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLegacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_NV_DATA));
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetLegacyOptions (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   LEGACY_MENU_ENTRY             *NewMenuEntry;
 | |
|   LEGACY_DEVICE_CONTEXT         *NewLegacyDevContext;
 | |
|   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;
 | |
|   UINTN                         BootOptionCount;
 | |
|   UINT16                        Index;
 | |
|   UINTN                         FDNum;
 | |
|   UINTN                         HDNum;
 | |
|   UINTN                         CDNum;
 | |
|   UINTN                         NETNum;
 | |
|   UINTN                         BEVNum;
 | |
| 
 | |
|   //
 | |
|   // Initialize Bbs Table Context from BBS info data
 | |
|   //
 | |
|   InitializeListHead (&LegacyFDMenu.Head);
 | |
|   InitializeListHead (&LegacyHDMenu.Head);
 | |
|   InitializeListHead (&LegacyCDMenu.Head);
 | |
|   InitializeListHead (&LegacyNETMenu.Head);
 | |
|   InitializeListHead (&LegacyBEVMenu.Head);
 | |
| 
 | |
|   FDNum   = 0;
 | |
|   HDNum   = 0;
 | |
|   CDNum   = 0;
 | |
|   NETNum  = 0;
 | |
|   BEVNum  = 0;
 | |
| 
 | |
|   EfiBootManagerConnectAll ();
 | |
|   
 | |
|   //
 | |
|   // for better user experience
 | |
|   // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option
 | |
|   // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option
 | |
|   //
 | |
|   EfiBootManagerRefreshAllBootOption ();
 | |
| 
 | |
|   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)
 | |
|        ) {
 | |
|       continue;
 | |
|     }
 | |
|     ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA));
 | |
|     NewMenuEntry = CreateMenuEntry ();
 | |
|     ASSERT (NewMenuEntry != NULL);
 | |
| 
 | |
|     NewLegacyDevContext              = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
 | |
|     NewLegacyDevContext->BbsIndex    = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex;
 | |
|     NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description);
 | |
|     ASSERT (NewLegacyDevContext->Description != NULL);
 | |
| 
 | |
|     NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
 | |
|     NewMenuEntry->HelpString    = NULL;
 | |
| 
 | |
|     switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) {
 | |
|     case BBS_TYPE_FLOPPY:
 | |
|       InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
 | |
|       FDNum++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_TYPE_HARDDRIVE:
 | |
|       InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
 | |
|       HDNum++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_TYPE_CDROM:
 | |
|       InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
 | |
|       CDNum++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_TYPE_EMBEDDED_NETWORK:
 | |
|       InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
 | |
|       NETNum++;
 | |
|       break;
 | |
| 
 | |
|     case BBS_TYPE_BEV:
 | |
|       InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
 | |
|       BEVNum++;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
 | |
| 
 | |
|   LegacyFDMenu.MenuNumber   = FDNum;
 | |
|   LegacyHDMenu.MenuNumber   = HDNum;
 | |
|   LegacyCDMenu.MenuNumber   = CDNum;
 | |
|   LegacyNETMenu.MenuNumber  = NETNum;
 | |
|   LegacyBEVMenu.MenuNumber  = BEVNum;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Install Boot Manager Menu driver.
 | |
| 
 | |
|   @param ImageHandle     The image handle.
 | |
|   @param SystemTable     The system table.
 | |
| 
 | |
|   @retval  EFI_SUCEESS  Install Boot manager menu success.
 | |
|   @retval  Other        Return error status.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootMaintUiLibConstructor (
 | |
|   IN EFI_HANDLE                            ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE                      *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_LEGACY_BIOS_PROTOCOL          *LegacyBios;
 | |
|   LEGACY_BOOT_OPTION_CALLBACK_DATA  *LegacyBootOptionData;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Create LegacyBootOptionData structures for Driver Callback
 | |
|     //
 | |
|     LegacyBootOptionData = AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_CALLBACK_DATA));
 | |
|     ASSERT (LegacyBootOptionData != NULL);
 | |
|     
 | |
|     LegacyBootOptionData->MaintainMapData = AllocateZeroPool (sizeof (LEGACY_BOOT_MAINTAIN_DATA));
 | |
|     ASSERT (LegacyBootOptionData->MaintainMapData != NULL);
 | |
| 
 | |
|     LegacyBootOptionData->ConfigAccess.ExtractConfig = LegacyBootOptionExtractConfig;
 | |
|     LegacyBootOptionData->ConfigAccess.RouteConfig   = LegacyBootOptionRouteConfig;
 | |
|     LegacyBootOptionData->ConfigAccess.Callback      = LegacyBootOptionCallback;
 | |
| 
 | |
|     //
 | |
|     // Install Device Path Protocol and Config Access protocol to driver handle
 | |
|     //
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &LegacyBootOptionData->DriverHandle,
 | |
|                     &gEfiDevicePathProtocolGuid,
 | |
|                     &mLegacyBootOptionHiiVendorDevicePath,
 | |
|                     &gEfiHiiConfigAccessProtocolGuid,
 | |
|                     &LegacyBootOptionData->ConfigAccess,
 | |
|                     NULL
 | |
|                     );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     //
 | |
|     // Publish our HII data
 | |
|     //
 | |
|     LegacyBootOptionData->HiiHandle = HiiAddPackages (
 | |
|                                       &mLegacyBootOptionGuid,
 | |
|                                       LegacyBootOptionData->DriverHandle,
 | |
|                                       LegacyBootMaintUiVfrBin,
 | |
|                                       LegacyBootMaintUiLibStrings,
 | |
|                                       NULL
 | |
|                                       );
 | |
|     ASSERT (LegacyBootOptionData->HiiHandle != NULL);
 | |
| 
 | |
|     mLegacyBootOptionPrivate = LegacyBootOptionData;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Destructor of Customized Display Library Instance.
 | |
| 
 | |
|   @param  ImageHandle   The firmware allocated handle for the EFI image.
 | |
|   @param  SystemTable   A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The destructor completed successfully.
 | |
|   @retval Other value   The destructor did not complete successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| LegacyBootMaintUiLibDestructor (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   if (mLegacyBootOptionPrivate->DriverHandle != NULL) {
 | |
|     Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                     mLegacyBootOptionPrivate->DriverHandle,
 | |
|                     &gEfiDevicePathProtocolGuid,
 | |
|                     &mLegacyBootOptionHiiVendorDevicePath,
 | |
|                     &gEfiHiiConfigAccessProtocolGuid,
 | |
|                     &mLegacyBootOptionPrivate->ConfigAccess,
 | |
|                     NULL
 | |
|                     );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     
 | |
|     HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle);
 | |
| 
 | |
|     FreePool (mLegacyBootOptionPrivate->MaintainMapData);
 | |
|     FreePool (mLegacyBootOptionPrivate);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 |