UEFI 스펙 또는 EDKII 파일(MdePkg/Include/Guid/GlobalVariable.h)를 읽고 이러한 옵션에 대한 도움말을 찾을 수 있다.
// L"Key####" - Describes hot key relationship with a Boot#### load option
OVMF는 BdsPlatform.c 파일에서 위 옵션을 설정한다.
$ cat MdePkg/Include/Guid/GlobalVariable.h---VOIDPlatformRegisterOptionsAndKeys ( VOID ){ ...//// Map F2 to Boot Manager Menu//F2.ScanCode = SCAN_F2;F2.UnicodeChar = CHAR_NULL;Esc.ScanCode = SCAN_ESC;Esc.UnicodeChar = CHAR_NULL; Status =EfiBootManagerGetBootManagerMenu (&BootOption);ASSERT_EFI_ERROR (Status); Status =EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber,0,&F2,NULL );ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); Status =EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber,0,&Esc,NULL ); ...}
EfiBootManagerAddKeyOptionVariable 코드는 부트 관리자 메뉴 항목에 대한 단축키로 F2 및 ESC 키 입력을 설정한다. 그리고 필요한 모든 정보와 함께 NVRAM 변수 KeyXXXX를 추가한다,
$ cat MdeModulePkg/Library/UefiBootManagerLib/BmHotKey.c
/**
Add the key option.
It adds the key option variable and the key option takes affect immediately.
@param AddedOption Return the added key option.
@param BootOptionNumber The boot option number for the key option.
@param Modifier Key shift state.
@param ... Parameter list of pointer of EFI_INPUT_KEY.
@retval EFI_SUCCESS The key option is added.
@retval EFI_ALREADY_STARTED The hot key is already used by certain key option.
**/
EFI_STATUS
EFIAPI
EfiBootManagerAddKeyOptionVariable (
OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL
IN UINT16 BootOptionNumber,
IN UINT32 Modifier,
...
)
{
EFI_BOOT_MANAGER_KEY_OPTION KeyOption;
...
UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumber);
Status = gRT->SetVariable ( // <------ this call sets 'KeyXXXX' variable
KeyOptionName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
BmSizeOfKeyOption (&KeyOption),
&KeyOption
);
if (!EFI_ERROR (Status)) {
...
if (mBmHotkeyServiceStarted) {
BmProcessKeyOption (&KeyOption); // <---- this function calls 'RegisterKeyNotify'
}
}
return Status;
}
EFI_BOOT_MANAGER_KEY_OPTION이 어떻게 코딩되어있는지 확인하려면, MdeModulePkg/Include/Library/UefiBootManager.h에서 정의를 보면 된다.
#pragma pack(1)
///
/// EFI Key Option.
///
typedef struct {
///
/// Specifies options about how the key will be processed.
///
EFI_BOOT_KEY_DATA KeyData;
///
/// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to
/// which BootOption refers. If the CRC-32s do not match this value, then this key
/// option is ignored.
///
UINT32 BootOptionCrc;
///
/// The Boot#### option which will be invoked if this key is pressed and the boot option
/// is active (LOAD_OPTION_ACTIVE is set).
///
UINT16 BootOption;
///
/// The key codes to compare against those returned by the
/// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.
/// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.
///
EFI_INPUT_KEY Keys[3];
UINT16 OptionNumber;
} EFI_BOOT_MANAGER_KEY_OPTION;
#pragma pack()
위의 gRT->SetVariable 호출에 사용된 BmSizeOfKeyOption 함수(BmHotKey.c)를 살펴보면 다음과 같다.
EFI_BOOT_MANAGER_KEY_OPTION의 OptionNumber 필드가 NVRAM에 저장되지 않고, 키 배열의 크기가 가변적임을 알 수 있다.
다른 하위 유형의 경우,
EFI_BOOT_KEY_DATA는 UefiSpec.h에 정의되어 있다.
$ cat MdePkg/Include/Uefi/UefiSpec.h
---
///
/// EFI Boot Key Data
///
typedef union {
struct {
///
/// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0.
///
UINT32 Revision : 8;
///
/// Either the left or right Shift keys must be pressed (1) or must not be pressed (0).
///
UINT32 ShiftPressed : 1;
///
/// Either the left or right Control keys must be pressed (1) or must not be pressed (0).
///
UINT32 ControlPressed : 1;
///
/// Either the left or right Alt keys must be pressed (1) or must not be pressed (0).
///
UINT32 AltPressed : 1;
///
/// Either the left or right Logo keys must be pressed (1) or must not be pressed (0).
///
UINT32 LogoPressed : 1;
///
/// The Menu key must be pressed (1) or must not be pressed (0).
///
UINT32 MenuPressed : 1;
///
/// The SysReq key must be pressed (1) or must not be pressed (0).
///
UINT32 SysReqPressed : 1;
UINT32 Reserved : 16;
///
/// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If
/// zero, then only the shift state is considered. If more than one, then the boot option will
/// only be launched if all of the specified keys are pressed with the same shift state.
///
UINT32 InputKeyCount : 2;
} Options;
UINT32 PackedValue;
} EFI_BOOT_KEY_DATA;