Skip to content

Latest commit

 

History

History

Lesson_24

All the PCD types that we've investigated so far are local to the module. PcdsFixedAtBuild and PcdsFeatureFlag are simple defines and PcdsPatchableInModule is just a local variable. It is not possible to pass information BETWEEN modules with these PCDs. I'm talking about situations where one module updates PCD and another module reads its value. It would be very usefull to have such functionality in a complete UEFI firmware image. Fortunately there is another class of PCDs that can help to solve this issue. This class is called PcdsDynamic. Let's think for a minute. Where would we store these PCD values? They belong to the platform (all modules), but not one particular module. Thus we need some common database in a platfrom with a known interface, that all the modules can access. Also we need to construct initial values for this database by reading all the dynamic PCD settings in the DEC/INF/DSC files.

The common PCD database modules are presented here https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Universal/PCD. As we need to have an access to the PCD database both in PEI and DXE stages there are two of them: one for PEI stage https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Universal/PCD/Pei and one for the DXE stage https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Universal/PCD/Dxe.

To get the functionality of the dynamic PCDs platfrom intergator needs to include these modules in the final image and load them at the very start of their stages. As usually we would use OVMF platfrom in our experiments, and it has these modules included.

Now the fun part - let's look at the PCD database files, that are created as a result of parsing of all DEC/INF/DSC in a platfrom.

You can find these files under the paths:

  • Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/OUTPUT/PEIPcdDataBase.raw
  • Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/OUTPUT/DXEPcdDataBase.raw

They are created because the modules have these defines in their INF files: https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Pei/Pcd.inf

[Defines]
  ...
  PCD_IS_DRIVER                  = PEI_PCD_DRIVER

https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

[Defines]
  ...
  PCD_IS_DRIVER                  = DXE_PCD_DRIVER

The PEI PCD database file includes PCDs that are used only in PEI modules or both in PEI and DXE modules. The DXE PCD database file includes PCDs that are used only in DXE modules. But the PEI database module can access only its own database, and the DXE database module is able to access both databases. This way we have only the necessary PCDs in the PEI stage and all of them in the DXE stage without any duplication. Keeping only the necessary PCDs in the PEI stage is done for the optimization. As in the PEI stage we need to reduce memory footprint as much as possible.

[PEI|DXE]PcdDataBase.raw format

You can look at the content of these files with a help of a hexdump utility:

$ hexdump Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/OUTPUT/PEIPcdDataBase.raw -C
00000000  3c 19 7d 3c 2c 68 14 4c  a6 8f 55 2d ea 4f 43 7e  |<.}<,h.L..U-.OC~|
00000010  07 00 00 00 f8 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  f8 00 00 00 60 00 00 00  84 00 00 00 6c 00 00 00  |....`.......l...|
00000030  dc 00 00 00 f0 00 00 00  f2 00 00 00 50 00 00 00  |............P...|
00000040  00 00 00 00 16 00 03 00  01 00 da da da da da da  |................|
00000050  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 08 00 00 00  40 00 00 00 05 00 03 00  |........@.......|
00000070  14 00 00 00 04 00 03 00  15 00 00 00 06 00 03 00  |................|
00000080  16 00 00 00 54 01 10 01  f8 00 00 08 00 01 00 08  |....T...........|
00000090  08 01 00 08 10 01 00 08  55 01 10 01 48 01 00 04  |........U...H...|
000000a0  4c 01 00 04 68 00 00 04  56 01 10 01 50 01 00 02  |L...h...V...P...|
000000b0  18 01 00 08 20 01 00 08  28 01 00 08 30 01 00 08  |.... ...(...0...|
000000c0  38 01 00 08 60 00 00 08  57 01 10 01 f6 00 00 02  |8...`...W.......|
000000d0  ec 00 00 10 52 01 00 02  40 01 00 08 49 f0 af a1  |[email protected]...|
000000e0  eb fd 2a 44 b3 20 13 ab  4c b7 2b bc 00 00 00 00  |..*D. ..L.+.....|
000000f0  00 00 01 00 01 00 08 00                           |........|
000000f8

