In this lesson we are going to look at the PCD override capability.
Create new UINT32
PCD with a name PcdInt32Override
and a default value equal to 42 (UefiLessonsPkg/UefiLessonsPkg.dec
):
[PcdsFixedAtBuild]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|42|UINT32|0x3CB8ABB8
Now when we would populate the PCD to our application via the INF file (UefiLessonsPkg/PCDLesson/PCDLesson.inf
), we would use the PCD override syntax to change the default value of our PCD, which looks like this:
[FixedPcd]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|43
If you build our application now, and look at the Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
, you would see that PcdInt32Override
default value was overriden:
...
#define _PCD_VALUE_PcdInt32Override 43U
...
You can even add a print statement to the UefiLessonsPkg/PCDLesson/PCDLesson.c
to verify the result:
Print(L"PcdInt32Override=%d\n", FixedPcdGet32(PcdInt32Override));
If you rebuild the application and execute it under OVMF you would get:
FS0:\> PCDLesson.efi
...
PcdInt32Override=43
So it means that every App/Driver can override a PCD declared in *.dec
file differently.
Besides overwriting PCDs locally in every module it is possible to override PCDs globally in the package via its DSC file.
Don't delete our INF override but another one in the DSC file (UefiLessonsPkg/UefiLessonsPkg.dsc
). In this case we would override the default value to 44:
[PcdsFixedAtBuild]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
If you build the app and execute in under OVMF now you would get:
FS0:\> PCDLesson.efi
...
PcdInt32Override=44
So as you can see there is some order of precedence for the override statments:
DEC < INF < DSC
- Declaration file (DEC) declares PCD with its default value
- Every App/Driver Information file (INF) can override the value of this PCD differently
- However a package description file that contains all these Apps/Drivers (DSC) can override this PCD for all of them
It is important to note that the DSC file in this case means a DSC file of the package that we build. And it is not necessary the same as the DSC file of the module origin package.
For the proof let's build our module as a part of the OvmfPkg/OvmfPkgX64.dsc
package. For this add our application to the [Components]
section in the OvmfPkg/OvmfPkgX64.dsc
file:
[Components]
...
UefiLessonsPkg/PCDLesson/PCDLesson.inf
Now build the OVMF image:
build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5
The image of our application in this case would be not at the usual Build/UefiLessonsPkg/RELEASE_GCC5/X64/PCDLesson.efi
path, but at the path
Build/OvmfX64/RELEASE_GCC5/X64/PCDLesson.efi
So if you copy this .efi
file to our shared disk and execute it under OVMF image, you would get:
FS0:\> PCDLesson.efi
...
PcdInt32Override=43
As you can see the override from the UefiLessonsPkg/UefiLessonsPkg.dsc
file doesn't work in this case.
For the DSC override you need to modify the DSC of the package that we build, i.e. OvmfPkg/OvmfPkgX64.dsc
file:
[PcdsFixedAtBuild]
...
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|45
Rebuild OVMF image, copy updated application to the shared folder, and verify that now DSC override is working correctly:
FS0:\> PCDLesson.efi
...
PcdInt32Override=45
When we've added our application to the [Components]
section in the OvmfPkg/OvmfPkgX64.dsc
we said that we want to compile our application as part of the package. If we want to include our application to the final OVMF flash image we need to add it to the FDF
file. We won't go into details of how it is done right now, just add the INF UefiLessonsPkg/PCDLesson/PCDLesson.inf
statement to the end of [FV.DXEFV]
setion:
[FV.DXEFV]
...
INF UefiLessonsPkg/PCDLesson/PCDLesson.inf
#################################################
Important part for us now is that in the same FDF file we can override our PCD via the SET
syntax. First put it in the [Defines]
section:
[Defines]
...
SET gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override = 46
...
Rebuild and verify the override result:
FS0:\> PCDLesson.efi
...
PcdInt32Override=46
Now add another SET
statement to the section of our module (which is [FV.DXEFV]
in our case):
[FV.DXEFV]
...
INF UefiLessonsPkg/PCDLesson/PCDLesson.inf
SET gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override = 47
#################################################
This override should take precedence over the general one in the [Defines]
section:
FS0:\> PCDLesson.efi
...
PcdInt32Override=47
The next level of PCD override is the DSC in-module overrides. The override syntax in this case looks like this:
[Components]
...
UefiLessonsPkg/PCDLesson/PCDLesson.inf {
<PcdsFixedAtBuild>
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|48
}
This override would take precedence over the ones in the FDF file:
FS0:\> PCDLesson.efi
...
PcdInt32Override=48
Finally it is possible to override PCD via a command-line argument to the build
command, for example:
build --platform=OvmfPkg/OvmfPkgX64.dsc \
--arch=X64 \
--buildtarget=RELEASE \
--tagname=GCC5 \
--pcd="gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override=49"
Verify the override via our print statement:
FS0:\> PCDLesson.efi
...
PcdInt32Override=49
In this lesson we've investgated some of the precedence rules of the PCD override.
The complete documentation on the subject can be found at this link https://edk2-docs.gitbook.io/edk-ii-dsc-specification/2_dsc_overview/27_pcd_section_processing#2.7.3.8-precedence