<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@99ee0b70ddc84bc68ab4c873548c6941" data-request-token="8913ee60039311efaa280242ac12000b" 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@7b4cb2cb0b8243fdac73a86c451ef921">
<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@7b4cb2cb0b8243fdac73a86c451ef921" data-request-token="8913ee60039311efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><p>UEFI Shell commands are like small application built-in to the UEFI Shell Application. To enter the UEFI Shell in the case of our QEMU+OVFM setup, we would just boot the platform and wait for Shell. Since it would be selected according to boot order.</p>
<h2>Exercise #1: Enter UEFI Shell</h2>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=0x402,chardev=edk2-debug -net none
</code></pre>
<p>After some time you should see:</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>
<ul>
<li>To list all available commands simply type <code>help</code>. Get familiar with available commands. Please note not all command are available in all versions of UEFI Shell. Available commands are selected at build time in EDKII.</li>
</ul>
<pre><code>Shell> help
alias - Displays, creates, or deletes UEFI Shell aliases.
attrib - Displays or modifies the attributes of files or directories.
bcfg - Manages the boot and driver options that are stored in NVRAM.
cd - Displays or changes the current directory.
cls - Clears the console output and optionally changes the background and foreground color.
comp - Compares the contents of two files on a byte-for-byte basis.
connect - Binds a driver to a specific device and starts the driver.
cp - Copies one or more files or directories to another location.
date - Displays and sets the current date for the system.
dblk - Displays one or more blocks from a block device.
devices - Displays the list of devices managed by UEFI drivers.
devtree - Displays the UEFI Driver Model compliant device tree.
dh - Displays the device handles in the UEFI environment.
disconnect - Disconnects one or more drivers from the specified devices.
dmem - Displays the contents of system or device memory.
dmpstore - Manages all UEFI variables.
drivers - Displays the UEFI driver list.
drvcfg - Invokes the driver configuration.
drvdiag - Invokes the Driver Diagnostics Protocol.
echo - Controls script file command echoing or displays a message.
edit - Provides a full screen text editor for ASCII or UCS-2 files.
eficompress - Compresses a file using UEFI Compression Algorithm.
efidecompress - Decompresses a file using UEFI Decompression Algorithm.
else - Identifies the code executed when 'if' is FALSE.
endfor - Ends a 'for' loop.
endif - Ends the block of a script controlled by an 'if' statement.
exit - Exits the UEFI Shell or the current script.
for - Starts a loop based on 'for' syntax.
getmtc - Gets the MTC from BootServices and displays it.
goto - Moves around the point of execution in a script.
help - Displays the UEFI Shell command list or verbose command help.
hexedit - Provides a full screen hex editor for files, block devices, or memory.
http - Download a file from HTTP server.
if - Executes commands in specified conditions.
ifconfig - Modifies the default IP address of the UEFI IPv4 Network Stack.
initrd - Registers or unregisters a file as Linux initrd.
load - Loads a UEFI driver into memory.
loadpcirom - Loads a PCI Option ROM.
ls - Lists the contents of a directory or file information.
map - Displays or defines file system mappings.
memmap - Displays the memory map maintained by the UEFI environment.
mkdir - Creates one or more new directories.
mm - Displays or modifies MEM/MMIO/IO/PCI/PCIE address space.
mode - Displays or changes the console output device mode.
mv - Moves one or more files to a destination within or between file systems.
openinfo - Displays the protocols and agents associated with a handle.
parse - Retrieves a value from a standard format output file.
pause - Pauses a script and waits for an operator to press a key.
pci - Displays PCI device list or PCI function configuration space and PCIe extended configuration space.
ping - Ping the target host with an IPv4 stack.
reconnect - Reconnects drivers to the specific device.
reset - Resets the system.
rm - Deletes one or more files or directories.
sermode - Sets serial port attributes.
set - Displays or modifies UEFI Shell environment variables.
setsize - Adjusts the size of a file.
setvar - Displays or modifies a UEFI variable.
shift - Shifts in-script parameter positions.
smbiosview - Displays SMBIOS information.
stall - Stalls the operation for a specified number of microseconds.
tftp - Download a file from TFTP server.
time - Displays or sets the current time for the system.
timezone - Displays or sets time zone information.
touch - Updates the filename timestamp with the current system date and time.
type - Sends the contents of a file to the standard output device.
unload - Unloads a driver image that was already loaded.
ver - Displays UEFI Firmware version information.
vol - Displays or modifies information about a disk volume.
Help usage:help [cmd|pattern|special] [-usage] [-verbose] [-section name][-b]
</code></pre>
<ul>
<li>Based on number of commands we can easily say this is very simple OS-like environment similar to DOS. But what is more important it runs in ring 0, so it is highly priviledged.</li>
<li>Try to read help for some commands and get through all documentation sections. (For instancel look at <code>mm</code> and think about how you could do things with PCIe access that you learned about in Arch4001, if you took that already.)</li>
<li>You can also read more about the commands, as well as scripting in the shell, in the <a href="https://uefi.org/sites/default/files/resources/UEFI_Shell_Spec_2_0.pdf">UEFI Shell Specification 2.0</a> document.</li>
</ul>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@0746fb2197a74710933e51c345f60098">
<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@0746fb2197a74710933e51c345f60098" data-request-token="8913ee60039311efaa280242ac12000b" 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-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@7ae56e72d04a46d4b2a4cddec05fb26c">
<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@7ae56e72d04a46d4b2a4cddec05fb26c" data-request-token="8913ee60039311efaa280242ac12000b" 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@9fc663038ead40afb82cdbb3aed8c84b" data-request-token="8913ee60039311efaa280242ac12000b" 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@297a73541e94461eb98031cd2f7cbefd">
<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@297a73541e94461eb98031cd2f7cbefd" data-request-token="8913ee60039311efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><h2>Exercise #2: list all block devices</h2>
<h3>Create a filesystem to act as a USB device</h3>
<ul>
<li>From Exercise #1 you may have looked at the <code>map</code> command, which shows existing block devices and filesystems.</li>
<li><code>map -r</code> is very useful to detect hotplugged devices, since UEFI does enumeration just once.</li>
<li>In other terminal let's create FAT32 image that will be used as USB stick:</li>
</ul>
<pre><code>user@user-OST-VM:~$ qemu-img create -f raw /tmp/usb.img 128M
Formatting '/tmp/usb.img', fmt=raw size=134217728
user@user-OST-VM:~$ mkfs.vfat -F32 /tmp/usb.img
mkfs.fat 4.1 (2017-01-24)
</code></pre>
<ul>
<li>Now let's add some files to the filesystem. The EFI Self-Certification Test (SCT) can be used to evaluate the quality of a UEFI implementation.</li>
<li>Obtain SCT:</li>
</ul>
<div class="codehilite">
<pre><span></span><code>wget https://github.com/tianocore/edk2-test/releases/download/edk2-test-stable202108/UefiSctBinaryX64.zip
unzip UefiSctBinaryX64.zip
</code></pre>
</div>
<p>(<a href="https://gitlab.com/opensecuritytraining/arch4021-intro-uefi-additional-files/-/blob/master/UefiSctBinaryX64.zip">Mirror copy of UefiSctBinaryX64.zip incase the above link breaks</a>)</p>
<ul>
<li>Mount our USB disk image and copy SCT to it</li>
</ul>
<div class="codehilite">
<pre><span></span><code>sudo mount /tmp/usb.img /media
sudo cp -r SctPackageX64/ /media
sudo umount /media
</code></pre>
</div>
<h3>Start QEMU and mount the virtual USB device</h3>
<ul>
<li>Now start qemu with USB XHCI controller.</li>
</ul>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=0x402,chardev=edk2-debug -net none -device qemu-xhci,id=xhci
</code></pre>
<ul>
<li>Check <code>map</code> output</li>
</ul>
<pre><code>Shell> map
Mapping table
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
</code></pre>
<ul>
<li>Let's check how the block devices listed change when we will add a file as a USB device. </li>
<li>Enter QEMU Monitor (<code>Ctrl-a c</code>) and add the virtual USB stick.</li>
</ul>
<pre><code>(qemu) drive_add 0 if=none,id=stick,format=raw,file=/tmp/usb.img
OK
(qemu) device_add usb-storage,id=ost2,bus=xhci.0,drive=stick
</code></pre>
<ul>
<li>Let's get back to our UEFI Shell, by <code>Ctrl-a c</code>, to clean screen use <code>cls</code> command</li>
<li>Let's run <code>map</code> again. It looks like nothing happen?</li>
<li>Let's use <code>map -r</code>:</li>
</ul>
<pre><code>Shell> map -r
Mapping table
FS0: Alias(s):HD1a0:;BLK1:
PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
</code></pre>
<p>As we can see <code>FS0</code> appeared under <code>BLK1</code> device.</p>
<ul>
<li><p>We would see similar behavior with real hardware.</p></li>
<li><p>Now you can change directory to the fs0 filesystem by just typing <code>fs0:</code> (the colon is required), and use <code>ls</code> or <code>dir</code> to see the filesystem contents.</p></li>
</ul>
<pre><code>Shell> fs0:
FS0:\> ls
Directory of: FS0:\
10/21/2022 12:01 <DIR> 512 SctPackageX64
0 File(s) 0 bytes
1 Dir(s)
</code></pre>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@39d7f7d65fca4129a181d72313260b2e">
<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@39d7f7d65fca4129a181d72313260b2e" data-request-token="8913ee60039311efaa280242ac12000b" 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-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@a28fa3ed4141457d940027294b79896f">
<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@a28fa3ed4141457d940027294b79896f" data-request-token="8913ee60039311efaa280242ac12000b" 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@8e20ebdfb7be46b5a7a3007475a40f1b" data-request-token="8913ee60039311efaa280242ac12000b" 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@1c36d616942b4b8183c28c32539acaea">
<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@1c36d616942b4b8183c28c32539acaea" data-request-token="8913ee60039311efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><h2>Exercise #3: Run UEFI Self-Certification Test (SCT)</h2>
<ul>
<li>Instead of dynamically adding the virtual USB at runtime, you can also attach the disk at boot time. This will cause it to be found by the initial enumeration.</li>
</ul>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=0x402,chardev=edk2-debug -net none -drive file=/tmp/usb.img,index=0,media=disk,format=raw
</code></pre>
<div class="codehilite">
<pre><span></span><code>UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 <span class="o">(</span>EDK II, 0x00010000<span class="o">)</span>
Mapping table
FS0: Alias<span class="o">(</span>s<span class="o">)</span>:F0a:<span class="p">;</span>BLK0:
PciRoot<span class="o">(</span>0x0<span class="o">)</span>/Pci<span class="o">(</span>0x1,0x1<span class="o">)</span>/Ata<span class="o">(</span>0x0<span class="o">)</span>
BLK1: Alias<span class="o">(</span>s<span class="o">)</span>:
PciRoot<span class="o">(</span>0x0<span class="o">)</span>/Pci<span class="o">(</span>0x1,0x1<span class="o">)</span>/Ata<span class="o">(</span>0x0<span class="o">)</span>
Press ESC <span class="k">in</span> <span class="m">1</span> seconds to skip startup.nsh or any other key to <span class="k">continue</span>.
Shell> fs0:
FS0:<span class="se">\></span> ls
Directory of: FS0:<span class="se">\</span>
<span class="m">10</span>/21/2022 <span class="m">12</span>:18 <span class="m">10</span>,367 NvVars
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <DIR> <span class="m">512</span> SctPackageX64
<span class="m">1</span> File<span class="o">(</span>s<span class="o">)</span> <span class="m">10</span>,367 bytes
<span class="m">1</span> Dir<span class="o">(</span>s<span class="o">)</span>
FS0:<span class="se">\></span> <span class="nb">cd</span> SctPackageX64
FS0:<span class="se">\S</span>ctPackageX64<span class="se">\></span> ls
Directory of: FS0:<span class="se">\S</span>ctPackageX64<span class="se">\</span>
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <DIR> <span class="m">512</span> .
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <DIR> <span class="m">0</span> ..
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <span class="m">32</span>,800 InstallX64.efi
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <span class="m">1</span>,505 SctStartup.nsh
<span class="m">10</span>/21/2022 <span class="m">12</span>:01 <DIR> <span class="m">1</span>,024 X64
FS0:<span class="se">\S</span>ctPackageX64<span class="se">\></span>
</code></pre>
</div>
<ul>
<li>Run <code>InstallX64.efi</code> and select index 1 for FS0. It will create a directory in <code>FS0:\</code> and <code>startup.nsh</code> script which will be used after reboot.</li>
<li>After installation completes, go to <code>FS0:\SCT</code></li>
<li>Running a full test suite using <code>SCT.efi -a</code> hangs in QEMU (at least it hanged for me) after around 10 hours of execution. <code>-v</code> should accelerate execution 70-80% but it is still a lot.</li>
<li>So, let's try running only some subset of tests through a sequence file:</li>
</ul>
<div class="codehilite">
<pre><span></span><code>FS0:<span class="se">\S</span>ct<span class="se">\></span> SCT.efi -u
</code></pre>
</div>
<ul>
<li>Go to <code>Test Case Management->GenericTest->EfiCompliantTest</code> and highlight <code>PlatformSpecificElements</code>.</li>
<li>Let's run that test case. Things would be easy if we could just hit <code>F9</code> as application bottom bar say, unfortunately in our case it will send different characters to SCT which will lead to setting 20 iteration without exiting. So we have to use the trick with sending <code>F9</code> from QEMU monitor.</li>
<li>Let's switch to monitor <code>Ctrl-a c</code> and type <code>sendkey f9</code>. This will run tests with result of 14 passes and 16 fails.</li>
<li>Let's get back to main menu, and generate test report using <code>Test Report Generator</code>. <code>F2</code> have to be sent using above trick to enter report file name. Test report can be found in <code>FS0:\SCT\Report\<report_name>.csv</code>. You can view them with <code>edit</code>, and exit edit with <code>Ctrl-q</code>.</li>
<li>We can also take a look at test logs by using <code>View Test Log</code> and choosing <code>GenericTest->EfiCompliantTest0</code> and file that is inside directory - now you are in primitive editor of UEFI (<code>Ctrl-e</code> for help).</li>
<li>Hit <code>Ctrl-g</code> and give line 142, this should give you following screen.
<img src="https://gitlab.com/opensecuritytraining/arch4021_uefi_intro_slides_and_subtitles/-/raw/main/images/sct_test_log_view.png" alt="" /></li>
<li>You can exit the editor with <code>Ctrl-q</code>.</li>
</ul>
<h2>Exercise #4: Save sequence file</h2>
<ul>
<li>If it is not selected, go to <code>Test Case Management->GenericTest->EfiCompliantTest</code> and highlight <code>PlatformSpecificElements</code>.</li>
<li>Now we have to save sequence file. Exit back to the main starting menu. You should see the F6 option to save a sequence at the bottom of the screen.</li>
<li>Let's switch to monitor <code>Ctrl-a c</code> and type <code>sendkey f6</code>, we should see following screen.
<img src="https://gitlab.com/opensecuritytraining/arch4021_uefi_intro_slides_and_subtitles/-/raw/main/images/sct_sendkey_f6.png" alt="" /></li>
<li>Then type <code>sendkey f2</code> and let's switch back (<code>Ctrl-a c</code>) top provide filename <code>ost2</code> and hit <code>Enter</code>, this should give us following screen.
<img src="https://gitlab.com/opensecuritytraining/arch4021_uefi_intro_slides_and_subtitles/-/raw/main/images/sct_seq_save_succeed.png" alt="" /></li>
<li>Then type <code>Ctrl-a c</code> to get out of the QEMU menu and type the sequence file name of "ost2", and hit enter.</li>
<li>We should see file in <code>Sequence</code> directory:</li>
</ul>
<div class="codehilite">
<pre><span></span><code>FS0:<span class="se">\S</span>ct<span class="se">\></span> ls Sequence Directory of: FS0:<span class="se">\S</span>ct<span class="se">\S</span>equence<span class="se">\ </span> <span class="m">06</span>/01/2022 <span class="m">22</span>:19 <DIR> <span class="m">512</span> . <span class="m">06</span>/01/2022 <span class="m">22</span>:19 <DIR> <span class="m">8</span>,704 .. <span class="m">06</span>/02/2022 <span class="m">23</span>:37 <span class="m">171</span>,170 ost2.seq <span class="m">1</span> File<span class="o">(</span>s<span class="o">)</span> <span class="m">171</span>,170 bytes <span class="m">2</span> Dir<span class="o">(</span>s<span class="o">)</span>
</code></pre>
</div>
<ul>
<li>It should be possible to run those tests using following command:</li>
</ul>
<div class="codehilite">
<pre><span></span><code>Shell> SCT.efi -s ost2.seq
</code></pre>
</div>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@bd47d84bb1c441dda8ffed50ad47e05f">
<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@bd47d84bb1c441dda8ffed50ad47e05f" data-request-token="8913ee60039311efaa280242ac12000b" 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-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@e9699b8002664a1b9e38fd7c1abacbfe">
<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@e9699b8002664a1b9e38fd7c1abacbfe" data-request-token="8913ee60039311efaa280242ac12000b" 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@7cf976ff5dab4e859fdf1927da8a71f1" data-request-token="8913ee60039311efaa280242ac12000b" 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@9410600cd28f4b899ecba50bccd79a1f">
<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@9410600cd28f4b899ecba50bccd79a1f" data-request-token="8913ee60039311efaa280242ac12000b" data-graded="True" data-has-score="False">
<div class="markdown_xblock"><h2>Exercise #5: Compile and run HelloWorld EFI application</h2>
<h3>Build HelloWorld and copy to a mountable drive</h3>
<ul>
<li>Future classes like Arch4023 will dive much deeper into programming in a UEFI environment. For now we'd like to give you a basic HelloWorld that will run as an OS-absent application from the UEFI shell. This will give you something to play with, and somewhere to put code you either write based on reading the UEFI specification on your own, or based on finding code on the internet and wanting to try it out.</li>
<li>As it turns out, EDKII has a HelloWorld application already built in at MdeModulePkg/Application/HelloWorld/HelloWorld.c</li>
<li>This is a little more complicated than a minimal HelloWorld, because instead of just hardcoding in the HelloWorld string, it chooses to look it up via a PCD entry (which as we mentioned earlier in the class is a Portable Configuration Database entry, which is just like a glorified configuration-specific global variable.) Lets proceed to just running the executable and then we can return to finding the PCD definitions (since simple grepping for now would yield too many hits to make it clear.) </li>
<li>To compile it, we must build the MdeModulePkg where the file is found.</li>
</ul>
<pre><code>build -a X64 -p MdeModulePkg/MdeModulePkg.dsc -t GCC5 -n$(nproc)
</code></pre>
<ul>
<li>Let's make a new /tmp/usb2.img and copy HelloWorld.efi to it:</li>
</ul>
<div class="codehilite">
<pre><span></span><code>qemu-img create -f raw /tmp/usb2.img 128M
mkfs.vfat -F32 /tmp/usb2.img
sudo mount /tmp/usb2.img /media
sudo cp Build/MdeModule/DEBUG_GCC5/X64/HelloWorld.efi /media
sudo umount /media
</code></pre>
</div>
<h3>Start QEMU and with the drive attached</h3>
<ul>
<li>Now start qemu with the /tmp/usb2.img file attached at boot time:</li>
</ul>
<pre><code>qemu-system-x86_64 -nographic -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -chardev file,path=debug.log,id=edk2-debug -device isa-debugcon,iobase=0x402,chardev=edk2-debug -net none -drive file=/tmp/usb2.img,index=0,media=disk,format=raw
</code></pre>
<ul>
<li>Now run QEMU and launch HelloWorld.efi from the UEFI shell. If you read the comments at the beginning of HelloWorld.c, you'll also know that it supports a <code>-?</code> option, so let's try that too.</li>
</ul>
<pre><code>UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
FS0: Alias(s):F0a:;BLK0:
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
BLK1: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
Press ESC in 5 seconds to skip startup.nsh or any other key to continue.
Shell> fs0:
FS0:\> HelloWorld.efi
UEFI Hello World!
FS0:\> HelloWorld.efi -?
HelloWorld application.
</code></pre>
<h3>Finding where the PCDs are defined</h3>
<ul>
<li>Now that we've actually executed the code, we know that the PcdHelloWorldPrintString corresponds to the string "UEFI Hello World!". So let's search for that.</li>
</ul>
<pre><code>grep -r "UEFI Hello World!" *
...
MdeModulePkg/MdeModulePkg.dec: gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString|L"UEFI Hello World!\n"|VOID*|0x40000004
</code></pre>
<ul>
<li>There were a decent number of hits, but only the last one looked like it wasn't a comment. So recall that .dec files are Package Description files, and <code>MdeModulePkg/MdeModulePkg.dec</code> seems to be the description for the MdeModule Package.</li>
<li>If we open up <code>MdeModulePkg/MdeModulePkg.dec</code> we will see the other PCD entries found in HelloWorld.c such as PcdHelloWorldPrintEnable and PcdHelloWorldPrintTimes.</li>
<li>Go ahead and edit PcdHelloWorldPrintTimes to be a number other than one, and also add your own Print() string to HelloWorld.c. But <strong><em>note</em></strong>, UEFI uses 2-byte long-character strings. So you must prefix your string with an L, like L"This is my string".</li>
<li>Recompile your HelloWorld, re-copy it into the disk image, re-run QEMU, and re-launch your HelloWorld.efi to see your changes took effect.</li>
</ul>
</div>
</div>
</div>
<div class="vert vert-1" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@done+block@c506af644632404792c14d73f4262d72">
<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@c506af644632404792c14d73f4262d72" data-request-token="8913ee60039311efaa280242ac12000b" 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-2" data-id="block-v1:OpenSecurityTraining2+Arch4021_intro_UEFI+2023_v1+type@discussion+block@1f0bd689674f44afaf837efb831534c6">
<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@1f0bd689674f44afaf837efb831534c6" data-request-token="8913ee60039311efaa280242ac12000b" 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>