According to UEFI spec, the RouteConfig protocol function should populate the Progress pointer with an address inside Configuration. This patch ensures that these functions are compliant when EFI_NOT_FOUND is returned. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Thomas Palmer <thomas.palmer@hpe.com> Reviewed-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com>
		
			
				
	
	
		
			1512 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1512 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Legacy Boot Maintainence UI implementation.
 | |
| 
 | |
| Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
| (C) Copyright 2018 Hewlett Packard Enterprise Development LP<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 = NULL;
 | |
| 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;
 | |
|   }
 | |
| 
 | |
|   *Progress = Configuration;
 | |
| 
 | |
|   //
 | |
|   // 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 != NULL && 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;
 | |
| }
 | |
| 
 |