--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. 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
+Module Name: \r
+\r
+ BootManager.c\r
+\r
+Abstract:\r
+\r
+ The platform boot manager reference implement\r
+\r
+--*/\r
+#include "BootManager.h"\r
+\r
+UINT16 mKeyInput;\r
+LIST_ENTRY *mBootOptionsList;\r
+BDS_COMMON_OPTION *gOption;\r
+EFI_HII_HANDLE gBootManagerHandle;\r
+EFI_HANDLE BootManagerCallbackHandle;\r
+EFI_FORM_CALLBACK_PROTOCOL BootManagerCallback;\r
+EFI_GUID gBmGuid = BOOT_MANAGER_GUID;\r
+\r
+extern EFI_FORM_BROWSER_PROTOCOL *gBrowser;\r
+extern UINT8 BootManagerVfrBin[];\r
+extern UINT8 BdsStrings[];\r
+extern BOOLEAN gConnectAllHappened;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallbackRoutine (\r
+ IN EFI_FORM_CALLBACK_PROTOCOL *This,\r
+ IN UINT16 KeyValue,\r
+ IN EFI_IFR_DATA_ARRAY *DataArray,\r
+ OUT EFI_HII_CALLBACK_PACKET **Packet\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This is the function that is called to provide results data to the driver. This data\r
+ consists of a unique key which is used to identify what data is either being passed back\r
+ or being asked for. \r
+\r
+Arguments:\r
+\r
+ KeyValue - A unique value which is sent to the original exporting driver so that it\r
+ can identify the type of data to expect. The format of the data tends to\r
+ vary based on the op-code that geerated the callback.\r
+\r
+ Data - A pointer to the data being sent to the original exporting driver.\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ UINT16 KeyCount;\r
+ EFI_HII_CALLBACK_PACKET *DataPacket;\r
+\r
+ //\r
+ // Initialize the key count\r
+ //\r
+ KeyCount = 0;\r
+\r
+ for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ KeyCount++;\r
+\r
+ gOption = Option;\r
+\r
+ //\r
+ // Is this device the one chosen?\r
+ //\r
+ if (KeyCount == KeyValue) {\r
+ //\r
+ // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+ //\r
+ mKeyInput = KeyValue;\r
+\r
+ *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);\r
+ ASSERT (*Packet != NULL);\r
+\r
+ //\r
+ // Assign the buffer address to DataPacket\r
+ //\r
+ DataPacket = *Packet;\r
+\r
+ DataPacket->DataArray.EntryCount = 1;\r
+ DataPacket->DataArray.NvRamMap = NULL;\r
+ ((EFI_IFR_DATA_ENTRY *) (((EFI_IFR_DATA_ARRAY *)DataPacket) + 1))->Flags = EXIT_REQUIRED | NV_NOT_CHANGED;\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CallBootManager (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Hook to enable UI timeout override behavior.\r
+\r
+Arguments:\r
+ BdsDeviceList - Device List that BDS needs to connect.\r
+\r
+ Entry - Pointer to current Boot Entry.\r
+\r
+Returns:\r
+ NONE\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGES *PackageList;\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ EFI_HII_UPDATE_DATA *UpdateData;\r
+ CHAR16 *ExitData;\r
+ UINTN ExitDataSize;\r
+ STRING_REF Token;\r
+ STRING_REF LastToken;\r
+ EFI_INPUT_KEY Key;\r
+ UINT8 *Location;\r
+ EFI_GUID BmGuid;\r
+ LIST_ENTRY BdsBootOptionList;\r
+ BOOLEAN BootMngrMenuResetRequired;\r
+\r
+ gOption = NULL;\r
+ InitializeListHead (&BdsBootOptionList);\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+ //\r
+ // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+ // get the boot order every time from "BootOrder" variable.\r
+ // Recreate the boot option list base on the BootOrder variable\r
+ //\r
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+ //\r
+ // This GUID must be the same as what is defined in BootManagerVfr.vfr\r
+ //\r
+ BmGuid = gBmGuid;\r
+\r
+ mBootOptionsList = &BdsBootOptionList;\r
+\r
+ //\r
+ // Post our VFR to the HII database\r
+ //\r
+ PackageList = PreparePackages (2, &BmGuid, BootManagerVfrBin, BdsStrings);\r
+ Status = Hii->NewPack (Hii, PackageList, &gBootManagerHandle);\r
+ gBS->FreePool (PackageList);\r
+\r
+ //\r
+ // This example does not implement worker functions\r
+ // for the NV accessor functions. Only a callback evaluator\r
+ //\r
+ BootManagerCallback.NvRead = NULL;\r
+ BootManagerCallback.NvWrite = NULL;\r
+ BootManagerCallback.Callback = BootManagerCallbackRoutine;\r
+\r
+ //\r
+ // Install protocol interface\r
+ //\r
+ BootManagerCallbackHandle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &BootManagerCallbackHandle,\r
+ &gEfiFormCallbackProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &BootManagerCallback\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ LastToken = 0;\r
+ Hii->NewString (Hii, NULL, gBootManagerHandle, &LastToken, L" ");\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData = AllocateZeroPool (0x1000);\r
+ ASSERT (UpdateData != NULL);\r
+\r
+ //\r
+ // Flag update pending in FormSet\r
+ //\r
+ UpdateData->FormSetUpdate = TRUE;\r
+ //\r
+ // Register CallbackHandle data for FormSet\r
+ //\r
+ UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) BootManagerCallbackHandle;\r
+ UpdateData->FormUpdate = FALSE;\r
+ UpdateData->FormTitle = 0;\r
+ UpdateData->DataCount = 1;\r
+\r
+ //\r
+ // Create blank space. Since when we update the contents of IFR data at a label, it is\r
+ // inserted at the location of the label. So if you want to add a string with an empty\r
+ // space afterwards, you need to add the space first and then the string like below.\r
+ //\r
+ Status = CreateSubTitleOpCode (\r
+ LastToken, // Token Value for the string\r
+ &UpdateData->Data // Buffer containing created op-code\r
+ );\r
+\r
+ Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
+\r
+ //\r
+ // Create "Boot Option Menu" title\r
+ //\r
+ Status = CreateSubTitleOpCode (\r
+ STRING_TOKEN (STR_BOOT_OPTION_BANNER), // Token Value for the string\r
+ &UpdateData->Data // Buffer containing created op-code\r
+ );\r
+\r
+ Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
+\r
+ Token = LastToken;\r
+ mKeyInput = 0;\r
+\r
+ UpdateData->DataCount = 0;\r
+ Location = (UINT8 *) &UpdateData->Data;\r
+\r
+ for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ //\r
+ // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+ //\r
+ mKeyInput++;\r
+ Token++;\r
+\r
+ Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);\r
+\r
+ //\r
+ // If we got an error it is almost certainly due to the token value being invalid.\r
+ // Therefore we will set the Token to 0 to automatically add a token.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Token = 0;\r
+ Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);\r
+ }\r
+\r
+ Status = CreateGotoOpCode (\r
+ 0x1000, // Form ID\r
+ Token, // Token Value for the string\r
+ 0, // Help String (none)\r
+ EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // The Op-Code flags\r
+ mKeyInput, // The Key to get a callback on\r
+ Location // Buffer containing created op-code\r
+ );\r
+\r
+ UpdateData->DataCount++;\r
+ Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+ }\r
+\r
+ Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0001, TRUE, UpdateData);\r
+\r
+ UpdateData->DataCount = 1;\r
+\r
+ //\r
+ // Create "Boot Option Menu" title\r
+ //\r
+ Status = CreateSubTitleOpCode (\r
+ STRING_TOKEN (STR_HELP_FOOTER), // Token Value for the string\r
+ &UpdateData->Data // Buffer containing created op-code\r
+ );\r
+\r
+ Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);\r
+\r
+ Status = CreateSubTitleOpCode (\r
+ LastToken, // Token Value for the string\r
+ &UpdateData->Data // Buffer containing created op-code\r
+ );\r
+\r
+ Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);\r
+\r
+ gBS->FreePool (UpdateData);\r
+\r
+ ASSERT (gBrowser);\r
+\r
+ BootMngrMenuResetRequired = FALSE;\r
+ gBrowser->SendForm (\r
+ gBrowser, \r
+ TRUE, \r
+ &gBootManagerHandle, \r
+ 1, \r
+ NULL, \r
+ NULL, \r
+ NULL, \r
+ NULL, \r
+ &BootMngrMenuResetRequired\r
+ );\r
+\r
+ if (BootMngrMenuResetRequired) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ Hii->ResetStrings (Hii, gBootManagerHandle);\r
+\r
+ if (gOption == NULL) {\r
+ return ;\r
+ }\r
+ \r
+ //\r
+ //Will leave browser, check any reset required change is applied? if yes, reset system\r
+ //\r
+ SetupResetReminder ();\r
+ \r
+ //\r
+ // BugBug: This code looks repeated from the BDS. Need to save code space.\r
+ //\r
+\r
+ //\r
+ // parse the selected option\r
+ //\r
+ Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ PlatformBdsBootSuccess (gOption);\r
+ } else {\r
+ PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+ gST->ConOut->OutputString (\r
+ gST->ConOut,\r
+ GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+ );\r
+\r
+ //\r
+ // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);\r
+ //\r
+\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ }\r
+}\r