$ hexdump Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/OUTPUT/DXEPcdDataBase.raw -C
00000000  3c 19 7d 3c 2c 68 14 4c  a6 8f 55 2d ea 4f 43 7e  |<.}<,h.L..U-.OC~|
00000010  07 00 00 00 e0 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  e0 00 00 00 2e 00 00 00  78 00 00 00 70 00 00 00  |........x...p...|
00000030  c0 00 00 00 d0 00 00 00  d1 00 00 00 50 00 00 00  |............P...|
00000040  00 00 00 00 12 00 00 00  01 00 da da da da da da  |................|
00000050  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  80 02 00 00 e0 01 00 00  20 03 00 00 58 02 00 00  |........ ...X...|
00000070  00 00 00 00 00 00 00 00  00 01 00 04 04 01 00 04  |................|
00000080  e0 00 00 08 e8 00 00 08  f0 00 00 08 60 00 00 04  |............`...|
00000090  64 00 00 04 0a 01 00 01  d5 00 00 02 0b 01 10 01  |d...............|
000000a0  68 00 00 04 6c 00 00 04  08 01 00 02 d7 00 00 01  |h...l...........|
000000b0  d8 00 00 01 f8 00 00 08  0c 01 10 01 0d 01 10 01  |................|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  00 00 00 00 00 08 02 01  01 da da da da da da da  |................|
000000e0

These databases start with a header struct which is defined in the https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Guid/PcdDataBaseSignatureGuid.h

typedef struct {
  GUID            Signature;                    // PcdDataBaseGuid.
  UINT32          BuildVersion;
  UINT32          Length;                       // Length of DEFAULT SKU PCD DB
  SKU_ID          SystemSkuId;                  // Current SkuId value.
  UINT32          LengthForAllSkus;             // Length of all SKU PCD DB
  UINT32          UninitDataBaseSize;           // Total size for PCD those default value with 0.
  TABLE_OFFSET    LocalTokenNumberTableOffset;
  TABLE_OFFSET    ExMapTableOffset;
  TABLE_OFFSET    GuidTableOffset;
  TABLE_OFFSET    StringTableOffset;
  TABLE_OFFSET    SizeTableOffset;
  TABLE_OFFSET    SkuIdTableOffset;
  TABLE_OFFSET    PcdNameTableOffset;
  UINT16          LocalTokenCount;              // LOCAL_TOKEN_NUMBER for all.
  UINT16          ExTokenCount;                 // EX_TOKEN_NUMBER for DynamicEx.
  UINT16          GuidTableCount;               // The Number of Guid in GuidTable.
  UINT8           Pad[6];                       // Pad bytes to satisfy the alignment.
} PCD_DATABASE_INIT;

Let's investigate fields of this structure:

Signature

GUID            Signature;

The first field is GUID, and it gets assigned to the:

#define PCD_DATA_BASE_SIGNATURE_GUID \
{ 0x3c7d193c, 0x682c, 0x4c14, { 0xa6, 0x8f, 0x55, 0x2d, 0xea, 0x4f, 0x43, 0x7e } }

If you look at the hexdumpoutputs, you'll see how they start with this value. The PCD database code would check this value to verify that the data is indeed the PCD database file.

Build version

UINT32          BuildVersion;

The format of the PCD database can change through edk2 development. If it changes, we need to increment BuildVersion value. The current version is 7. Off course the PEI PCD DB module, DXE PCD DB module and the build tools all need to be synchronized at this part. The DB module code verifies that it is true:

https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Pei/Service.h

/
// Please make sure the PCD Serivce PEIM Version is consistent with
// the version of the generated PEIM PCD Database by build tool.
//
#define PCD_SERVICE_PEIM_VERSION  7

//
// PCD_PEI_SERVICE_DRIVER_VERSION is defined in Autogen.h.
//
#if (PCD_SERVICE_PEIM_VERSION != PCD_PEI_SERVICE_DRIVER_VERSION)
  #error "Please make sure the version of PCD PEIM Service and the generated PCD PEI Database match."
#endif

https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Dxe/Service.h

//
// Please make sure the PCD Serivce DXE Version is consistent with
// the version of the generated DXE PCD Database by build tool.
//
#define PCD_SERVICE_DXE_VERSION  7

//
// PCD_DXE_SERVICE_DRIVER_VERSION is defined in Autogen.h.
//
#if (PCD_SERVICE_DXE_VERSION != PCD_DXE_SERVICE_DRIVER_VERSION)
  #error "Please make sure the version of PCD DXE Service and the generated PCD DXE Database match."
#endif

For example of a version change look at this commit https://github.com/tianocore/edk2/commit/7c73626513238176bdd16dca14fcf3f9e10bcc81 that have updated version from 6 to 7.

Length

UINT32          Length;
UINT32          UninitDataBaseSize;

Some PCDs in the end of edk2 build calculation would be equal to 0. There can be a lot of such PCDs and it is not optimal to store them all in a flash image. Therefore in the *.rawimage we would store only the non-zero PCDs. And Length signifies the size of this image:

|.........| 0
|.........|
|.........|
___________ Length

But when we are actually working with PCDs in PEI/DXE DB modules, we need for all of the PCDs to actually be present in memory, as we can assign values to them. And with a help of UninitDataBaseSize field we know how much space do we need to reserve for this:

|.........| 0
|.........|
|.........|
___________ Length
|000000000|
|000000000|
|000000000|
___________ Length + UninitDataBaseSize

LocalTokenNumberTable

TABLE_OFFSET    LocalTokenNumberTableOffset;
...
UINT16          LocalTokenCount;

This is the most important part of the table. TABLE_OFFSET is just a UINT32 value - offset to the LocalToken table which has LocalTokenCount records. Each record (=LocalToken) is a UINT32 value. It can be represented like this:

union {
  UINT32 LocalToken;
  struct {
    UINT32 pcd_type : 4;
    UINT32 pcd_datum_type : 8;
    UINT32 offset : 20;
  }
}

-pcd_type - type of the PCD. Yes, there can be multiple classes of PCD, we'll get to that later. The PCD can be DATA, HII or VPD -pcd_datum_type - type of the data in the PCD (UINT8, UINT16, UINT32, UINT64, VOID*) -offset - offset to the initial data of this PCD in the Database image

The Local tokens are implicitly numbered from 1. And when some firmware module wants to work with a PCD it communicates with a database saying "Hey, I want to get/set PCD at the local token №xxx". The PCD database reads this local token and then interprets actual data at the offset field depending on the values pcd_type and pcd_datum_type. This is how [PcdsDynamic] work.

It is important to note that the numbering is sequential for PEI and DXE databases. That means that local tokens in the PEI database are assumed to have numbers 1 .. (PEI_DB.LocalTokenCount) and local tokens in the DXE database are assumed to have numbers (PEI_DB.LocalTokenCount + 1) .. (PEI_DB.LocalTokenCount + 1 + DXE_DB.LocalTokenCount).

ExMapTable and GuidTable. The necessity of [PcdsDynamic] and [PcdsDynamicEx]

TABLE_OFFSET    ExMapTableOffset;
TABLE_OFFSET    GuidTableOffset;
UINT16          ExTokenCount;
UINT16          GuidTableCount;

It is easy to reference PCDs by the local token number. But for that we actually need to know the mapping PCD<-->LocalToken. And we do, when we build our module and PCD database at the same time as parts of the flash image (OVMF in our case). But sometimes flash image is already built and we are writing a separate module that needs to use some of the image PCDs. For this case EDKII offers us [PcdsDynamicEx] mechanics. In this case we reference dynamic PCDs by a combination GUID+ExTokenNumber. ExTokenNumber in this case is just a UINT32 and both values must be unique for every PCD. When PCD database receives request for GUID+ExTokenNumber it first verifies if the GUID is present in the database. There are totally GuidTableCount guids in the database and they are placed starting form the GuidTableOffset in the database file. If the requested GUID is equal to some GUID in the database we remember the index of this GUID. After that the code looks at the records in the ExMapTable which is present under ExMapTableOffset. There are totally ExTokenCount records and each record has the format:

typedef struct  {
  UINT32    ExTokenNumber;
  UINT16    TokenNumber;        // local token index in the LocalTokenNumberTable
  UINT16    ExGuidIndex;        // GUID index in the GuidTable
} DYNAMICEX_MAPPING;

If some record has the requested ExTokenNumber and ExGuidIndex that correspond to the requested GUID, we've found our LocalToken number. The rest goes exactly like in the [PcdsDynamic] case. And as you can deduct ExTokenCount always less or equal than LocalTokenCount.

StringTable and SizeTable

TABLE_OFFSET    StringTableOffset;
TABLE_OFFSET    SizeTableOffset;

When the Database code needs to return a PCD value, beside the offset it needs to know the PCD size. For the simple data types the size fixed. For example if the PCD has a pcd_datum_type type UINT64 the size of the PCD data is 8 bytes. But PCD data can be a structure or a string. In this cases offset in the Local token interpreted as an index to the StringTable with is present under the StringTableOffset. This table consists of UINT32 values - actual offsets to the data. Size of the data in this case is written in the SizeTable which is present under the SizeTableOffset and consists of an elements like this:

struct {
  UINT16 MaxSize;
  UINT16 CurrentSize;
}

Once again the numbering is implicit. For our target local token we need to inspect LocalTokenNumberTable from the start and calculate how many String/Pointer PCDs were before our target local token, and this value would be an index of the SizeTable record.

AutoGen files

Based on the previous section you can see that it is not easy to parse database content. Fortunately EDKII provide some help for us in the AutoGen files. For example this content is written in the PEI PCD DB AutoGen files:

Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/DEBUG/AutoGen.h:

//
// External PCD database debug information
//
#if 0
#define PEI_GUID_TABLE_SIZE                1U
#define PEI_STRING_TABLE_SIZE              2U
#define PEI_SKUID_TABLE_SIZE               1U
#define PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE  22
#define PEI_LOCAL_TOKEN_NUMBER             22
#define PEI_EXMAPPING_TABLE_SIZE           3U
#define PEI_EX_TOKEN_NUMBER                3U
#define PEI_SIZE_TABLE_SIZE                2U
#define PEI_GUID_TABLE_EMPTY               FALSE
#define PEI_STRING_TABLE_EMPTY             FALSE
#define PEI_SKUID_TABLE_EMPTY              TRUE
#define PEI_DATABASE_EMPTY                 FALSE
#define PEI_EXMAP_TABLE_EMPTY              FALSE

typedef struct {
  ...
} PEI_PCD_DATABASE_INIT;

typedef struct {
  ...
} PEI_PCD_DATABASE_UNINIT;

typedef struct {
  PEI_PCD_DATABASE_INIT    Init;
  PEI_PCD_DATABASE_UNINIT  Uninit;
} PEI_PCD_DATABASE;
#endif

Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/DEBUG/AutoGen.c:

//
// External PCD database debug information
//
#if 0
PEI_PCD_DATABASE_INIT gPEIPcdDbInit = {
  ...
};
#endif

You can find the content of your PCDs with comments inside the PEI_PCD_DATABASE_INIT/PEI_PCD_DATABASE_UNINIT structures. As you can see all the code is not included in the build (in is under the #if 0 .. #endif), so all of these is just a help message for the developer.

The similar comment you can find in the DXE PCD DB AutoGen files:

  • Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/AutoGen.h
  • Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/DEBUG/AutoGen.c

PCD_TABLE_parser

Information in AutoGen files is fine, but sometimes it is kinda hard to search it. For this case I've created a PCD_TABLE_parser utility.

Clone it and build:

$ git clone https://github.com/Kostr/PCD_TABLE_parser.git ~/PCD_TABLE_parser
$ cd ~/PCD_TABLE_parser
$ make
cc    -c -o main.o main.c
cc    -c -o guids.o guids.c
cc    -c -o utils.o utils.c
gcc main.o guids.o utils.o -o parse_pcd_db

Look at the help message:

$ ./parse_pcd_db --help
Usage: parse_pcd_db [--peidb <PEI_PCD_DB.raw>] [--dxedb <DXE_PCD_DB.raw>] [--vpd <VPD.bin>]
Program to parse PCD Database raw files

--peidb <PEI_PCD_DB.raw>     - provide PEI PCD database
--dxedb <DXE_PCD_DB.raw>     - provide DXE PCD database
--vpd   <VPD.bin>            - provide VPD binary

Example:
parse_pcd_db \
 --peidb "Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/OUTPUT/PEIPcdDataBase.raw" \
 --dxedb "Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/OUTPUT/DXEPcdDataBase.raw" \
 --vpd   "Build/OvmfX64/RELEASE_GCC5/FV/8C3D856A-9BE6-468E-850A-24F7A8D38E08.bin"

Don't mind the --vpd option right now. Let's launch the program giving it just --peidb and --dxedb arguments. Also you would probably want to pipe the output to less.

$ parse_pcd_db \
 --peidb "Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/OUTPUT/PEIPcdDataBase.raw" \
 --dxedb "Build/OvmfX64/RELEASE_GCC5/X64/MdeModulePkg/Universal/PCD/Dxe/Pcd/OUTPUT/DXEPcdDataBase.raw" | less

Here is an example output. I think it is more illustrative to the PCD table description that we've just covered. Some comments for the output:

  • you can see the sequential numbering between PEI and DXE databases
  • the 0 - unitialized means the PCD is in the Length .. (Length + UninitDataBaseSize) area
  • only some PCDs have DynamicEx Token/GUID information - these are PCDs that are declared via PcdsDynamicEx method
  • the PCDs of the pointer type has Size info
PEI PCD DB
LocalTokenNumberTable:

1:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

2:
Token type = Data
Datum type = UINT64
0 - unitialized

3:
Token type = Data
Datum type = UINT64
0 - unitialized

4:
Token type = Data
Datum type = UINT64
0 - unitialized

5:
Token type = Data
Datum type = UINT64
0 - unitialized

6:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

7:
Token type = Data
Datum type = UINT32
0 - unitialized

8:
Token type = Data
Datum type = UINT32
0 - unitialized

9:
Token type = Data
Datum type = UINT32
Value:
0x00000040 (=64)

10:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

11:
Token type = Data
Datum type = UINT16
0 - unitialized

12:
Token type = Data
Datum type = UINT64
0 - unitialized

13:
Token type = Data
Datum type = UINT64
0 - unitialized

14:
Token type = Data
Datum type = UINT64
0 - unitialized

15:
Token type = Data
Datum type = UINT64
0 - unitialized

16:
Token type = Data
Datum type = UINT64
0 - unitialized

17:
Token type = Data
Datum type = UINT64
Value:
0x0000000800000000 (=34359738368)

18:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

19:
Token type = Data
Datum type = UINT16
Value:
0x0008 (=8)

20:
Token type = String
Datum type = Pointer
DynamicEx Token = 0x00030005
DynamicEx GUID  = a1aff049-fdeb-442a-b32013ab4cb72bbc [gEfiMdeModulePkgTokenSpaceGuid]
CurrentSize = 1
MaxSize     = 1
Value:
00                                               | .

21:
Token type = Data
Datum type = UINT16
DynamicEx Token = 0x00030004
DynamicEx GUID  = a1aff049-fdeb-442a-b32013ab4cb72bbc [gEfiMdeModulePkgTokenSpaceGuid]
0 - unitialized

22:
Token type = Data
Datum type = UINT64
DynamicEx Token = 0x00030006
DynamicEx GUID  = a1aff049-fdeb-442a-b32013ab4cb72bbc [gEfiMdeModulePkgTokenSpaceGuid]
0 - unitialized
_____

DXE PCD DB
LocalTokenNumberTable:

23:
Token type = Data
Datum type = UINT32
0 - unitialized

24:
Token type = Data
Datum type = UINT32
0 - unitialized

25:
Token type = Data
Datum type = UINT64
0 - unitialized

26:
Token type = Data
Datum type = UINT64
0 - unitialized

27:
Token type = Data
Datum type = UINT64
0 - unitialized

28:
Token type = Data
Datum type = UINT32
Value:
0x00000280 (=640)

29:
Token type = Data
Datum type = UINT32
Value:
0x000001e0 (=480)

30:
Token type = Data
Datum type = UINT8
0 - unitialized

31:
Token type = Data
Datum type = UINT16
Value:
0x0208 (=520)

32:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

33:
Token type = Data
Datum type = UINT32
Value:
0x00000320 (=800)

34:
Token type = Data
Datum type = UINT32
Value:
0x00000258 (=600)

35:
Token type = Data
Datum type = UINT16
0 - unitialized

36:
Token type = Data
Datum type = UINT8
Value:
0x01 (=1)

37:
Token type = Data
Datum type = UINT8
Value:
0x01 (=1)

38:
Token type = Data
Datum type = UINT64
0 - unitialized

39:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized

40:
Token type = Data
Datum type = UINT8 (Bool)
0 - unitialized
_____

UEFITool

Let's imagine a situation where we want to look at the PCD DB content in the binary UEFI image.

https://github.com/LongSoft/UEFITool. You can download and compile it from the source code, or just download precompiled image from the releases page https://github.com/LongSoft/UEFITool/releases.

When you load the program it looks like this: UEFITool

Let's open UEFI firmware file Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd via File->Open image file... menu option. UEFITool_1

Now you can investigate the OVMF.fd image content by unfolding/folding image sections. For this you need to click on the '>' symbols.

But right now we need to find PEI/DXE PCD databases in the image. As you might remember each database starts from the signature GUID:

#define PCD_DATA_BASE_SIGNATURE_GUID \
{ 0x3c7d193c, 0x682c, 0x4c14, { 0xa6, 0x8f, 0x55, 0x2d, 0xea, 0x4f, 0x43, 0x7e } }

Therefore use Action->Search... menu option and input this value in the GUID tab: UEFITool_2

The program should find two Raw sections. If you click on the first result, program would show you where this section is placed in the image. You can see that it is placed under the PcdPeim module. This is the module name of the https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Pei/Pcd.inf file. At the Information panel on the right you could see that Body size: F8h (248). This is the actual size of the section which is equal to the size the we saw with hexdump.

UEFITool_3

You can save the section data if you right-click on the section name and select Extract body.... By default the program would suggest Section_Raw_PcdPeim_PcdPeim_body.raw name for the new file. UEFITool_4

Now you can check the second result of our search. This section is inside the PcdDxe module https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf. The Body size: E0h (224) is once again corresponds to the hexdump output size. For the body of this section the program would suggest the Section_Raw_PcdDxe_PcdDxe_body.raw name. UEFITool_5

Now we have both databases, and we can parse them with our parse_pcd_db utility. Save the extracted files to the home folder and execute the program:

$ ./parse_pcd_db \
 --peidb ~/Section_Raw_PcdPeim_PcdPeim_body.raw \
 --dxedb ~/Section_Raw_PcdDxe_PcdDxe_body.raw

The output should be the same as before.

Links