出力

一番シンプルなのは、EFI_SIMPLE_TEXT_OUTPUT_PROTOCOLであるEFI_SYSTEM_TABLE.ConOutを使う方法です。

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.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");
	return EFI_SUCCESS;
}

EDK2ではprintf相当のことをしてくれるPrint関数があったりするので、出力はかなり楽です。

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
	Print(L"Hello, %s!\n", L"world");
	return EFI_SUCCESS;
}

その他にも、<Library/PrintLib.h>にはsprintf相当のUnicodeSPrintなどの便利関数があります。

入力

入力は出力に比べて少々面倒です。EFI_SIMPLE_TEXT_INPUT_PROTOCOLEFI_SIMPLE_TEXT_OUTPUT_PROTOCOLに比べて貧弱な機能しか持っておらず、キーを1つだけ入力として受け取る以外のことができません。そのため、キーボードから1行読み取るといった単純な関数すら自作しなければなりません。

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>

EFI_SYSTEM_TABLE *gST;
EFI_BOOT_SERVICES *gBS;

EFI_STATUS GetLine (
	OUT CHAR16 *Buf,
	IN OUT UINTN *BufSize
	)
{
	EFI_STATUS Status;
	UINTN EventIndex;
	EFI_INPUT_KEY Key;
	for (UINTN i = 0; i < *BufSize; i++) {
		gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &EventIndex);
		Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
		if (Status != EFI_SUCCESS) {
			return Status;
		}
		Buf[i] = Key.UnicodeChar;
		if (Buf[i] == L'\n' || Buf[i] == L'\r') {
			Print(L"\n");
			Buf[i] = L'\0';
			*BufSize = i;
			return EFI_SUCCESS;
		}
		Print(L"%c", Buf[i]);

	}
	return EFI_BUFFER_TOO_SMALL;
}

#define BUF_SIZE 256

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
	CHAR16 *Buf;
	UINTN BufSize = BUF_SIZE;
	EFI_STATUS Status;

	gST = SystemTable;
	gBS = SystemTable->BootServices;

	Status = gBS->AllocatePool(EfiLoaderData, BUF_SIZE, &Buf);
	if (Status != EFI_SUCCESS) {
		Print(L"Memory allocation failed\n");
		return Status;
	}

	Print(L"input here: ");

	Status = GetLine(Buf, &BufSize);
	if (Status != EFI_SUCCESS) {
		Print(L"error: %d\n", Status);
		return Status;
	}

	Print(L"you wrote: %s\n", Buf);

	return EFI_SUCCESS;
}

ちなみに、UEFIでは入出力ともにデフォルトでUnicodeが使えます。