In the last lesson to build our app we've included its *.inf file as a component to the other package and have built this package. It is clearly not a good solution and in this lesson we will create our own package.
First lets remove our app from the OvmfPkg/OvmfPkgX64.dsc
file:
################################################################################
[Components]
- SimplestApp/SimplestApp.inf
OvmfPkg/ResetVector/ResetVector.inf
Then create UefiLessonsPkg
folder in the edk2 directory and move our app into this folder:
mkdir UefiLessonsPkg
mv SimplestApp UefiLessonsPkg/SimplestApp
Then we need to create platform description file (DSC) for our newly created package:
$ vi UefiLessonsPkg/UefiLessonsPkg.dsc
[Defines]
DSC_SPECIFICATION = 0x0001001C
PLATFORM_GUID = 3db7270f-ffac-4139-90a4-0ae68f3f8167
PLATFORM_VERSION = 0.01
PLATFORM_NAME = UefiLessonsPkg
SKUID_IDENTIFIER = DEFAULT
SUPPORTED_ARCHITECTURES = X64
BUILD_TARGETS = RELEASE
[Components]
UefiLessonsPkg/SimplestApp/SimplestApp.inf
All the fileds under Defines
section are mondatory.
Full specification for the Platform Description (DSC) File can be found under https://edk2-docs.gitbook.io/edk-ii-dsc-specification/
Let's try to build our SimplestApp module that is now in our own package:
$ . edksetup.sh
$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \
--module=UefiLessonsPkg/SimplestApp/SimplestApp.inf \
--arch=X64 \
--buildtarget=RELEASE \
--tagname=GCC5
Unfortunately the build would fail:
build.py...
/home/kostr/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 4000: Instance of library class [UefiApplicationEntryPoint] is not found
in [/home/kostr/edk2/UefiLessonsPkg/SimplestApp/SimplestApp.inf] [X64]
consumed by module [/home/kostr/edk2/UefiLessonsPkg/SimplestApp/SimplestApp.inf]
To fix this we need to add UefiApplicationEntryPoint
to the LibraryClasses
section in our UefiLessonsPkg.dsc
file.
To find necessay include lets search our edk2 codebase:
$ grep UefiApplicationEntryPoint -r ./ --include=*.inf | grep LIBRARY_CLASS
./MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf: LIBRARY_CLASS = UefiApplicationEntryPoint|UEFI_APPLICATION
Therefore we need to add these strings to our *.dsc file:
[LibraryClasses]
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
Format of the record is
LibraryClassName|Path/To/LibInstanceName.inf
LibraryClass can have several potential realizations (instances), therefore we need to write both LibraryClassName
and LibraryInstanceName
.
In the end this adds this string to the Makefile:
LIBS = $(LIBS) $(LIB_DIR)/$(LibInstanceName)
You can read more about LibraryClasses
section under https://edk2-docs.gitbook.io/edk-ii-dsc-specification/2_dsc_overview/26_-libraryclasses-_section_processing
Let's try to rebuild:
$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \
--module=UefiLessonsPkg/SimplestApp/SimplestApp.inf \
--arch=X64 \
--buildtarget=RELEASE \
--tagname=GCC5
But the build would fail again:
build.py...
/home/kostr/tiano/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 4000: Instance of library class [UefiBootServicesTableLib] is not found
in [/home/kostr/tiano/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf] [X64]
consumed by module [/home/kostr/tiano/edk2/UefiLessonsPkg/SimplestApp/SimplestApp.inf]
As we see the error message is the same. It seems like UefiApplicationEntryPoint
module that we've included needs some additional includes. So we search necessary libraries again... and again... and again.
In the end our *.dsc file would be looking like this:
[Defines]
PLATFORM_NAME = UefiLessonsPkg
PLATFORM_GUID = 3db7270f-ffac-4139-90a4-0ae68f3f8167
PLATFORM_VERSION = 0.01
DSC_SPECIFICATION = 0x00010006
OUTPUT_DIRECTORY = Build/UefiLessonsPkg
SUPPORTED_ARCHITECTURES = X64
BUILD_TARGETS = RELEASE
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
[Components]
UefiLessonsPkg/SimplestApp/SimplestApp.inf
After the successful build the result binary would be in a Build/UefiLessonsPkg/RELEASE_GCC5/X64
folder:
$ ls -lh Build/UefiLessonsPkg/RELEASE_GCC5/X64/SimplestApp.efi
-rw-r--r-- 1 kostr kostr 960 Jun 13 12:47 Build/UefiLessonsPkg/RELEASE_GCC5/X64/SimplestApp.efi
Let's copy in our UEFI_disk
folder and run it in OVMF:
$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/SimplestApp.efi ~/UEFI_disk/
$ 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 everything would be the same it was earlier:
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 4 seconds to skip startup.nsh or any other key to continue.
Shell> fs0:
FS0:\> SimplestApp.efi
FS0:\>