17. 부팅 옵션에 WaitForEvent 함수 추가

이전 장에서 부팅 옵션에 HelloWorld 애플리케이션을 부팅 옵션에 추가했다.

EFI Shell에서 exit 명령어를 통해 BIOS로 이동한 후 부팅 매니저를 보면 HelloWorld 애플리케이션을 확인할 수 있다. 해당 애플리케이션을 실행하면 글자를 출력하고 바로 BIOS 화면으로 돌아가는 것을 확인할 수 있다.

Shell> exit

문자열을 출력하고 바로 BIOS로 돌아가는 것을 고치기 위해 이번 장에서는 HelloWorld 애플리케이션 코드에 WaitForEvent 함수를 추가한다.

WaitForEvent 는 사용자로부터 키 입력을 받을 때까지 기다리는 함수이다.

EFI_BOOT_SERVICES.WaitForEvent()

Summary
Stops execution until an event is signaled.

Prototype
typedef

EFI_STATUS
(EFIAPI *EFI_WAIT_FOR_EVENT) (
 IN UINTN NumberOfEvents,
 IN EFI_EVENT *Event,
 OUT UINTN *Index
);

Parameters
NumberOfEvents 	The number of events in the Event array.
Event 		An array of EFI_EVENT.
Index 		Pointer to the index of the event which satisfied the wait condition.

해당 문제를 해결하기 위해서 EFI_SIMPLE_TEXT_INPUT_PROTOCOLEFI_EVENT WaitForKey를 사용해야 한다.(gST->ConIn으로 사용할 수 있다.)

typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
 EFI_INPUT_RESET Reset;
 EFI_INPUT_READ_KEY ReadKeyStroke;
 EFI_EVENT WaitForKey;
} EFI_SIMPLE_TEXT_INPUT_PROTOCOL;

함수를 추가하기 위해 UefiLessonsPkg/HelloWorld/HelloWorld.c에 아래 코드를 추가한다.

UINTN Index;
gBS->WaitForEvent(1, &(gST->ConIn->WaitForKey), &Index);

OVMF를 새롭게 빌드한 후 BIOS -> Boot Manager -> HelloWorld 애플리케이션을 실행하면 처음과는 달리 문자열들을 출력하고 대기하는 화면을 볼 수 있다.

build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5

아직 문제가 남아있다. 이번에는 엔터키 입력을 했을 경우 다시 문자열 출력 화면으로 돌아온다.

이 문제는 입력 버퍼를 읽거나 지우지 않아 발생하는 문제로 Reset 함수를 통해 해결할 수 있다.

EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset()

Summary:
Resets the input device hardware.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_RESET) (
 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
 IN BOOLEAN ExtendedVerification
 );

Parameters:
This 			A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
ExtendedVerification	Indicates that the driver may perform a more exhaustive verification
			operation of the device during reset.

Description:
The Reset() function resets the input device hardware.
The implementation of Reset is required to clear the contents of any input queues resident in memory
used for buffering keystroke data and put the input stream in a known empty state

UefiLessonsPkg/HelloWorld/HelloWorld.c에 아래 코드를 추가한다.

gST->ConIn->Reset(gST->ConIn, FALSE);

다시 OVMF를 빌드하고 HelloWorld 애플리케이션을 실행해보면 모든 키 입력에서 정상적으로 종료가 되는 것을 볼 수 있다.

HelloWorld.c

#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI
UefiMain (
	IN EFI_HANDLE		ImageHandle,
	IN EFI_SYSTEM_TABLE *SystemTable
)
{
	SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n");
	gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n");
	Print(L"Bye!\n");

	UINTN Index;
	gBS->WaitForEvent(1, &(gST->ConIn->WaitForKey), &Index);
	gST->ConIn->Reset(gST->ConIn, FALSE);
	return EFI_SUCCESS;
}

Last updated