1. gRT(Runtime Services)란?
gRT는 UEFI 런타임 서비스 테이블(EFI_RUNTIME_SERVICES)을 가리키는 전역 포인터이다.
gBS(Boot Service)가 제공하는 메모리 할당이나 화면 출력 같은 기능들은 OS 부팅 직전인 ExitBootServices() 호출 시점에 메모리에서 모두 해제되고 소멸된다. 하지만 gRT가 제공하는 기능들은 OS 커널이 로드된 후(Runtime Phase)에도 메모리에 계속 유지되며, OS가 펌웨어 하드웨어(NVRAM 플래시, RTC 칩 등)에 접근할 수 있는 표준 API를 제공한다.
윈도우나 리눅스에서 efibootmgr로 부팅 순서를 바꾸거나, 펌웨어 업데이트를 스케줄링하고 시스템을 재부팅하는 모든 동작이 내부적으로는 OS 커널을 통해 펌웨어의 gRT 함수를 호출하는 것이다. EDK2 환경에서는 UefiRuntimeServicesTableLib를 통해 gRT 포인터가 자동으로 초기화된다.
2. 구조체 정의
EDK2 소스 코드 내에서 gRT는 전역 포인터로 선언되며, 가리키는 EFI_RUNTIME_SERVICES구조체는 NVRAM, 시간(RTC), 시스템 제어에 특화된 함수 포인터들로 구성된다.
2.1.전역변수 선언
// MdePkg/Include/Library/UefiRuntimeServicesTableLib.h
// 런타임 단계까지 유지되는 서비스 테이블 포인터
extern EFI_RUNTIME_SERVICES *gRT;
2.2.구조체 정의 (UefiSpec.h 축약)
// MdePkg/Include/Uefi/UefiSpec.h
typedef struct {
EFI_TABLE_HEADER Hdr;
// 1. Time Services (RTC 제어)
EFI_GET_TIME GetTime;
EFI_SET_TIME SetTime;
EFI_GET_WAKEUP_TIME GetWakeupTime;
EFI_SET_WAKEUP_TIME SetWakeupTime;
// 2. Virtual Memory Services (OS 커널용 가상 주소 매핑)
EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
EFI_CONVERT_POINTER ConvertPointer;
// 3. Variable Services (NVRAM 변수 제어 - 가장 중요)
EFI_GET_VARIABLE GetVariable;
EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName;
EFI_SET_VARIABLE SetVariable;
// 4. Miscellaneous Services
EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount;
EFI_RESET_SYSTEM ResetSystem; // 시스템 재부팅/종료
// 5. UEFI 2.0 Capsule Services (펌웨어 업데이트)
EFI_UPDATE_CAPSULE UpdateCapsule;
EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities;
// 6. Miscellaneous UEFI 2.0 Service
EFI_QUERY_VARIABLE_INFO QueryVariableInfo;
} EFI_RUNTIME_SERVICES;
3. 자주 쓰는 패턴
3.1. NVRAM 변수 읽기 (설정 로드): gRT->GetVariable
#include <Uefi.h>
#include <Library/UefiRuntimeServicesTableLib.h> // gRT 사용
#include <Library/MemoryAllocationLib.h> // AllocatePool 사용 (Boot Phase 전용)
// 이 패턴은 OS 부팅 전(Boot Phase)에만 사용할 수 있다.
// 런타임(OS 진입 후)에는 동적 할당을 할 수 없으므로 정적 버퍼를 사용해야 한다.
EFI_STATUS ReadMyCustomConfig() {
EFI_STATUS Status;
UINTN DataSize = 0;
UINT32 Attributes;
VOID *Data = NULL;
// 1단계: 변수의 실제 크기 알아내기 (Data=NULL, DataSize=0으로 호출)
Status = gRT->GetVariable (
L"MyCustomConfig",
&gMyCustomVariableGuid,
&Attributes,
&DataSize,
Data
);
// 변수가 아직 존재하지 않는 경우의 예외 처리
if (Status == EFI_NOT_FOUND) {
return EFI_NOT_FOUND;
}
// 변수가 존재하여 크기를 알아낸 경우 (정상적인 흐름)
if (Status == EFI_BUFFER_TOO_SMALL) {
// 2단계: 알아낸 크기만큼 메모리 할당 후 실제 데이터 읽기
Data = AllocatePool(DataSize);
if (Data != NULL) {
Status = gRT->GetVariable (
L"MyCustomConfig",
&gMyCustomVariableGuid,
&Attributes,
&DataSize,
Data
);
// Data 메모리 활용 로직
FreePool(Data); // 사용 완료 후 해제
} else {
Status = EFI_OUT_OF_RESOURCES;
}
}
return Status;
}
가장 빈번하게 사용되는 패턴이다. Boot Order(부팅 순서), Secure Boot 상태, 혹은 제조사 고유의 커스텀 설정값을 SPI Flash(NVRAM)에서 읽어온다.
3.2. NVRAM 변수 쓰기 (설정 저장): gRT->SetVariable
EFI_STATUS SaveMyCustomConfig(UINT32 MyValue) {
EFI_STATUS Status;
// NVRAM에 MyCustomConfig라는 이름으로 4바이트(UINT32) 데이터 저장
// OS에서도 접근 가능하도록 RUNTIME_ACCESS 속성 부여
Status = gRT->SetVariable(
L"MyCustomConfig",
&gMyCustomVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(UINT32),
&MyValue
);
return Status;
}
부팅 중에 변경된 하드웨어 설정이나 로그를 비휘발성 메모리에 저장할 때 사용한다. Attributes 플래그를 조합하여 OS에서도 접근 가능하게 할지(EFI_VARIABLE_RUNTIME_ACCESS), 비휘발성으로 플래시에 저장할지(EFI_VARIABLE_NON_VOLATILE) 결정한다.
3.3. 시스템 리셋 (재부팅/종료): gRT->ResetSystem
// 시스템 콜드 부트(전체 전원 차단 후 초기화 재부팅) 수행
// 이 함수는 정상적으로 실행되면 시스템이 즉시 재부팅되므로 값을 반환하지 않는다.
gRT->ResetSystem(
EfiResetCold,
EFI_SUCCESS,
0,
NULL
);
시스템을 재시작하거나 종료할 때 호출한다. ACPI나 하드웨어 레벨의 복잡한 전원 제어를 펌웨어가 대신 처리해 준다.
'CS > Graduation project' 카테고리의 다른 글
| Taint Analysis 개념 정리 (0) | 2026.03.01 |
|---|---|
| [UEFI] Ghidra에서 edk2 함수 P-code로 확인해 보기 (0) | 2026.02.26 |
| [UEFI] gBS(Boot Services)란? (0) | 2026.02.24 |
| [UEFI] SMM/MM Communication Protocol이란? (0) | 2026.02.24 |
| [UEFI] CommBuffer 검증 우회 (Ring -2) (0) | 2026.02.24 |