Example #1
0
File: Hotkey.c Project: etiago/vbox
/**
  Try to boot the boot option triggered by hotkey.
  @retval  EFI_SUCCESS             There is HotkeyBootOption & it is processed
  @retval  EFI_NOT_FOUND           There is no HotkeyBootOption
**/
EFI_STATUS
HotkeyBoot (
  VOID
  )
{ 
  EFI_STATUS           Status;
  UINTN                ExitDataSize;
  CHAR16               *ExitData;

  if (mHotkeyBootOption == NULL) {
    return EFI_NOT_FOUND;
  } 
  
  BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);

  //
  // Clear the screen before launch this BootOption
  //
  gST->ConOut->Reset (gST->ConOut, FALSE);

  Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);

  if (EFI_ERROR (Status)) {
    //
    // Call platform action to indicate the boot fail
    //
    mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
    PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);
  } else {
    //
    // Call platform action to indicate the boot success
    //
    mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
    PlatformBdsBootSuccess (mHotkeyBootOption);
  }
  FreePool (mHotkeyBootOption->Description);
  FreePool (mHotkeyBootOption->DevicePath);
  FreePool (mHotkeyBootOption->LoadOptions);
  FreePool (mHotkeyBootOption);

  mHotkeyBootOption = NULL;

  return EFI_SUCCESS;
}
Example #2
0
/**
  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;
    UINTN                       HelpSize;
    EFI_STRING_ID               HelpToken;
    UINT16                      *TempStr;
    EFI_HII_HANDLE              HiiHandle;
    EFI_BROWSER_ACTION_REQUEST  ActionRequest;
    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);

    EndOpCodeHandle = HiiAllocateOpCodeHandle ();
    ASSERT (EndOpCodeHandle != NULL);

    //
    // 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, ARRAY_SIZE (mDeviceTypeStr) - 1)
                             ],
                             NULL
                         );
            HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
            NeedEndOp = TRUE;
        }

        ASSERT (Option->Description != NULL);

        Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);

        TempStr = DevicePathToStr (Option->DevicePath);
        HelpSize = StrSize (TempStr) + StrSize (L"Device Path : ");
        HelpString = AllocateZeroPool (HelpSize);
        ASSERT (HelpString != NULL);
        StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : ");
        StrCatS (HelpString, HelpSize / sizeof (CHAR16), 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);
    }
}
Example #3
0
/**

  This function attempts to boot for the boot order specified
  by platform policy.

**/
VOID
BdsBootDeviceSelect (
  VOID
  )
{
  EFI_STATUS        Status;
  LIST_ENTRY        *Link;
  BDS_COMMON_OPTION *BootOption;
  UINTN             ExitDataSize;
  CHAR16            *ExitData;
  UINT16            Timeout;
  LIST_ENTRY        BootLists;
  CHAR16            Buffer[20];
  BOOLEAN           BootNextExist;
  LIST_ENTRY        *LinkBootNext;
  EFI_EVENT         ConnectConInEvent;

  //
  // Got the latest boot option
  //
  BootNextExist = FALSE;
  LinkBootNext  = NULL;
  ConnectConInEvent = NULL;
  InitializeListHead (&BootLists);

  //
  // First check the boot next option
  //
  ZeroMem (Buffer, sizeof (Buffer));

  //
  // Create Event to signal ConIn connection request
  //
  if (PcdGetBool (PcdConInConnectOnDemand)) {
    Status = gBS->CreateEventEx (
                    EVT_NOTIFY_SIGNAL,
                    TPL_CALLBACK,
                    BdsEmptyCallbackFunction,
                    NULL,
                    &gConnectConInEventGuid,
                    &ConnectConInEvent
                    );
    if (EFI_ERROR(Status)) {
      ConnectConInEvent = NULL;
    }
  }

  if (mBootNext != NULL) {
    //
    // Indicate we have the boot next variable, so this time
    // boot will always have this boot option
    //
    BootNextExist = TRUE;

    //
    // Clear the this variable so it's only exist in this time boot
    //
    Status = gRT->SetVariable (
                    L"BootNext",
                    &gEfiGlobalVariableGuid,
                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
                    0,
                    NULL
                    );
    //
    // Deleting variable with current variable implementation shouldn't fail.
    //
    ASSERT_EFI_ERROR (Status);

    //
    // Add the boot next boot option
    //
    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
    BootOption = BdsLibVariableToOption (&BootLists, Buffer);

    //
    // If fail to get boot option from variable, just return and do nothing.
    //
    if (BootOption == NULL) {
      return;
    }

    BootOption->BootCurrent = *mBootNext;
  }
  //
  // Parse the boot order to get boot option
  //
  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");

  //
  // When we didn't have chance to build boot option variables in the first 
  // full configuration boot (e.g.: Reset in the first page or in Device Manager),
  // we have no boot options in the following mini configuration boot.
  // Give the last chance to enumerate the boot options.
  //
  if (IsListEmpty (&BootLists)) {
    BdsLibEnumerateAllBootOption (&BootLists);
  }

  Link = BootLists.ForwardLink;

  //
  // Parameter check, make sure the loop will be valid
  //
  if (Link == NULL) {
    return ;
  }
  //
  // Here we make the boot in a loop, every boot success will
  // return to the front page
  //
  for (;;) {
    //
    // Check the boot option list first
    //
    if (Link == &BootLists) {
      //
      // When LazyConIn enabled, signal connect ConIn event before enter UI
      //
      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
        gBS->SignalEvent (ConnectConInEvent);
      }

      //
      // There are two ways to enter here:
      // 1. There is no active boot option, give user chance to
      //    add new boot option
      // 2. All the active boot option processed, and there is no
      //    one is success to boot, then we back here to allow user
      //    add new active boot option
      //
      Timeout = 0xffff;
      PlatformBdsEnterFrontPage (Timeout, FALSE);
      InitializeListHead (&BootLists);
      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
      Link = BootLists.ForwardLink;
      continue;
    }
    //
    // Get the boot option from the link list
    //
    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);

    //
    // According to EFI Specification, if a load option is not marked
    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
    // load the option.
    //
    if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
      //
      // skip the header of the link list, because it has no boot option
      //
      Link = Link->ForwardLink;
      continue;
    }
    //
    // Make sure the boot option device path connected,
    // but ignore the BBS device path
    //
    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
      //
      // Notes: the internal shell can not been connected with device path
      // so we do not check the status here
      //
      BdsLibConnectDevicePath (BootOption->DevicePath);
    }

    //
    // Restore to original mode before launching boot option.
    //
    BdsSetConsoleMode (FALSE);
    
    //
    // All the driver options should have been processed since
    // now boot will be performed.
    //
    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
    if (Status != EFI_SUCCESS) {
      //
      // Call platform action to indicate the boot fail
      //
      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
      PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);

      //
      // Check the next boot option
      //
      Link = Link->ForwardLink;

    } else {
      //
      // Call platform action to indicate the boot success
      //
      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
      PlatformBdsBootSuccess (BootOption);

      //
      // Boot success, then stop process the boot order, and
      // present the boot manager menu, front page
      //

      //
      // When LazyConIn enabled, signal connect ConIn Event before enter UI
      //
      if (PcdGetBool (PcdConInConnectOnDemand) && ConnectConInEvent != NULL) {
        gBS->SignalEvent (ConnectConInEvent);
      }

      Timeout = 0xffff;
      PlatformBdsEnterFrontPage (Timeout, FALSE);

      //
      // Rescan the boot option list, avoid potential risk of the boot
      // option change in front page
      //
      if (BootNextExist) {
        LinkBootNext = BootLists.ForwardLink;
      }

      InitializeListHead (&BootLists);
      if (LinkBootNext != NULL) {
        //
        // Reserve the boot next option
        //
        InsertTailList (&BootLists, LinkBootNext);
      }

      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
      Link = BootLists.ForwardLink;
    }
  }

}
Example #4
0
/**

  This is the common notification function for HotKeys, it will be registered
  with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.

  @param KeyData         A pointer to a buffer that is filled in with the keystroke
                         information for the key that was pressed.

  @retval  EFI_SUCCESS   KeyData is successfully processed.
  @return  EFI_NOT_FOUND Fail to find boot option variable.
**/
EFI_STATUS
EFIAPI
HotkeyCallback (
  IN EFI_KEY_DATA     *KeyData
)
{
  BOOLEAN            HotkeyCatched;
  LIST_ENTRY         BootLists;
  LIST_ENTRY         *Link;
  BDS_HOTKEY_OPTION  *Hotkey;
  UINT16             Buffer[10];
  BDS_COMMON_OPTION  *BootOption;
  UINTN              ExitDataSize;
  CHAR16             *ExitData;
  EFI_STATUS         Status;
  EFI_KEY_DATA       *HotkeyData;

  if (mHotkeyCallbackPending) {
    //
    // When responsing to a Hotkey, ignore sequential hotkey stroke until
    // the current Boot#### load option returned
    //
    return EFI_SUCCESS;
  }

  Status = EFI_SUCCESS;
  Link = GetFirstNode (&mHotkeyList);

  while (!IsNull (&mHotkeyList, Link)) {
    HotkeyCatched = FALSE;
    Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);

    //
    // Is this Key Stroke we are waiting for?
    //
    ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
    HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
    if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
       (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
       (((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) {
      //
      // Receive an expecting key stroke
      //
      if (Hotkey->CodeCount > 1) {
        //
        // For hotkey of key combination, transit to next waiting state
        //
        Hotkey->WaitingKey++;

        if (Hotkey->WaitingKey == Hotkey->CodeCount) {
          //
          // Received the whole key stroke sequence
          //
          HotkeyCatched = TRUE;
        }
      } else {
        //
        // For hotkey of single key stroke
        //
        HotkeyCatched = TRUE;
      }
    } else {
      //
      // Receive an unexpected key stroke, reset to initial waiting state
      //
      Hotkey->WaitingKey = 0;
    }

    if (HotkeyCatched) {
      //
      // Reset to initial waiting state
      //
      Hotkey->WaitingKey = 0;

      //
      // Launch its BootOption
      //
      InitializeListHead (&BootLists);

      UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
      BootOption = BdsLibVariableToOption (&BootLists, Buffer);
      if (BootOption == NULL) {
        return EFI_NOT_FOUND;
      }
      BootOption->BootCurrent = Hotkey->BootOptionNumber;
      BdsLibConnectDevicePath (BootOption->DevicePath);

      //
      // Clear the screen before launch this BootOption
      //
      gST->ConOut->Reset (gST->ConOut, FALSE);

      mHotkeyCallbackPending = TRUE;
      Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
      mHotkeyCallbackPending = FALSE;

      if (EFI_ERROR (Status)) {
        //
        // Call platform action to indicate the boot fail
        //
        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
        PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
      } else {
        //
        // Call platform action to indicate the boot success
        //
        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
        PlatformBdsBootSuccess (BootOption);
      }
    }

    Link = GetNextNode (&mHotkeyList, Link);
  }

  return Status;
}