예제 #1
0
/**

  Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.

  @retval  EFI_SUCCESS    Hotkey services successfully initialized.
  @retval  EFI_NOT_FOUND  Can not find the "KeyOrder" variable
**/
EFI_STATUS
InitializeHotkeyService (
  VOID
  )
{
  EFI_STATUS      Status;
  UINT32          BootOptionSupport;
  UINT16          *KeyOrder;
  UINTN           KeyOrderSize;
  UINTN           Index;
  UINT16          KeyOptionName[8];
  UINTN           KeyOptionSize;
  EFI_KEY_OPTION  *KeyOption;

  //
  // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
  // with maximum number of key presses of 3
  //
  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
  SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
  Status = gRT->SetVariable (
                  L"BootOptionSupport",
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                  sizeof (UINT32),
                  &BootOptionSupport
                  );

  //
  // Get valid Key Option List from private EFI variable "KeyOrder"
  //
  KeyOrder = BdsLibGetVariableAndSize (
               VAR_KEY_ORDER,
               &gEfiGlobalVariableGuid,
               &KeyOrderSize
               );

  if (KeyOrder == NULL) {
    return EFI_NOT_FOUND;
  }

  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
    KeyOption = BdsLibGetVariableAndSize (
                  KeyOptionName,
                  &gEfiGlobalVariableGuid,
                  &KeyOptionSize
                  );

    if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
      UnregisterHotkey (KeyOrder[Index]);
    } else {
      HotkeyInsertList (KeyOption);
    }
  }

  //
  // Register Protocol notify for Hotkey service
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_CALLBACK,
                  HotkeyEvent,
                  NULL,
                  &mHotkeyEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Register for protocol notifications on this event
  //
  Status = gBS->RegisterProtocolNotify (
                  &gEfiSimpleTextInputExProtocolGuid,
                  mHotkeyEvent,
                  &mHotkeyRegistration
                  );
  ASSERT_EFI_ERROR (Status);

  return Status;
}
예제 #2
0
/**
  Create Key#### for the given hotkey.

  @param KeyOption       The Hot Key Option to be added.
  @param KeyOptionNumber The key option number for Key#### (optional).

  @retval  EFI_SUCCESS            Register hotkey successfully.
  @retval  EFI_INVALID_PARAMETER  The hotkey option is invalid.
  @retval  EFI_OUT_OF_RESOURCES   Fail to allocate memory resource.

**/
EFI_STATUS
RegisterHotkey (
  IN EFI_KEY_OPTION     *KeyOption,
  OUT UINT16            *KeyOptionNumber
)
{
  UINT16          KeyOptionName[10];
  UINT16          *KeyOrder;
  UINTN           KeyOrderSize;
  UINT16          *NewKeyOrder;
  UINTN           Index;
  UINT16          MaxOptionNumber;
  UINT16          RegisterOptionNumber;
  EFI_KEY_OPTION  *TempOption;
  UINTN           TempOptionSize;
  EFI_STATUS      Status;
  UINTN           KeyOptionSize;
  BOOLEAN         UpdateBootOption;

  //
  // Validate the given key option
  //
  if (!IsKeyOptionValid (KeyOption)) {
    return EFI_INVALID_PARAMETER;
  }

  KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);
  UpdateBootOption = FALSE;

  //
  // Check whether HotKey conflict with keys used by Setup Browser
  //
  KeyOrder = BdsLibGetVariableAndSize (
               VAR_KEY_ORDER,
               &gEfiGlobalVariableGuid,
               &KeyOrderSize
               );
  if (KeyOrder == NULL) {
    KeyOrderSize = 0;
  }

  //
  // Find free key option number
  //
  MaxOptionNumber = 0;
  TempOption = NULL;
  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
    if (MaxOptionNumber < KeyOrder[Index]) {
      MaxOptionNumber = KeyOrder[Index];
    }

    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
    TempOption = BdsLibGetVariableAndSize (
                   KeyOptionName,
                   &gEfiGlobalVariableGuid,
                   &TempOptionSize
                   );

    if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {
      //
      // Got the option, so just return
      //
      FreePool (TempOption);
      FreePool (KeyOrder);
      return EFI_SUCCESS;
    }

    if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {
      if (KeyOption->KeyData.Options.InputKeyCount == 0 ||
          CompareMem (
            ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),
            ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),
            KeyOptionSize - sizeof (EFI_KEY_OPTION)
            ) == 0) {
          //
          // Hotkey is the same but BootOption changed, need update
          //
          UpdateBootOption = TRUE;
          break;
      }
    }

    FreePool (TempOption);
  }

  if (UpdateBootOption) {
    RegisterOptionNumber = KeyOrder[Index];
    FreePool (TempOption);
  } else {
    RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);
  }

  if (KeyOptionNumber != NULL) {
    *KeyOptionNumber = RegisterOptionNumber;
  }

  //
  // Create variable Key####
  //
  UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);
  Status = gRT->SetVariable (
                  KeyOptionName,
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
                  KeyOptionSize,
                  KeyOption
                  );
  if (EFI_ERROR (Status)) {
    FreePool (KeyOrder);
    return Status;
  }

  //
  // Update the key order variable - "KeyOrder"
  //
  if (!UpdateBootOption) {
    Index = KeyOrderSize / sizeof (UINT16);
    KeyOrderSize += sizeof (UINT16);
  }

  NewKeyOrder = AllocatePool (KeyOrderSize);
  if (NewKeyOrder == NULL) {
    FreePool (KeyOrder);
    return EFI_OUT_OF_RESOURCES;
  }

  if (KeyOrder != NULL) {
    CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);
  }

  NewKeyOrder[Index] = RegisterOptionNumber;

  Status = gRT->SetVariable (
                  VAR_KEY_ORDER,
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
                  KeyOrderSize,
                  NewKeyOrder
                  );

  FreePool (KeyOrder);
  FreePool (NewKeyOrder);

  return Status;
}
예제 #3
0
EFIAPI
EfiBootManagerGetKeyOptions (
  OUT UINTN     *Count
  )
{
  EFI_STATUS                  Status;
  UINTN                       Index;
  CHAR16                      *Name;
  EFI_GUID                    Guid;
  UINTN                       NameSize;
  UINTN                       NewNameSize;
  EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
  EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;
  UINT16                      OptionNumber;

  if (Count == NULL) {
    return NULL;
  }

  *Count     = 0;
  KeyOptions = NULL;

  NameSize = sizeof (CHAR16);
  Name     = AllocateZeroPool (NameSize);
  ASSERT (Name != NULL);
  while (TRUE) {
    NewNameSize = NameSize;
    Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
    if (Status == EFI_BUFFER_TOO_SMALL) {
      Name = ReallocatePool (NameSize, NewNameSize, Name);
      ASSERT (Name != NULL);
      Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
      NameSize = NewNameSize;
    }

    if (Status == EFI_NOT_FOUND) {
      break;
    }
    ASSERT_EFI_ERROR (Status);

    if (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {
      GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, NULL);
      ASSERT (KeyOption != NULL);
      if (IsKeyOptionValid (KeyOption)) {
        KeyOptions = ReallocatePool (
                       *Count * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
                       (*Count + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
                       KeyOptions
                       );
        ASSERT (KeyOptions != NULL);
        //
        // Insert the key option in order
        //
        for (Index = 0; Index < *Count; Index++) {
          if (OptionNumber < KeyOptions[Index].OptionNumber) {
            break;
          }
        }
        CopyMem (&KeyOptions[Index + 1], &KeyOptions[Index], (*Count - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
        CopyMem (&KeyOptions[Index], KeyOption, SizeOfKeyOption (KeyOption));
        KeyOptions[Index].OptionNumber = OptionNumber;
        (*Count)++;
      }
      FreePool (KeyOption);
    }
  }

  FreePool (Name);

  return KeyOptions;
}