<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@vertical+block@6bef04b7622b4df2bd7e56cd8b077609" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@markdown+block@7a617a7f6f0648299d14ad7a5cd4cff1">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@markdown+block@7a617a7f6f0648299d14ad7a5cd4cff1" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>In the development preparation section we built EDKII the first time using the <code>./build.sh</code> script for the OVMF package. Now it is time to dive deeper into the EDKII build process and understand what happened behind the scenes.</p>
<h2>How to get documentation of EDKII build process</h2>
<p>The most recent documentation of the EDKII build process is stored as code in the TianoCore Documentation respository called <a href="https://github.com/tianocore-docs/edk2-BuildSpecification">edk2-BuildSpecification</a>.</p>
<p>The easiest way to explore it is to download an already generated PDF file, for example, available at Tianocore's github repository, together with all other documenations. Specifically in the tianocore/tianocore.github.io repository's wiki. The document we are looking for is <a href="https://tianocore-docs.github.io/edk2-BuildSpecification/release-1.28/edk2-BuildSpecification-release-1.28.pdf">here</a>.</p>
<p>Other way to explore it, without installing lot of dependencies or using gitbook, would be cloning repository and hosting a local HTTP server:</p>
<div class="codehilite">
<pre><span></span><code>git clone https://github.com/tianocore-docs/edk2-BuildSpecification.git
<span class="nb">cd</span> edk2-BuildSpecification
git checkout gh-pages
python3 -m http.server
</code></pre>
</div>
<p>Then open <code>0.0.0.0:8000</code> in web browser.</p>
<h2>Key environment variables</h2>
<ul>
<li><code>WORKSPACE</code> - environment variable which keeps the name of the directory in which the build process is performed</li>
<li><code>PACKAGES_PATH</code> - environment variable which keeps package search paths. Searching always uses the first match, where <code>WORKSPACE</code> is first directory to be searched</li>
<li><code>EDK_TOOLS_PATH</code> - environment was already discussed, but it points to the <code>BaseTools</code> and <code>Conf</code> directories which contain build tools and their configuration</li>
</ul>
<p>The EDKII build system supports Windows, Linux, macOS, and various compilers. You may check <code>./BaseTools/Conf/tools_def.template</code> to see what development environments are supported.
Please note that despite the huge number of environments not all of them work out-of-the-box.</p>
<p>To simplify environment variables setup, EDKII provides the <code>edksetup.sh</code> script for UNIX-like environments. To use it type:</p>
<div class="codehilite">
<pre><span></span><code><span class="nb">source</span> edksetup.sh
</code></pre>
</div>
<h2>Key file extensions</h2>
<ul>
<li><code>INF</code> - EDKII build information (INF) file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-inf-specification/v/release-1.27/">edk2-InfSpecification (1.27)</a>. This file is used to describe various modules whether they are derived from binaries, source, or mixed. It also describes the intermediate product of the EDKII build system. This file format is a fundamental component of build system, since it describes the most basic units of EDKII - modules.</li>
<li><code>DEC</code> - EDKII Package Declaration (DEC) file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-dec-specification/v/release-1.27-3/">edk2-DecSpecification (1.27-3)</a>. This file declares information about what is provided in the package. An EDKII package is a collection of like content.</li>
<li><code>DSC</code> - EDKII Platform Description (DSC) file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-dsc-specification/v/release-1.28-2/">edk2-DscSpecification (1.28-2)</a>. This file describes what and how modules, libraries and components are to be built, as well as defining library instances which will be used when linking EDKII modules.</li>
<li><code>FDF</code> - EDKII Flash Description (FDF) file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-fdf-specification/v/release-1.28.01/">edk2-FdfSpecification (1.28.01</a>. This file is used to define the content and binary image layouts for firmware images, update capsules and PCI option ROMs. </li>
<li><code>IDF</code> - EDKII Image Description (IDF) files used for creating HII Image Packs used for graphical content presentation.</li>
<li><code>UNI</code> - EDKII Unicode string file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-uni-specification/v/release-1.40/">edk2-UniSpecification (1.40)</a>. This file is used for mapping token names to localized strings that are identified by an RFC4646 language code - in this way EDKII supports switching between multiple languages.</li>
<li><code>VFR</code> - EDKII Visual Forms Representation file format described in <a href="https://edk2-docs.gitbook.io/edk-ii-vfr-specification/v/release-1.92/">edk2-VfrSpecification (1.92)</a>. This is the source code format that is used by developers to create a user interface with varying pieces of data or questions. This is later compiled into a binary encoding IFR (Internal Forms Representation) that is used for the representation of user interface pages.</li>
</ul>
<p><code>DSC</code> are most important for build process since it define our target platform.</p>
<p>Please note we tried to use links to the most recent, already generated documentation at the point of creation of this exercise, but looking at published material may be misleading since the repository may contain newer content. Feel free to check the available version as well as associated Github repositories.</p>
<h2>Exercise #1</h2>
<p>Find all file types mentioned above in EDKII source tree and check its content.</p>
<h2>Build command</h2>
<p>EDKII build system is quite sophisticated and its build command provide a lot of parameters.</p>
<h2>Exercise #2</h2>
<p>Let's go over the basic EDKII build process. Normally we would start with installing tools required for compiling and cloning EDKII sources, but to save time and network bandwidth this is already part of VM image. For reference, this is what is required:</p>
<div class="codehilite">
<pre><span></span><code>$ sudo apt update
$ sudo apt install git build-essential uuid-dev nasm acpica-tools
$ git clone --recurse-submodules --branch edk2-stable202202 https://github.com/tianocore/edk2.git
</code></pre>
</div>
<p>To simplify environment variables setup, EDKII provides the edksetup.sh script for UNIX-like environments. To use it, type:</p>
<div class="codehilite">
<pre><span></span><code><span class="nb">cd</span> ~/edk2
<span class="nb">source</span> edksetup.sh
</code></pre>
</div>
<p>Please check build command parameters by calling <code>build --help</code> or <code>build -h</code>.</p>
<p>The most important parameters at this point in the course are: </p>
<ul>
<li><code>-p PLATFORMFILE</code> - Build the platform specified by the DSC file name </li>
<li><code>-b BUILDTARGET</code> - DEBUG or RELEASE build target </li>
<li><code>-t TOOLCHAIN</code> - Using the toolchain tagname to build the platform defined in tools_def.template, in this course we use GCC5 </li>
<li><code>-n THREADNUMBER</code> - Build the platform using multi-threaded compiler with defined number of threads, typically half of available CPU threads </li>
<li><code>-a ARCH</code> - ARCH is one of list: IA32, X64, ARM, AARCH64, RISCV64 or EBC </li>
</ul>
<p>There is no need to provide those paramters every time as input to the <code>build</code> command. Default parameters can be stored in <code>./Conf/target.txt</code>.
Please note the <code>build</code> command can also run just part of the build process by getting a stage name as the final parameter. The most important stages are:</p>
<ul>
<li><code>all</code> - go through all build stages. This is default if no other stage option is given. </li>
<li><code>fds</code> - use platform FDF to build final binary flash image. Useful if we changed FDF file and we want to rebuild the final binary. </li>
<li><code>genc</code> - autogenerate all necessary code files. </li>
<li><code>genmake</code> - autogenerate all necessary makefile files. </li>
<li><code>clean</code> - remove all binary products of build process, but keep intermediate autogenerated files. </li>
<li><code>cleanall</code> - clean everything from platform target directory. </li>
</ul>
<p>Despite all these possibilities, frequent building and code changes may get you into a weird state, which gives hard to diagnose compilation errors. To resolve that typically <code>cleanall</code> is required.</p>
<h2>Exercise #3</h2>
<ol>
<li>Setup environment variables by running "<code>source edksetup.sh</code>"</li>
<li><p>Before we build EDKII we need to build edk2 build tools first</p>
<div class="codehilite">
<pre><span></span><code>make -C /home/user/edk2/BaseTools/Source/C
</code></pre>
</div></li>
<li><p>Find DSC file for OVMF X64</p></li>
<li>Run the <code>build</code> process, setting all the most important command line parameters (use <code>DEBUG</code> as <code>BUILDTARGET</code>)</li>
</ol>
<p>Final result should look tell us how much space each Firmware Volume takes:</p>
<pre><code>(...)
FV Space Information
SECFV [19%Full] 212992 (0x34000) total, 42432 (0xa5c0) used, 170560 (0x29a40) free
PEIFV [22%Full] 917504 (0xe0000) total, 210152 (0x334e8) used, 707352 (0xacb18) free
DXEFV [33%Full] 12582912 (0xc00000) total, 4212944 (0x4048d0) used, 8369968 (0x7fb730) free
FVMAIN_COMPACT [35%Full] 3440640 (0x348000) total, 1233928 (0x12d408) used, 2206712 (0x21abf8) free
- Done -
Build end time: 00:30:41, Apr.05 2022
Build total time: 00:01:17
</code></pre>
<p>Our firmware image can be found in <code>Build/OvmfX64/<BUILDTARGET_TOOLCHAIN>/FV/OVMF.fd</code>, where <code><BUILDTARGET_TOOLCHAIN></code> is combination of target and toolchain that we defined as <code>build</code> command parameters.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@problem+block@3d89bda1f28743c19acd63e8db59a0d4">
<div class="xblock xblock-public_view xblock-public_view-problem xmodule_display xmodule_ProblemBlock" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="problem" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@problem+block@3d89bda1f28743c19acd63e8db59a0d4" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Mini-quiz #1 is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@28683e2362254bedb9395bd41ea5ded1">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@28683e2362254bedb9395bd41ea5ded1" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-3" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@5806476cf9dc4877832c74c68e6e4018">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@5806476cf9dc4877832c74c68e6e4018" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>
<div class="xblock xblock-public_view xblock-public_view-vertical" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-init="VerticalStudentView" data-runtime-class="LmsRuntime" data-runtime-version="1" data-block-type="vertical" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@vertical+block@b569d0f6eae94153850d1e4237ee21df" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="vert-mod">
<div class="vert vert-0" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@markdown+block@bdc1306286b94ab6a694d441b6862c91">
<div class="xblock xblock-public_view xblock-public_view-markdown" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="markdown" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@markdown+block@bdc1306286b94ab6a694d441b6862c91" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>Let's run results of build process:</p>
<pre><code>qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -nographic -net none
</code></pre>
<h2>-net none disclaimer</h2>
<p>We added <code>-net none</code> so that the network stack would not load in QEMU, so that the <a href="https://en.wikipedia.org/wiki/Preboot_Execution_Environment">PXE</a> network-based-boot would not wait while trying to receive something to boot over the network (which we're not providing, so it would just wait a while until timing out). We will continue to use <code>-net none</code> throughout this class to speed up the boot to the EFI shell. But just remember to remove it later if you're ever trying to do anything with networking from within QEMU after this class.</p>
<p>Once the system is fully booted, we should be at a UEFI Shell command line prompt. As a reminder, to leave QEMU you can use the special command listed in the help, which can be found using <code>Ctrl-a h</code>. We should see the UEFI shell, you can leave QEMU with <code>Ctrl-a x</code></p>
<p>To verify the instance of the UEFI shell, it should be looking like below:</p>
<pre><code>UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
Shell>
</code></pre>
<h2>Exercise #4</h2>
<p>Please repeat steps from Exercise #3, but instead parameters to <code>build</code> command use <code>Conf/target.txt</code> file. If you modify <code>Conf/target.txt</code> correctly <code>build</code> command should run without problems and build fresh <code>OVMF.fd</code>.</p>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@problem+block@aacb350e5c4f4a328d84c74d7b025840">
<div class="xblock xblock-public_view xblock-public_view-problem xmodule_display xmodule_ProblemBlock" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="problem" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@problem+block@aacb350e5c4f4a328d84c74d7b025840" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Mini-quiz #2 is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@881b5cab696f494b8e6af7b90632573e">
<div class="xblock xblock-public_view xblock-public_view-done" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="done" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@881b5cab696f494b8e6af7b90632573e" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="True">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Completion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
<div class="vert vert-3" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@095d00bdb26d437db806fe74d72ba705">
<div class="xblock xblock-public_view xblock-public_view-discussion" data-course-id="course-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1" data-block-type="discussion" data-usage-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@095d00bdb26d437db806fe74d72ba705" data-request-token="db3fd5f6032911efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="page-banner"><div class="alert alert-warning"><span class="icon icon-alert fa fa fa-warning" aria-hidden="true"></span><div class="message-content">Discussion is only accessible to enrolled learners. Sign in or register, and enroll in this course to view it.</div></div></div>
</div>
</div>
</div>
<script type="text/javascript">
(function (require) {
require(['/static/js/dateutil_factory.be68acdff619.js?raw'], function () {
require(['js/dateutil_factory'], function (DateUtilFactory) {
DateUtilFactory.transform('.localized-datetime');
});
});
}).call(this, require || RequireJS.require);
</script>
<script>
function emit_event(message) {
parent.postMessage(message, '*');
}
</script>
</div>