PCD(Platform Configuration Database)는 드라이버 또는 애플리케이션이 액세스할 수 있는 다양한 현재 플랫폼 설정 또는 지침이 포함된 데이터베이스이다.
PCD에 대한 자세한 설명은 EDKII 스펙을 통해 확인할 수 있다.
- https://edk2-docs.gitbook.io/edk-ii-pcd-specification/
- https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/edkii-platform-config-database-entries-paper.pdf
PCD entry는 PCD라고도 불린다. 그래서 여기서도 그냥 PCD라고 부른다.
PCD entry는 DEC 파일에 정의된다.
<TokenSpaceGuidCName>
은 GUID 값이고, <Token>
은 32bit 값이다. 이것들은 PCD를 식별하는 데 사용된다.
Copy <TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>
먼저 모든 PCD를 포함하는 토큰 공간을 선언한다. 일반적으로 g<PakageName>TokenSpaceGuid
로 정의되기 때문에 UefiLessonsPkg/UefiLessonsPkg.dec
에 추가해야 한다.
Copy [Guids]
...
gUefiLessonsPkgTokenSpaceGuid = {0x150cab53, 0xad47, 0x4385, {0xb5, 0xdd, 0xbc, 0xfc, 0x76, 0xba, 0xca, 0xf0}}
<Token>
값의 경우, 일반적으로 패키지 작성자는 0x00000001
부터 순차적으로 쓰기 시작한다. 또한 일부 PCD가 하나의 논리 그룹에 속한다는 것을 나타내기 위해 종종 토큰 번호를 사용하여 이를 나타낼 수 있다. 예를 들어 토큰 그룹은 0x1XXXXXXX
, 0x2XXXXXXX
등이 될 수 있다.
패키지가 발전함에 따라 일부 PCD가 추가되고 일부 PCD가 제거된다. 만약 순차적인 번호를 사용한다면 이것은 어려움을 줄 수 있다. 예를 들어 토큰이 0x0000000A
및 0x0000000B
인 PCD가 있는 경우 어려움이 발생할 수 있으며 새 PCD를 넣는 가장 논리적인 방법은 0x0000000A
인 PCD 이후이다. 물론 PCD 토큰을 0x0000000C
에 할당하여 실행할 수도 있지만, 그렇다면 순차적인 번호 지정의 의미를 알아야 한다.
순차적인 번호 지정은 힘들기 때문에 아래 스크립트를 생성했다. 아래 스크립트는 임의의 4바이트 토큰 번호를 생성하는 스크립트다.
Copy #!/bin/bash
##
# This is a simple script that generates a random 4-byte hex value for a PCD Token
##
hexdump -vn4 -e'"0x%08X\n"' /dev/urandom
스크립트를 사용하면 아래와 같이 4바이트의 토큰 번호를 생성할 수 있다.
Copy $ ./scripts/genToken.sh
0x3B81CDF1
이제 gUefiLessonsPkgTokenSpaceGuid
를 정의하는 데 사용한 *.dec
파일에 PCD를 정의할 수 있다.
PCD를 UINT8 PcdInt8 = 0x88
로 시작한다.
Copy [PcdsFixedAtBuild]
gUefiLessonsPkgTokenSpaceGuid.PcdInt8|0x88|UINT8|0x3B81CDF1
PCDLesson
애플리케이션을 생성하기 위해 UefiLessons/PCDLesson/PCDLesson.c
파일에 아래 코드를 추가한다.
Copy #include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle ,
IN EFI_SYSTEM_TABLE * SystemTable
)
{
Print(L "PcdInt8=0x %x \n" , FixedPcdGet8(PcdInt8)) ;
return EFI_SUCCESS;
}
FixedPcdGet8
을 사용하기 위해서는 헤더 파일이 필요하다. PcdLib
헤더를 추가한다.
Copy #include <Library/PcdLib.h>
이 링크(https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h )를 통해 FixedPcdGet8
을 살펴보면 단순히 정의되어 있다는 것을 알 수 있다.
Copy #define FixedPcdGet8 (TokenName) _PCD_VALUE_##TokenName
아직은 빌드를 시도하면 애플리케이션이 정의되어 있지 않기 때문에 에러가 발생한다.
Copy /home/kostr/tiano/edk2/MdePkg/Include/Library/PcdLib.h:97:45: error: ‘_PCD_VALUE_PcdInt8’ undeclared (first use in this function)
97 | #define FixedPcdGet8(TokenName) _PCD_VALUE_##TokenName
| ^~~~~~~~~~~
에러를 해결하기 위해서는 아직 생성하지 않았던 *.inf 파일을 생성해야 한다. 해당 파일은 HelloWorld
애플리케이션에서 사용했던 것을 복사하여 수정 해야 할 부분을 수정한 후 PCD 애플리케이션을 추가한다.
Copy [FixedPcd]
gUefiLessonsPkgTokenSpaceGuid.PcdInt8
추가적으로 PCD를 정의하는 dec
파일을 포함하도록 한 후 빌드를 시도하면 잘 되는 것을 볼 수 있다.
Copy [Packages]
...
UefiLessonsPkg/UefiLessonsPkg.dec
자동 생성된 파일 AutoGen.h
/AutoGen.c
의 내용을 확인하면 PCD가 있는 것을 확인할 수 있다.
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
Copy // Definition of PCDs used in this module
#define _PCD_TOKEN_PcdInt8 0U
#define _PCD_SIZE_PcdInt8 1
#define _PCD_GET_MODE_SIZE_PcdInt8 _PCD_SIZE_PcdInt8
#define _PCD_VALUE_PcdInt8 0x88U
extern const UINT8 _gPcd_FixedAtBuild_PcdInt8;
#define _PCD_GET_MODE_8_PcdInt8 _gPcd_FixedAtBuild_PcdInt8
//#define _PCD_SET_MODE_8_PcdInt8 ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c
Copy // Definition of PCDs used in this module
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdInt8 = _PCD_VALUE_PcdInt8;
따라서 프리프로세서는 아래와 같이 코드를 확장한다.
Copy FixedPcdGet8(PcdInt8) -> _PCD_VALUE_PcdInt8 -> 0x88U
OVMF를 통해 PCDLesson
애플리케이션을 실행하면 올바른 값이 출력되는 것을 볼 수 있다.
Copy FS0:\> PCDLesson.efi
PcdInt8=0x88
PCD에는 여러 유형이 있고 FixedAtBuild
PCD는 그 중 하나이다. 코드에서는 FixedPcdGet8
호출을 사용하여 PCD 값을 얻었으며, 이 호출은 PCD가 FixedAtBuild
인 경우에만 할 수 있다.
FixedAtBuild
와는 달리 PCD 유형에 관계없이 PCD 값을 얻는 데 사용할 수 있는 일반적인 PcdGet8
호출이 있다.
Copy #define PcdGet8(TokenName) _PCD_GET_MODE_8_##TokenName
PcdGet8
을 사용하면 아래와 같이 확장된다.
Copy PcdGet8(PcdInt8) -> _PCD_GET_MODE_8_PcdInt8 -> _gPcd_FixedAtBuild_PcdInt8
AutoGen.c
에서는 아래와 같이 정의되어 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdInt8 = _PCD_VALUE_PcdInt8 // =0x88U;
PCDLesson.c
에 아래와 같이 PcdGet8
과 FixedAtBuild
를 비교할 수 있도록 수정한다.
Copy Print(L"PcdInt8=%d\n", FixedPcdGet8(PcdInt8));
Print(L"PcdInt8=%d\n", PcdGet8(PcdInt8));
빌드 후 결과를 확인하면 동일한 것을 볼 수 있다. 다만, 차이점은 PcdGet8
은 다른 PCD 유형과 함께 사용할 수 있다는 것이다.
Copy FS0:\> PCDLesson.efi
PcdInt8=0x88
PcdInt8=0x88
다른 간단한 PCD 유형
위의 예제에서는 UINT8
을 PCD의 <DatumType>
로 사용했다. 이러한 유형과 함께 EDKII를 사용하면 다른 정수 데이터 유형 UINT16
, UINT32
또는 UINT64
정수 데이터 유형 및 BOOLEAN
유형을 사용할 수 있다.
이러한 PCD를 UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdInt16|0x1616|UINT16|0x77DFB6E6
gUefiLessonsPkgTokenSpaceGuid.PcdInt32|0x32323232|UINT32|0xF2A48130
gUefiLessonsPkgTokenSpaceGuid.PcdInt64|0x6464646464646464|UINT64|0x652F4E29
gUefiLessonsPkgTokenSpaceGuid.PcdBool|TRUE|BOOLEAN|0x69E88A63
또한, UefiLessonsPkg/PCDLesson/PCDLesson.inf
모듈에 포함하여야 한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdInt16
gUefiLessonsPkgTokenSpaceGuid.PcdInt32
gUefiLessonsPkgTokenSpaceGuid.PcdInt64
gUefiLessonsPkgTokenSpaceGuid.PcdBool
빌드를 진행하면 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
에 채워지는 것을 볼 수 있다.
Copy #define _PCD_TOKEN_PcdInt16 0U
#define _PCD_SIZE_PcdInt16 2
#define _PCD_GET_MODE_SIZE_PcdInt16 _PCD_SIZE_PcdInt16
#define _PCD_VALUE_PcdInt16 0x1616U
extern const UINT16 _gPcd_FixedAtBuild_PcdInt16;
#define _PCD_GET_MODE_16_PcdInt16 _gPcd_FixedAtBuild_PcdInt16
//#define _PCD_SET_MODE_16_PcdInt16 ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_TOKEN_PcdInt32 0U
#define _PCD_SIZE_PcdInt32 4
#define _PCD_GET_MODE_SIZE_PcdInt32 _PCD_SIZE_PcdInt32
#define _PCD_VALUE_PcdInt32 0x32323232U
extern const UINT32 _gPcd_FixedAtBuild_PcdInt32;
#define _PCD_GET_MODE_32_PcdInt32 _gPcd_FixedAtBuild_PcdInt32
//#define _PCD_SET_MODE_32_PcdInt32 ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_TOKEN_PcdInt64 0U
#define _PCD_SIZE_PcdInt64 8
#define _PCD_GET_MODE_SIZE_PcdInt64 _PCD_SIZE_PcdInt64
#define _PCD_VALUE_PcdInt64 0x6464646464646464ULL
extern const UINT64 _gPcd_FixedAtBuild_PcdInt64;
#define _PCD_GET_MODE_64_PcdInt64 _gPcd_FixedAtBuild_PcdInt64
//#define _PCD_SET_MODE_64_PcdInt64 ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_TOKEN_PcdBool 0U
#define _PCD_SIZE_PcdBool 1
#define _PCD_GET_MODE_SIZE_PcdBool _PCD_SIZE_PcdBool
#define _PCD_VALUE_PcdBool 1U
extern const BOOLEAN _gPcd_FixedAtBuild_PcdBool;
#define _PCD_GET_MODE_BOOL_PcdBool _gPcd_FixedAtBuild_PcdBool
//#define _PCD_SET_MODE_BOOL_PcdBool ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c
에서도 확인이 가능하다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 _gPcd_FixedAtBuild_PcdInt16 = _PCD_VALUE_PcdInt16;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdInt32 = _PCD_VALUE_PcdInt32;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT64 _gPcd_FixedAtBuild_PcdInt64 = _PCD_VALUE_PcdInt64;
GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_PcdBool = _PCD_VALUE_PcdBool;
선언된 내용 살펴보면 처음에 사용했던 UINT8
와 모두 비슷한 것을 알 수 있다.
이전과 같이 FixedPcdGet
과 PcdGet
API를 사용하여 PCD 값을 확인한다.
Copy Print(L"PcdInt16=0x%x\n", FixedPcdGet16(PcdInt16));
Print(L"PcdInt32=0x%x\n", FixedPcdGet32(PcdInt32));
Print(L"PcdInt64=0x%x\n", FixedPcdGet64(PcdInt64));
Print(L"PcdBool=0x%x\n", FixedPcdGetBool(PcdBool));
Print(L"PcdInt16=0x%x\n", PcdGet16(PcdInt16));
Print(L"PcdInt32=0x%x\n", PcdGet32(PcdInt32));
Print(L"PcdInt64=0x%x\n", PcdGet64(PcdInt64));
Print(L"PcdIntBool=0x%x\n", PcdGetBool(PcdBool));
출력된 결과를 보면 값이 동일한 것을 볼 수 있다.
Copy FS0:\> PCDLesson.efi
...
PcdInt16=0x1616
PcdInt32=0x32323232
PcdInt64=0x64646464
PcdBool=0x1
PcdInt16=0x1616
PcdInt32=0x32323232
PcdInt64=0x64646464
PcdIntBool=0x1
값을 초기화 할 때 사용할 수 있는 표현
값을 초기화 할 때 식을 사용할 수 있다. 연산에서 |
를 사용할 때는 괄호(...)
안에 식을 넣어야 한다.
예시는 아래와 같다. UefiLessonsPkg/UefiLessonsPkg.dec
에 아래와 같이 입력한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdExpression|0xFF000000 + 0x00FFFFFF|UINT32|0x9C405222
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_1|((0xFFFFFFFF & 0x000000FF) << 8) + 0x33|UINT32|0x5911C44B
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_2|(0x00000000 | 0x00100000)|UINT32|0xAD880207
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_3|((56 < 78) || !(23 > 44))|BOOLEAN|0x45EDE955
*.dec
파일에 추가하였으니 *.inf
파일에도 추가해야 한다. 여기서는 UefiLessonsPkg/PCDLesson/PCDLesson.inf
에 추가한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdExpression
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_1
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_2
gUefiLessonsPkgTokenSpaceGuid.PcdExpression_3
빌드 후 Autogen.h
을 확인하면 값이 계산되어 들어간 것을 볼 수 있다.
Copy ...
#define _PCD_VALUE_PcdExpression 4294967295U // =0xffffffff
...
#define _PCD_VALUE_PcdExpression_1 65331U // =0xff33
...
#define _PCD_VALUE_PcdExpression_2 1048576U // =0x100000
...
#define _PCD_VALUE_PcdExpression_3 1U
...
VOID* PCD 데이터 유형
EDK2에서는 UINT8
, UINT16
, UINT32
, UINT64
, BOOLEAN
외에도 VOID*
유형을 사용할 수 있다.
문자열 PCD
아래와 같은 PCD를 UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdAsciiStr|"hello"|VOID*|0xB29914B5
gUefiLessonsPkgTokenSpaceGuid.PcdUCS2Str|L"hello"|VOID*|0xF22124E5
첫 번째와 두번째는 데이터를 표현에 차이가 있다. 첫 번째는 "..."
로 되어있고 두 번째는 L"..."
로 되어있다.
이제 PCD를 UefiLessonsPkg/PCDLesson/PCDLesson.inf
에 추가한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdAsciiStr
gUefiLessonsPkgTokenSpaceGuid.PcdUCS2Str
빌드 후 AutoGen.h
파일을 살펴보면 아래와 같다.
Copy #define _PCD_TOKEN_PcdAsciiStr 0U
#define _PCD_VALUE_PcdAsciiStr _gPcd_FixedAtBuild_PcdAsciiStr
extern const UINT8 _gPcd_FixedAtBuild_PcdAsciiStr[6];
#define _PCD_GET_MODE_PTR_PcdAsciiStr _gPcd_FixedAtBuild_PcdAsciiStr
#define _PCD_SIZE_PcdAsciiStr 6
#define _PCD_GET_MODE_SIZE_PcdAsciiStr _PCD_SIZE_PcdAsciiStr
//#define _PCD_SET_MODE_PTR_PcdAsciiStr ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_TOKEN_PcdUCS2Str 0U
#define _PCD_VALUE_PcdUCS2Str _gPcd_FixedAtBuild_PcdUCS2Str
extern const UINT16 _gPcd_FixedAtBuild_PcdUCS2Str[6];
#define _PCD_GET_MODE_PTR_PcdUCS2Str _gPcd_FixedAtBuild_PcdUCS2Str
#define _PCD_SIZE_PcdUCS2Str 12
#define _PCD_GET_MODE_SIZE_PcdUCS2Str _PCD_SIZE_PcdUCS2Str
//#define _PCD_SET_MODE_PTR_PcdUCS2Str ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
Autogen.c
파일은 아래와 같다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdAsciiStr[6] = {104, 101, 108, 108, 111, 0 };
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdAsciiStr = 6;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT16 _gPcd_FixedAtBuild_PcdUCS2Str[6] = {104, 101, 108, 108, 111, 0 };
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdUCS2Str = 12;
위 파일들을 보면 알 수 있듯이 PcdAsciiStr
배열은 UINT8
로 구성됐지만 PcdUCS2Str
배열은 UINT16
으로 구성되어 있다.
또 다른 차이점은 문자열 크기에 대한 상수(sizeof()의 값)가 생성된다는 것이다. 이러한 값은 빌드 시스템에 의해 동적으로 계산된다.
VOID*
타입인 PCD 값을 가져오려면 FixedPcdGetPtr
이나 PcdGetPtr
API를 사용하고 바이트 단위로 가져오려면 FixedPcdGetSize
나 PcdGetSize
API를 사용한다.
Copy Print (L "PcdAsciiStr= %a \n" , FixedPcdGetPtr (PcdAsciiStr));
Print (L "PcdAsciiStrSize= %d \n" , FixedPcdGetSize (PcdAsciiStr));
Print (L "PcdUCS2Str= %s \n" , PcdGetPtr (PcdUCS2Str));
Print (L "PcdUCS2StrSize= %d \n" , PcdGetSize (PcdUCS2Str));
빌드 후 PCDLesson.efi
를 실행하면 아래와 같이 문자열과 크기를 확인할 수 있다.
Copy FS0:\> PCDLesson.efi
...
PcdAsciiStr=hello
PcdAsciiStrSize=6
PcdUCS2Str=hello
PcdUCS2StrSize=12
만약 프리프로세서를 대체하고 싶다면 PcdLib.h(https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h )를 사용하기 전에 했던 것처럼 할 수 있다.
Copy #define FixedPcdGetPtr(TokenName) ((VOID *)_PCD_VALUE_##TokenName)
#define FixedPcdGetSize(TokenName) _PCD_SIZE_##TokenName
#define PcdGetPtr(TokenName) _PCD_GET_MODE_PTR_##TokenName
#define PcdGetSize(TokenName) _PCD_GET_MODE_SIZE_##TokenName
이 예제에서는 문자열을 초기화 할 때 "..."
과 L"..."
을 사용했지만 '...'
이나 L'...'
을 사용해도 된다.
Byte 배열 PCD
VOID*
는 일반적으로 바이트 배열에 사용된다.
예시로 보기 위해 PCD를 UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdArray|{0xA5, 0xA6, 0xA7}|VOID*|0xD5DB9A27
UefiLessonsPkg/PCDLesson/PCDLesson.inf
에도 추가한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdArray
AutoGen 파일을 보면 PCD 배열이 추가된 것을 볼 수 있다.
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
Copy #define _PCD_TOKEN_PcdArray 0U
#define _PCD_VALUE_PcdArray (VOID *)_gPcd_FixedAtBuild_PcdArray
extern const UINT8 _gPcd_FixedAtBuild_PcdArray[3];
#define _PCD_GET_MODE_PTR_PcdArray (VOID *)_gPcd_FixedAtBuild_PcdArray
#define _PCD_SIZE_PcdArray 3
#define _PCD_GET_MODE_SIZE_PcdArray _PCD_SIZE_PcdArray
//#define _PCD_SET_MODE_PTR_PcdArray ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArray[3] = {0xA5, 0xA6, 0xA7};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArray = 3;
배열 요소를 출력하기 위해 아래 코드를 PCDLesson.c
에 추가한다. AutoGen.h
에서 데이터가 (VOID *)
로 캐스트 될 때 (UINT8*)
캐스트가 필요하다.
Copy for (UINTN i=0; i<FixedPcdGetSize(PcdArray); i++) {
Print(L"PcdArray[%d]=0x%02x\n", i, ((UINT8*)FixedPcdGetPtr(PcdArray))[i]);
}
빌드 후 PCDLesson.efi
를 실행하면 아래와 같이 배열이 출력되는 것을 볼 수 있다.
Copy FS0:\> PCDLesson.efi
...
PcdArray[0]=0xA5
PcdArray[1]=0xA6
PcdArray[2]=0xA7
GUID PCD
바이트 배열 초기화 구문을 사용하면 사용자 지정 구조의 유형을 이해하는 즉시 모든 사용자 지정 구조를 초기화할 수 있다.
EFI_GUID
(=GUID
) 구조를 살펴본다.
Copy typedef struct {
UINT32 Data1;
UINT16 Data2;
UINT16 Data3;
UINT8 Data4[8];
} GUID;
typedef GUID EFI_GUID;
만약 GUID가 "f1740707-691d-4203-bfab-99e132fa4166
"인 것을 인코딩 하려면 아래와 같이 하게 된다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdGuidInBytes|{0x07, 0x07, 0x74, 0xF1, 0x1D, 0x69, 0x03, 0x42, 0xBF, 0xAB, 0x99, 0xE1, 0x32, 0xFA, 0x41, 0x66}|VOID*|0xB9E0CDC0
따라서 정확한 값을 얻기 위해서는 일부 바이트를 재구성해야 한다. x86은 little-endian이기 때문에 필요하며, 이러한 시스템에서 숫자의 바이트는 상위에서 하위로 메모리에 배치되기 때문이다.
그렇기 때문에 사용자 지정 구조에 대해 바이트 배열 초기화를 인코딩할 때 이점을 염두해야 한다.
UEFI 코드에서는 GUID가 과도하게 사용되기 때문에 EDKII는 GUID PCD 초기화를 위한 도우미 구문을 가지고 있다.
도우미 구문을 사용하는 방법은 아래와 같다. 도우미 구문을 사용하여 PCD를 정의한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdGuid|{GUID("f1740707-691d-4203-bfab-99e132fa4166")}|VOID*|0x7F2066F7
도우미를 사용하지 않을 때와 사용할 때를 비교하기 위해 UefiLessonsPkg/UefiLessonsPkg.dec
에 아래 두 줄을 입력한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdGuidInBytes|{0x07, 0x07, 0x74, 0xF1, 0x1D, 0x69, 0x03, 0x42, 0xBF, 0xAB, 0x99, 0xE1, 0x32, 0xFA, 0x41, 0x66}|VOID*|0xB9E0CDC0
gUefiLessonsPkgTokenSpaceGuid.PcdGuid|{GUID("f1740707-691d-4203-bfab-99e132fa4166")}|VOID*|0x7F2066F7
그리고 UefiLessonsPkg/PCDLesson/PCDLesson.inf
에도 추가한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdGuidInBytes
gUefiLessonsPkgTokenSpaceGuid.PcdGuid
빌드하고 AutoGen 파일들을 살펴보면 아래와 같이 추가된 것을 확인할 수 있다.
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
Copy #define _PCD_TOKEN_PcdGuidInBytes 0U
#define _PCD_VALUE_PcdGuidInBytes (VOID *)_gPcd_FixedAtBuild_PcdGuidInBytes
extern const UINT8 _gPcd_FixedAtBuild_PcdGuidInBytes[16];
#define _PCD_GET_MODE_PTR_PcdGuidInBytes (VOID *)_gPcd_FixedAtBuild_PcdGuidInBytes
#define _PCD_SIZE_PcdGuidInBytes 16
#define _PCD_GET_MODE_SIZE_PcdGuidInBytes _PCD_SIZE_PcdGuidInBytes
//#define _PCD_SET_MODE_PTR_PcdGuidInBytes ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_TOKEN_PcdGuid 0U
#define _PCD_VALUE_PcdGuid (VOID *)_gPcd_FixedAtBuild_PcdGuid
extern const UINT8 _gPcd_FixedAtBuild_PcdGuid[16];
#define _PCD_GET_MODE_PTR_PcdGuid (VOID *)_gPcd_FixedAtBuild_PcdGuid
#define _PCD_SIZE_PcdGuid 16
#define _PCD_GET_MODE_SIZE_PcdGuid _PCD_SIZE_PcdGuid
//#define _PCD_SET_MODE_PTR_PcdGuid ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdGuidInBytes[16] = {0x07, 0x07, 0x74, 0xF1, 0x1D, 0x69, 0x03, 0x42, 0xBF, 0xAB, 0x99, 0xE1, 0x32, 0xFA, 0x41, 0x66};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdGuidInBytes = 16;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdGuid[16] = {0x07, 0x07, 0x74, 0xF1, 0x1D, 0x69, 0x03, 0x42, 0xBF, 0xAB, 0x99, 0xE1, 0x32, 0xFA, 0x41, 0x66};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdGuid = 16;
파일들을 통해 알 수 있듯이 PCD 인코딩과 초기화는 두 경우 모두 동일하다.
코드에서 GUID를 사용하려면 (VOID *)
에서 (EFI_GUID*)
로 GUID를 캐스팅 해야 한다.
Copy Print (L "PcdGuidInBytes= %g \n" , * (EFI_GUID * ) FixedPcdGetPtr (PcdGuidInBytes));
Print (L "PcdGuid= %g \n" , * (EFI_GUID * ) FixedPcdGetPtr (PcdGuid));
빌드 후 PCDLesson.efi
를 실행하면 출력된 결과도 동일한 것을 확인할 수 있다.
Copy FS0:\> PCDLesson.efi
...
PcdGuidInBytes=F1740707-691D-4203-BFAB-99E132FA4166
PcdGuid=F1740707-691D-4203-BFAB-99E132FA4166
GUID가 포함된 PCD를 초기화하는 방법에는 두 가지가 더 존재한다. 다른 GUID를 초기화에 사용하거나 표준 C 구문을 EFI_GUID 구조 초기화에 사용할 수 있다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdGuidByPCD|{GUID(gUefiLessonsPkgTokenSpaceGuid)}|VOID*|0x0860CCD5
gUefiLessonsPkgTokenSpaceGuid.PcdGuidByEfiGuid|{GUID({0x150cab53, 0xad47, 0x4385, {0xb5, 0xdd, 0xbc, 0xfc, 0x76, 0xba, 0xca, 0xf0}})}|VOID*|0x613506D5
새롭게 빌드하고 AutoGen.c
파일을 통해 확인할 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdGuidByPCD[16] = {0x53, 0xAB, 0x0C, 0x15, 0x47, 0xAD, 0x85, 0x43, 0xB5, 0xDD, 0xBC, 0xFC, 0x76, 0xBA, 0xCA, 0xF0};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdGuidByPCD = 16;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdGuidByEfiGuid[16] = {0x53, 0xAB, 0x0C, 0x15, 0x47, 0xAD, 0x85, 0x43, 0xB5, 0xDD, 0xBC, 0xFC, 0x76, 0xBA, 0xCA, 0xF0};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdGuidByEfiGuid = 16;
DEVICE_PATH
GUID(...)
도우미 외에도 EDK2에는 DEVICE_PATH(...)
도우미가 있어 다른 특별한 UEFI 구조인 Device Path를 초기화할 수 있다.
예를 들어, UEFI Shell이 시작될 때 출력되는 경로는 UEFI Device Path이다.
Copy UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
FS0: Alias(s):HD0a1:;BLK1:
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
BLK2: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
Press ESC in 5 seconds to skip startup.nsh or any other key to continue.
그 중 하나를 PCD 초기화에 사용한다. UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdDevicePath|{DEVICE_PATH("PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)")}|VOID*|0xC56EE1E2
UefiLessonsPkg/PCDLesson/PCDLesson.inf
에도 생성한 PCD를 추가한다.
Copy [FixedPcd]
...
gUefiLessonsPkgTokenSpaceGuid.PcdDevicePath
빌드 후 AutoGen.c를 살펴보면 아래와 같이 배열이 생성된 것을 볼 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdDevicePath[30] = {0x02,0x01,0x0c,0x00,0xd0,0x41,0x03,0x0a,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x01,0x01,0x03,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0x04,0x00};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdDevicePath = 30;
배열이 올바른지 확인하기 위해 프로그램에서 생성된 Device Path를 출력한다. 이를 위해 DevicePathLib.h
헤더 파일을 추가해야 한다.
Copy #include <Library/DevicePathLib.h>
그리고 ConvertDevicePathToText
함수를 사용한다.
Copy Print(L"PcdDevicePath: %s\n", ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*) FixedPcdGetPtr(PcdDevicePath), FALSE, FALSE));
빌드 후 PCDLesson.efi
를 실행하면 아래와 같은 출력을 볼 수 있다.
Copy FS0:\> PCDLesson.efi
...
PcdDevicePath: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
정수 캐스트 사용
UINT8(...)
, UINT16(...)
, UINT32(...)
, UINT64(...)
캐스트 도우미를 사용하여 VOID*
배열을 초기화할 수 있다.
UefiLessonsPkg/UefiLessonsPkg.dec
에 아래와 같이 추가한다. 앞으로 inf에 추가하는 것은 더이상 얘기하지 않을 것이니 dec에 PCD가 추가된다면 *.inf
에도 추가해야 한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdIntCasts|{UINT16(0x1122), UINT32(0x33445566), UINT8(0x77), UINT64(0x8899aabbccddeeff)}|VOID*|0x647456A6
빌드 후 AutoGen.c
를 살펴보면 little-endian
아키텍처와 관련하여 배열이 초기화되어 있음을 알 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdIntCasts[15] = {0x22, 0x11, 0x66, 0x55, 0x44, 0x33, 0x77, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdIntCasts = 15;
LABEL과 OFFSET_OF
일부 요소에 레이블을 할당하고 LABEL(...)
과 OFFSET_OF(...)
구문을 통해 요소의 오프셋을 가져올 수 있다.
UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdWithLabels|{ 0x0A, 0x0B, OFFSET_OF(End), 0x0C, LABEL(Start) 0x0D, LABEL(End) 0x0E, 0x0F, OFFSET_OF(Start) }|VOID*|0xD91A8BF6
빌드 후 AutoGen.c
를 확인하면 아래와 같이 생성된다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdWithLabels[8] = {0x0A, 0x0B, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x04};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdWithLabels = 8;
결합 배열 초기화
다양한 바이트 배열 초기화 방법을 결합할 수 있다.
UefiLessonsPkg/UefiLessonsPkg.dec
에 추가한다.
Copy gUefiLessonsPkgTokenSpaceGuid.PcdArrayExt|{0x11, UINT16(0x2233), UINT32(0x44556677), L"hello", "world!", GUID("09b9b358-70bd-421e-bafb-4f97e2ac7d44")}|VOID*|0x7200C5DF
빌드 후 AutoGen.c
를 통해 확인할 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArrayExt[42] = {0x11, 0x33, 0x22, 0x77, 0x66, 0x55, 0x44, 0x68, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0 0, 0x58, 0xB3, 0xB9, 0x09, 0xBD, 0x70, 0x1E, 0x42, 0xBA, 0xFB, 0x4F, 0x97, 0xE2, 0xAC, 0x7D, 0x44};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayExt = 42;
사용자 지정 타입
PCD에 대한 사용자 지정 타입을 만들 수 있다.
예를 들어 아래 코드로 UefiLessonsPkg/Include/CustomPcdTypes.h
만들었다.
Copy #ifndef CUSTOM_PCD_TYPES_H
#define CUSTOM_PCD_TYPES_H
typedef struct {
EFI_GUID Guid;
CHAR16 Name[ 6 ];
} InnerCustomStruct;
typedef struct {
UINT8 Val8;
UINT32 Val32[ 2 ];
InnerCustomStruct ValStruct;
union {
struct {
UINT8 Field1: 1 ;
UINT8 Field2: 4 ;
UINT8 Filed3: 3 ;
} BitFields;
UINT8 Byte ;
} ValUnion;
} CustomStruct;
#endif
UefiLessonsPkg/UefiLessonsPkg.dec
에 해당 파일을 포함하도록 한다.
생성된 CustomStructure
타입을 사용하고 이 구문을 통해 값을 초기화할 수 있다.
Copy gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct|{0}|CustomStruct|0x535D4CB5 {
<Packages>
UefiLessonsPkg/UefiLessonsPkg.dec
<HeaderFiles>
CustomPcdTypes.h
}
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.Val8|0x11
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.Val32[0]|0x22334455
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.Val32[1]|0x66778899
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.ValStruct.Guid|{GUID("f1740707-691d-4203-bfab-99e132fa4166")}
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.ValStruct.Name|L'Hello'
gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct.ValUnion.BitFields.Field2|0xF
빌드 후 AutoGen.c
를 확인하면 데이터가 생성된 것을 볼 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdCustomStruct[44] = {0x11,0x00,0x00,0x00,0x55,0x44,0x33,0x22,0x99,0x88,0x77,0x66,0x07,0x07,0x74,0xf1,0x1d,0x69,0x03,0x42,0xbf,0xab,0x99,0xe1,0x32,0xfa,0x41,0x66,0x48,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdCustomStruct = 44;
필드를 그룹화하면 모든 필드가 의도한 대로 초기화되었음을 알 수 있다.
Copy {
0x11, // UINT8 Val8
0x00,0x00,0x00, // alignment
0x55,0x44,0x33,0x22, // UINT32 Val32[0]
0x99,0x88,0x77,0x66, // UINT32 Val32[1]
0x07,0x07,0x74,0xf1,0x1d,0x69,0x03,0x42,0xbf,0xab,0x99,0xe1,0x32,0xfa,0x41,0x66, // InnerCustomStruct.Guid
0x48,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x00,0x00, // InnerCustomStruct.Name
0x1e, // ValUnion
0x00,0x00,0x00 // alignment
}
필드별 파일 초기화가 너무 길어 보이면 특수 CODE(...)
구문을 사용하여 C 스타일 배열 초기화를 사용할 수 있다. 그러나 이 경우 GUID(...)
또는 L'...'
초기화와 같은 도우미를 사용할 수 없다. 따라서 구조에 대한 동일한 초기화는 아래와 같다.
Copy gUefiLessonsPkgTokenSpaceGuid.PcdCustomStruct_1|{CODE(
{
0x11,
{0x22334455, 0x66778899},
{
{0xf1740707, 0x691d, 0x4203, {0xbf, 0xab, 0x99, 0xe1, 0x32, 0xfa, 0x41, 0x66}},
{0x0048, 0x0065, 0x006c, 0x006c, 0x006f, 0x0000}
},
{{0x0, 0xf, 0x0}}
}
)}|CustomStruct|0xC1D6B9A7 {
<Packages>
UefiLessonsPkg/UefiLessonsPkg.dec
<HeaderFiles>
CustomPcdTypes.h
}
빌드 후 AutoGen.c
파일을 통해 결과는 같은 것을 볼 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdCustomStruct_1[44] = {0x11,0x00,0x00,0x00,0x55,0x44,0x33,0x22,0x99,0x88,0x77,0x66,0x07,0x07,0x74,0xf1,0x1d,0x69,0x03,0x42,0xbf,0xab,0x99,0xe1,0x32,0xfa,0x41,0x66,0x48,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdCustomStruct_1 = 44;
고정 크기의 배열
PCD 배열의 크기를 구할 수 있다. UINT32[3]
과 같이 크기가 1바이트를 넘는 유형의 배열을 사용하는 경우 모든 초기화 값을 유형에 캐스팅 해야 한다.
이 문제를 방지하기 위해 특수 CODE(...)
를 사용할 수 있다.
Copy [PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdArrayWithFixedSize|{0x0}|UINT8[12]|0x4C4CB9A3
gUefiLessonsPkgTokenSpaceGuid.PcdArrayWithFixedSize_1|{0x0}|UINT32[3]|0x285DAD21
gUefiLessonsPkgTokenSpaceGuid.PcdArrayWithFixedSize_2|{UINT32(0x11223344), UINT32(0x55667788), UINT32(0x99aabbcc)}|UINT32[3]|0x25D6ED26
gUefiLessonsPkgTokenSpaceGuid.PcdArrayWithFixedSize_3|{CODE({0x11223344, 0x55667788, 0x99aabbcc})}|UINT32[3]|0xE5BC424D
AutoGen.c
를 확인하면 아래와 같이 추가된 것을 볼 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArrayWithFixedSize[8] = {0xee,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayWithFixedSize = 8;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArrayWithFixedSize_1[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayWithFixedSize_1 = 12;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArrayWithFixedSize_2[12] = {0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55,0xcc,0xbb,0xaa,0x99};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayWithFixedSize_2 = 12;
GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gPcd_FixedAtBuild_PcdArrayWithFixedSize_3[12] = {0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55,0xcc,0xbb,0xaa,0x99};
GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayWithFixedSize_3 = 12;
사용자 정의 유형에 맞는 고정 크기 배열을 생성할 수도 있다.
Copy gUefiLessonsPkgTokenSpaceGuid.PcdArrayWithFixedSize_4|{0x0}|CustomStruct[2]|0x0D00EE44 {
<Packages>
UefiLessonsPkg/UefiLessonsPkg.dec
<HeaderFiles>
CustomPcdTypes.h
}
여기서는 필드 초기화를 수행하지 않지만 구문 증명을 위해 AutoGen.c
를 보고 최종 데이터 배열의 크기가 일반적인 구조의 두 배인지 확인할 수 있다.
Copy GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gPcd_FixedAtBuild_Size_PcdArrayWithFixedSize_4 = 88;
PcdValueInit
사용자 지정 유형 또는 고정 크기 배열과 함께 PCD를 사용할 경우 빌드 시스템은 빌드 폴더에 PcdValueInit
폴더를 생성한다. 이 폴더에는 빌드 시스템이 AutoGen.c
파일의 데이터를 가져오는 데 사용할 특별한 C 프로그램 PcdValueInit
이 포함된다.
Copy $ find ./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueCommon.c
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueInit.o
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueInit.c
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueInit
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/Input.txt
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueInit.d
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueCommon.d
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/Output.txt
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueCommon.o
./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/Makefile
프로그램의 도움말 메시지를 확인할 수 있다.
Copy $ ./Build/UefiLessonsPkg/RELEASE_GCC5/PcdValueInit/PcdValueInit -h
Usage: -i <input_file> -o <output_file>
optional arguments:
-h, --help Show this help message and exit
-i INPUT_FILENAME, --input INPUT_FILENAME
PCD Database Input file name
-o OUTPUT_FILENAME, --output OUTPUT_FILENAME
PCD Database Output file name
이를 통해 이 프로그램은 동일한 폴더의 input.txt
파일에서 output.txt
파일을 생성한다고 추측할 수 있다. 빌드 시스템 내부에 대해 궁금한 점이 있으면 *.txt
파일을 확인하거나 프로그램 소스를 확인한다.