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