After you've written you application code in C you need to compile it for the target CPU architecture.
EDKII supports compilation for several CPU architectures. You can see the complete list if you look at the output of the build --help
command:
$ build --help
...
Options:
...
-a TARGETARCH, --arch=TARGETARCH
ARCHS is one of list: IA32, X64, ARM, AARCH64, RISCV64
or EBC, which overrides target.txt's TARGET_ARCH
definition. To specify more archs, please repeat this
option.
...
The abbreviations above mean:
IA32 - x86 32bit
X64 - x86 64bit
ARM - ARM 32bit
AARCH64 - ARM 64bit
RISCV64 - RISCV 64bit
EBC - EFI Byte Code
As we use qemu-system-x86_64
virualization tool, we've compiled our applications for the X64
architecture.
In our first application examples we did it via an argument to the build
command:
build ... --arch=X64 ...
Later we've constructed the Conf/target.txt
file, so we could call the build
command without any arguments. In this file we've indicated the target arch by setting the TARGET_ARCH
define:
`TARGET_ARCH = X64`
Let's try to build our code for the x86 32bit (IA32
) architecture.
To do this we can override default argument (which comes from the Conf/target.txt
) via a command argument:
build --arch=IA32
If you try to do it right now, you'll get the error:
build.py...
: error 2000: Invalid parameter
Invalid ARCH specified. [Valid ARCH: X64]
- Failed -
This is happening because IA32
architecture is not present in the architecture whitelist in our DSC file UefiLessonsPkg/UefiLessonsPkg.dsc
:
[Defines]
...
SUPPORTED_ARCHITECTURES = X64
To correct this modify SUPPORTED_ARCHITECTURES
to the following value:
[Defines]
...
SUPPORTED_ARCHITECTURES = IA32|X64
Now the build via build --arch=IA32
should succeed. The results will be in the same Build/UefiLessonsPkg/RELEASE_GCC5/
folder. But now along with the X64
subfolder there would be the IA32
subfolder.
You can verify that the generated application indeed are different via the Linux file
command:
$ file Build/UefiLessonsPkg/RELEASE_GCC5/X64/PCDLesson.efi
Build/UefiLessonsPkg/RELEASE_GCC5/X64/PCDLesson.efi: MS-DOS executable PE32+ executable (EFI application) x86-64, for MS Windows
$ file Build/UefiLessonsPkg/RELEASE_GCC5/IA32/PCDLesson.efi
Build/UefiLessonsPkg/RELEASE_GCC5/IA32/PCDLesson.efi: MS-DOS executable PE32 executable (EFI application) Intel 80386, for MS Windows
In our UefiLessonsPkg/UefiLessonsPkg.dsc
file we have an override for the PcdInt32Override
PCD:
[PcdsFixedAtBuild]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
This override works for both X64
and IA32
builds:
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 44U
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/IA32/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 44U
It is possible to set override for the particular architecture. For example change the section name to the:
[PcdsFixedAtBuild.IA32]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
Regenerate both builds and verify the PCD values:
$ build && build --arch=IA32
...
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 43U
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/IA32/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 44U
It is possible to have both the generic arch section and the qualified one:
[PcdsFixedAtBuild.IA32]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|45
[PcdsFixedAtBuild]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
In this case X64
arch PCD would get its value from the generic override, and IA32
arch PCD would get its value from the qualified section. The order of sections is not important in this case:
$ build && build --arch=IA32
...
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 44U
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/IA32/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 45U
It is worth to notice that it is possible to provide different section names as a list, for example:
[PcdsFixedAtBuild.IA32, PcdsFixedAtBuild.X64]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|45
In this case the override would be applied for the X64
and IA32
builds, but not for the ARM
build for example (if we would ever want to permit one).
Keep and mind that currently you can write any name in the arch section name qualifier. EDKII doesn't perform any checks on this matter:
[PcdsFixedAtBuild.IA32]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|45
[PcdsFixedAtBuild.blablabla]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
Off course in this case the X64
PCD wouldn't get its override to the 44 value:
$ build && build --arch=IA32
...
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 43U
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/IA32/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 45U
So don't confuse IA32
with X32
or something like that. You woudn't see any error, but you'll get incorrect values.
As we will know next, there are many layers to the section name override (e.g. [PcdsFixedAtBuild.XXX.YYY.ZZZ]
). If you want to override second layer but want to keep the first one as generic, you use common
for indication that the override goes to any architecture. For example this override:
[PcdsFixedAtBuild.IA32]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|45
[PcdsFixedAtBuild.common]
gUefiLessonsPkgTokenSpaceGuid.PcdInt32Override|44
Will give you the same results as with the [PcdsFixedAtBuild.IA32]/[PcdsFixedAtBuild]
sections:
$ build && build --arch=IA32
...
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 44U
$ grep _PCD_VALUE_PcdInt32Override Build/UefiLessonsPkg/RELEASE_GCC5/IA32/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
#define _PCD_VALUE_PcdInt32Override 45U
But with a help of a common
syntax you can construct overrides for other build aspects like [PcdsFixedAtBuild.common.XXX]
.
In the example above we've used arch section name override for the [PcdsFixedAtBuild]
section in the DSC file. But it is also to possible to override other sections in other EDKII metafiles (DEC/INF/FDF), for example:
[PcdsPatchableInModule.X64]
[PcdsDynamic.X64]
[Protocols.X64]
[LibraryClasses.X64]
[Components.X64]
[BuildOptions.X64]
[Guids.X64]
[Sources.X64]
[Includes.X64]
[Defines.X64]
[Depex.X64]
[Pcd.X64]
You should consult EDKII documentation for the particular metafile (DEC/INF/DSC/FDF), but generally almost every section name can be overriden with the ARCH qualifier. And the ARCH override would always be the first qualifier one in section naming.