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:\> ```