/edk2/Clover/OsxBdsDxe/BootMngr/BootManager.c
C | 412 lines | 256 code | 51 blank | 105 comment | 37 complexity | ee549d8310433b6ed2361108d31c6f80 MD5 | raw file
- /** @file
- The platform boot manager reference implementation
-
- Copyright (c) 2004 - 2012, 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 "BootManager.h"
-
- UINT16 mKeyInput;
- LIST_ENTRY mBootOptionsList;
- BDS_COMMON_OPTION *gOption;
- CHAR16 *mDeviceTypeStr[] = {
- L"Legacy BEV",
- L"Legacy Floppy",
- L"Legacy Hard Drive",
- L"Legacy CD ROM",
- L"Legacy PCMCIA",
- L"Legacy USB",
- L"Legacy Embedded Network",
- L"Legacy Unknown Device"
- };
-
-
- HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {
- {
- {
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP,
- {
- (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
- (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
- }
- },
- BOOT_MANAGER_FORMSET_GUID
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- (UINT8) (END_DEVICE_PATH_LENGTH),
- (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
- }
- }
- };
-
- BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
- BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
- NULL,
- NULL,
- {
- FakeExtractConfig,
- FakeRouteConfig,
- BootManagerCallback
- }
- };
-
- /**
- 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
- BootManagerCallback (
- 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
- )
- {
- BDS_COMMON_OPTION *Option;
- LIST_ENTRY *Link;
- UINT16 KeyCount;
-
- if (Action == EFI_BROWSER_ACTION_CHANGED) {
- if ((Value == NULL) || (ActionRequest == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Initialize the key count
- //
- KeyCount = 0;
-
- for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
- Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
-
- KeyCount++;
-
- gOption = Option;
-
- //
- // Is this device the one chosen?
- //
- if (KeyCount == QuestionId) {
- //
- // Assigning the returned Key to a global allows the original routine to know what was chosen
- //
- mKeyInput = QuestionId;
-
- //
- // Request to exit SendForm(), so that we could boot the selected option
- //
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
- break;
- }
- }
-
- return EFI_SUCCESS;
- }
-
- //
- // All other action return unsupported.
- //
- return EFI_UNSUPPORTED;
- }
-
- /**
-
- Registers HII packages for the Boot Manger to HII Database.
- It also registers the browser call back function.
-
- @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.
- @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.
-
- **/
- EFI_STATUS
- InitializeBootManager (
- VOID
- )
- {
- EFI_STATUS Status;
-
- //
- // Install Device Path Protocol and Config Access protocol to driver handle
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &gBootManagerPrivate.DriverHandle,
- &gEfiDevicePathProtocolGuid,
- &mBootManagerHiiVendorDevicePath,
- &gEfiHiiConfigAccessProtocolGuid,
- &gBootManagerPrivate.ConfigAccess,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Publish our HII data
- //
- gBootManagerPrivate.HiiHandle = HiiAddPackages (
- &gBootManagerFormSetGuid,
- gBootManagerPrivate.DriverHandle,
- BootManagerVfrBin,
- BdsDxeStrings,
- NULL
- );
- if (gBootManagerPrivate.HiiHandle == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- Status = EFI_SUCCESS;
- }
- return Status;
- }
-
- /**
- This function invokes Boot Manager. If all devices have not a chance to be connected,
- the connect all will be triggered. It then enumerate all boot options. If
- a boot option from the Boot Manager page is selected, Boot Manager will boot
- from this boot option.
-
- **/
- VOID
- CallBootManager (
- VOID
- )
- {
- EFI_STATUS Status;
- BDS_COMMON_OPTION *Option;
- LIST_ENTRY *Link;
- CHAR16 *ExitData;
- UINTN ExitDataSize;
- EFI_STRING_ID Token;
- EFI_INPUT_KEY Key;
- CHAR16 *HelpString;
- EFI_STRING_ID HelpToken;
- UINT16 *TempStr;
- EFI_HII_HANDLE HiiHandle;
- EFI_BROWSER_ACTION_REQUEST ActionRequest;
- UINTN TempSize;
- VOID *StartOpCodeHandle;
- VOID *EndOpCodeHandle;
- EFI_IFR_GUID_LABEL *StartLabel;
- EFI_IFR_GUID_LABEL *EndLabel;
- UINT16 DeviceType;
- BOOLEAN IsLegacyOption;
- BOOLEAN NeedEndOp;
-
- DeviceType = (UINT16) -1;
- gOption = NULL;
- InitializeListHead (&mBootOptionsList);
-
- //
- // Connect all prior to entering the platform setup menu.
- //
- if (!gConnectAllHappened) {
- BdsLibConnectAllDriversToAllControllers ();
- gConnectAllHappened = TRUE;
- }
-
- BdsLibEnumerateAllBootOption (&mBootOptionsList);
-
- //
- // Group the legacy boot options for the same device type
- //
- GroupMultipleLegacyBootOption4SameType ();
-
- InitializeListHead (&mBootOptionsList);
- BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder");
-
- HiiHandle = gBootManagerPrivate.HiiHandle;
-
- //
- // Allocate space for creation of UpdateData Buffer
- //
- StartOpCodeHandle = HiiAllocateOpCodeHandle ();
- // ASSERT (StartOpCodeHandle != NULL);
- if (!StartOpCodeHandle) {
- return;
- }
-
- EndOpCodeHandle = HiiAllocateOpCodeHandle ();
- // ASSERT (EndOpCodeHandle != NULL);
- if (!EndOpCodeHandle) {
- return;
- }
-
- //
- // Create Hii Extend Label OpCode as the start opcode
- //
- StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
- StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
- StartLabel->Number = LABEL_BOOT_OPTION;
-
- //
- // Create Hii Extend Label OpCode as the end opcode
- //
- EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
- EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
- EndLabel->Number = LABEL_BOOT_OPTION_END;
-
- mKeyInput = 0;
- NeedEndOp = FALSE;
- for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
- Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
-
- //
- // At this stage we are creating a menu entry, thus the Keys are reproduceable
- //
- mKeyInput++;
-
- //
- // Don't display the hidden/inactive boot option
- //
- if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) {
- continue;
- }
-
- //
- // Group the legacy boot option in the sub title created dynamically
- //
- IsLegacyOption = (BOOLEAN) (
- (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
- (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
- );
-
- if (!IsLegacyOption && NeedEndOp) {
- NeedEndOp = FALSE;
- HiiCreateEndOpCode (StartOpCodeHandle);
- }
-
- if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) {
- if (NeedEndOp) {
- HiiCreateEndOpCode (StartOpCodeHandle);
- }
-
- DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType;
- Token = HiiSetString (
- HiiHandle,
- 0,
- mDeviceTypeStr[
- MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1)
- ],
- NULL
- );
- HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
- NeedEndOp = TRUE;
- }
-
- // ASSERT (Option->Description != NULL);
- if (!Option->Description) {
- return;
- }
-
- Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);
-
- TempStr = FileDevicePathToStr (Option->DevicePath);
- TempSize = StrSize (TempStr);
- HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
- // ASSERT (HelpString != NULL);
- if (!HelpString) {
- return;
- }
-
- StrCat (HelpString, L"Device Path : ");
- StrCat (HelpString, TempStr);
-
- HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
-
- HiiCreateActionOpCode (
- StartOpCodeHandle,
- mKeyInput,
- Token,
- HelpToken,
- EFI_IFR_FLAG_CALLBACK,
- 0
- );
- }
-
- if (NeedEndOp) {
- HiiCreateEndOpCode (StartOpCodeHandle);
- }
-
- HiiUpdateForm (
- HiiHandle,
- &gBootManagerFormSetGuid,
- BOOT_MANAGER_FORM_ID,
- StartOpCodeHandle,
- EndOpCodeHandle
- );
-
- HiiFreeOpCodeHandle (StartOpCodeHandle);
- HiiFreeOpCodeHandle (EndOpCodeHandle);
-
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
- Status = gFormBrowser2->SendForm (
- gFormBrowser2,
- &HiiHandle,
- 1,
- &gBootManagerFormSetGuid,
- 0,
- NULL,
- &ActionRequest
- );
- if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
- EnableResetRequired ();
- }
-
- if (gOption == NULL) {
- return ;
- }
-
- //
- // Will leave browser, check any reset required change is applied? if yes, reset system
- //
- SetupResetReminder ();
-
- //
- // Restore to original mode before launching boot option.
- //
- BdsSetConsoleMode (FALSE);
-
- //
- // parse the selected option
- //
- Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
-
- if (!EFI_ERROR (Status)) {
- gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
- PlatformBdsBootSuccess (gOption);
- } else {
- gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
- PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
- gST->ConOut->OutputString (
- gST->ConOut,
- GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
- );
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- }
- }