| /** @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; | |
| } | |