14.gRT->GetNextVariableName API를 사용하여 모든 변수 이름 및 GUID 가져오기
이번 장에서는 런타임 변수를 모두 출력해보는 실습을 한다.
이를 위해서는 EFI Runtime Services의 GetNextVariableName() API 함수를 사용해야 한다.
GetNextVariableName()
Summary:
Enumerates the current variable names.
Prototype:
typedef
EFI_STATUS
GetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
);
Parameters:
VariableNameSize The size of the VariableName buffer. The size must be large
enough to fit input string supplied in VariableName buffer.
VariableName On input, supplies the last VariableName that was returned by
GetNextVariableName(). On output, returns the Nullterminated string
of the current variable.
VendorGuid On input, supplies the last VendorGuid that was returned by
GetNextVariableName(). On output, returns the VendorGuid
of the current variable.
Description
GetNextVariableName() is called multiple times to retrieve the VariableName and VendorGuid of all
variables currently available in the system. On each call to GetNextVariableName() the previous
results are passed into the interface, and on output the interface returns the next variable name data.
When the entire variable list has been returned, the error EFI_NOT_FOUND is returned.
Note that if EFI_BUFFER_TOO_SMALL is returned, the VariableName buffer was too small for the next
variable. When such an error occurs, the VariableNameSize is updated to reflect the size of buffer
needed. In all cases when calling GetNextVariableName() the VariableNameSize must not exceed the
actual buffer size that was allocated for VariableName. The VariableNameSize must not be smaller the size
of the variable name string passed to GetNextVariableName() on input in the VariableName buffer.
To start the search, a Null-terminated string is passed in VariableName; that is, VariableName is a pointer
to a Null character. This is always done on the initial call to GetNextVariableName(). When
VariableName is a pointer to a Null character, VendorGuid is ignored.
Status Codes Returned:
EFI_SUCCESS The function completed successfully.
EFI_NOT_FOUND The next variable was not found.
EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result.
VariableNameSize has been updated with the size needed to complete the request.
...이전에 gST/gBS를 얻기 위해 파일에 #include <Library/UefiBootServicesTableLib.h>를 포함했다. EFI Runtime Services Table에 대한 바로가기를 얻으려면 비슷한 헤더파일을 추가해야 한다.
위 파일을 보면 라이브러리 생성자 호출 때 gRT = SystemTable->RuntimeServices;로 채워지는 extern EFI_RUNTIME_SERVICES *gRT;만 단순히 추가해준다.
UEFI 스펙에 따르면 검색을 하려면 Null (=0)과 같은 1개의 문자로 문자열을 생성해야 한다고 한다.이러한 문자열을 생성하기 위해 AllocateZeroPool함수를 사용한다.
AllocateZeroPool 은 UEFI 스펙에서 정의된 기능이 아니고 EDKII의 MemoryAllocationLib에서 사용자를 편하게 해주기 위해 만든 기능이다.
이 문자열은 변수 이름을 저장하기에 충분히 크지 않을 것이므로 적어도 첫 번째 호출에서는 확실하게 EFI_BUFFER_TOO_SMALL을 반환할 것이다.
이 경우 버퍼를 재할당해야 하는데 ReallocatePool 함수로 이를 수행할 수 있다.
ReallocatePool또한 EDKII의 MemoryAllocationLib에서 만들어진 함수이다.
이제 ListVariables라는 애플리케이션을 만들어서 첫 번째 변수를 출력해보자.
빌드 후에 OVMF로 실행해보면 다음과 같은 결과를 얻을 수 있다.
이제 사용되는 모든 변수를 출력하는 반복문을 작성하여 모든 변수를 출력해보자.
while(TRUE) 반복문 안에서 gRT->GetNextVariableName함수를 계속 실행하여 반환된 EFI_STATUS코드를 구분한다.
EFI_SUCCESS는 변수를 성공적으로 획득했음을 나타내므로 그냥 출력하면 된다.EFI_BUFFER_TOO_SMALL은 배열을ReAllocatePool을 호출해 크기를 늘리고 다시gRT->GetNextVariableName를 호출해야 함을 의미한다.EFI_NOT_FOUND는 우리가 모든 변수를 파싱하여 멈춰야 한다는 것을 의미한다.다른 상태에서는 단순 오류로 출력하고 반환한다.
이제 우리 프로그램을 OVMF에서 실행하면 다음과 같이 출력된다.
8BE4DF61-93CA-11D2-AA0D-00E098032B8C를 GUID로 가지고 있는 그룹이 제일 중요하다.
EFI_GLOBAL_VARIABLE을 뜻하는 GUID며 UEFI 스펙에 정의되어 있다.
EDKII에서는 여기에서 찾을 수 있다.
Boot####같은 옵션들은 UEFI 스펙에서 정의되므로 미리 정의된 GUID인 EFI_GLOBAL_VARIABLE를 가지고 있다. 고유한 옵션을 만들고 싶다면 EFI_GLOBAL_VARIABLE을 사용하면 안되고 충돌 가능성을 없애기 위해 고유한 옵션을 만들어야한다.
EDKII 코드베이스에서 GUID가 정의된 위치를 보려면 다음과 같이 하면 된다.
GUID별로 변수를 정렬하려면 위의 명령 실행결과를 파일로 저장하고 Linux Shell에서 정렬을 수행하면 된다.
여기서부터는 GUID에 대한 정의가 있는 파일이 있고 그룹화된 GUID를 쓰는 변수들의 목록이다.
8BE4DF61-93CA-11D2-AA0D-00E098032B8C - gEfiGlobalVariableGuid
04B37FE8-F6AE-480B-BDD5-37D98C5E89AA - gEdkiiVarErrorFlagGuid
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Guid/VarErrorFlag.h
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/MdeModulePkg.dec
4C19049F-4137-4DD3-9C10-8B97A83FFDFA - gEfiMemoryTypeInformationGuid
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/MdeModulePkg.dec
5B446ED1-E30B-4FAA-871A-3654ECA36080 - gEfiIp4Config2ProtocolGuid
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/Ip4Config2.h
https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec
EB704011-1402-11D3-8E77-00A0C969723B - gMtcVendorGuid
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Guid/MtcVendor.h
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/MdeModulePkg.dec
59324945-EC44-4C0D-B1CD-9DB139DF070C - gEfiIScsiInitiatorNameProtocolGuid
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/IScsiInitiatorName.h
https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec
158DEF5A-F656-419C-B027-7A3192C079D2 - gShellVariableGuid
https://github.com/tianocore/edk2/blob/master/ShellPkg/Include/Guid/ShellVariableGuid.h
https://github.com/tianocore/edk2/blob/master/ShellPkg/ShellPkg.dec
4B47D616-A8D6-4552-9D44-CCAD2E0F4CF9 - gIScsiConfigGuid
https://github.com/tianocore/edk2/blob/master/NetworkPkg/Include/Guid/IScsiConfigHii.h
https://github.com/tianocore/edk2/blob/master/NetworkPkg/NetworkPkg.dec
0053D9D6-2659-4599-A26B-EF4536E631A9 - gShellAliasGuid
https://github.com/tianocore/edk2/blob/master/ShellPkg/Include/Guid/ShellAliasGuid.h
https://github.com/tianocore/edk2/blob/master/ShellPkg/ShellPkg.dec
Last updated