In last lesson we've built an app that was already included in the TianoCore sources.
Let's work our way through to our own app. We will be working on UEFI app that can be run in UEFI shell.
Create directory for our app:
mkdir SimplestApp
Then create *.c source file for our app with the folowing content:
$ cat SimplestApp/SimplestApp.c
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EFI_SUCCESS;
}
Then we need to create edk2 app configuration file. This configuration in edk2 is represented in the *.inf format. INF file can have several sections:
- Defines
- Sources
- Packages
- LibraryClasses
- Guids
- Ppis
- Protocols
- FeaturePcd
- Pcd
- ...
But right now for our minimal example we're interested in the 3 of those:
- Defines - this section contatins some basic module description. In this section:
BASE_NAME - our app name
FILE_GUID - as was said earlier UEFI uses GUID numbers for identification of the components. You could use free online GUID generator to get random GUID https://www.guidgenerator.com/ or simply use uuidgen
command line utility:
$ uuidgen
e7218aab-998e-4d88-af9b-9573a5bf90ea
MODULE_TYPE - we want to build an application that can be run from the UEFI shell, so we use UEFI_APPLICATION
here. UEFI application is like a simple program that you can run from shell. It is getting loaded to some memory address, executes and returns something, after that app memory would be freed again. For example other possible value here is UEFI_DRIVER - the difference is when you load a driver it keeps staying in memory even after its execution.
Other values are listed here: https://edk2-docs.gitbook.io/edk-ii-inf-specification/appendix_f_module_types
ENTRY_POINT - name of the main function in our *.c source file. As it was UefiMain
this is the value that we write here.
- Sources - source files for our edk2 module
- LibraryClasses - we need to include
UefiApplicationEntryPoint
library class for our minimal example - Packages -
MdePkg/MdePkg.dec
is edk2 package with basic UEFI services. It includesUefiApplicationEntryPoint
that we need to compile our package.
vi SimplestApp/SimplestApp.inf
[Defines]
INF_VERSION = 1.25
BASE_NAME = SimplestApp
FILE_GUID = 4a298956-fbe0-47fb-ae3a-2d5a0a959a26
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Sources]
SimplestApp.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
Full specification for the "Module Information (INF) File" can be found under https://edk2-docs.gitbook.io/edk-ii-inf-specification/
After the creation of the INF file we need to include our app to some package so we could build it.
We don't have our own package, so let's include it to OvmfPkg/OvmfPkgX64.dsc
that we've compiled earlier.
Add a path to our app *.inf file in the components section.
################################################################################
[Components]
+ SimplestApp/SimplestApp.inf
OvmfPkg/ResetVector/ResetVector.inf
Then build OVMF:
build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5
Our compiled app would be in a directory Build/OvmfX64/RELEASE_GCC5/X64
:
$ ls -lh Build/OvmfX64/RELEASE_GCC5/X64/SimplestApp.efi
-rw-r--r-- 1 kostr kostr 832 Jun 13 10:14 Build/OvmfX64/RELEASE_GCC5/X64/SimplestApp.efi
Create a folder that we would populate to UEFI shell and copy our app into it:
mkdir ~/UEFI_disk
cp Build/OvmfX64/RELEASE_GCC5/X64/SimplestApp.efi ~/UEFI_disk
Now lets run OVMF with this folder included:
$ qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \
-drive format=raw,file=fat:rw:~/UEFI_disk \
-nographic \
-net none
Hopefully you'll see something like this:
UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
FS0: Alias(s):HD0a1:;BLK1:
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
BLK2: Alias(s):
PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
Press ESC in 3 seconds to skip startup.nsh or any other key to continue.
As you can see we have new rows in our mapping table. Our app would be under FS0
. Lets mount
this filesystem and execute our app.
Shell> fs0:
FS0:\> SimplestApp.efi
FS0:\>