From 949552d025a5968b3fd3e8d0ab399c9a85232def Mon Sep 17 00:00:00 2001 From: Konstantin Aladyshev Date: Sat, 19 Jun 2021 21:03:52 +0300 Subject: Rename lesson numbers to XX notation With XX notation lessons would be placed in a folder from first to last. --- Lesson_0/README.md | 98 -------- Lesson_00/README.md | 98 ++++++++ Lesson_01/README.md | 138 +++++++++++ Lesson_01/SimplestApp/SimplestApp.c | 10 + Lesson_01/SimplestApp/SimplestApp.inf | 16 ++ Lesson_02/README.md | 154 ++++++++++++ Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_02/UefiLessonsPkg/UefiLessonsPkg.dsc | 23 ++ Lesson_03/README.md | 168 +++++++++++++ Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.c | 10 + Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 17 ++ Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_03/UefiLessonsPkg/UefiLessonsPkg.dsc | 26 ++ Lesson_04/README.md | 229 ++++++++++++++++++ Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_04/UefiLessonsPkg/UefiLessonsPkg.dsc | 30 +++ Lesson_05/Conf/target.txt | 7 + Lesson_05/README.md | 53 ++++ Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_05/UefiLessonsPkg/UefiLessonsPkg.dsc | 30 +++ Lesson_06/Conf/target.txt | 7 + Lesson_06/Handle_Protocol_databases_scheme.jpg | Bin 0 -> 59389 bytes Lesson_06/README.md | 243 +++++++++++++++++++ Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c | 30 +++ .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 ++ Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 +++ Lesson_07/Conf/target.txt | 7 + Lesson_07/README.md | 229 ++++++++++++++++++ Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c | 88 +++++++ .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 ++ Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 +++ Lesson_08/DevicePath.png | Bin 0 -> 68176 bytes Lesson_08/README.md | 269 +++++++++++++++++++++ Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.c | 88 +++++++ .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 ++ Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.c | 44 ++++ Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.inf | 22 ++ Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_08/UefiLessonsPkg/UefiLessonsPkg.dsc | 32 +++ Lesson_09/Conf/target.txt | 7 + Lesson_09/README.md | 148 ++++++++++++ Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.c | 102 ++++++++ .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 ++ Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.c | 44 ++++ Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.inf | 22 ++ Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ Lesson_09/UefiLessonsPkg/UefiLessonsPkg.dsc | 32 +++ Lesson_1/README.md | 138 ----------- Lesson_1/SimplestApp/SimplestApp.c | 10 - Lesson_1/SimplestApp/SimplestApp.inf | 16 -- Lesson_2/README.md | 154 ------------ Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_2/UefiLessonsPkg/UefiLessonsPkg.dsc | 23 -- Lesson_3/README.md | 168 ------------- Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c | 10 - Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 17 -- Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc | 26 -- Lesson_4/README.md | 229 ------------------ Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_4/UefiLessonsPkg/UefiLessonsPkg.dsc | 30 --- Lesson_5/Conf/target.txt | 7 - Lesson_5/README.md | 53 ---- Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_5/UefiLessonsPkg/UefiLessonsPkg.dsc | 30 --- Lesson_6/Conf/target.txt | 7 - Lesson_6/Handle_Protocol_databases_scheme.jpg | Bin 59389 -> 0 bytes Lesson_6/README.md | 243 ------------------- Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.c | 30 --- .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 -- Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_6/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 --- Lesson_7/Conf/target.txt | 7 - Lesson_7/README.md | 229 ------------------ Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.c | 88 ------- .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 -- Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_7/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 --- Lesson_8/DevicePath.png | Bin 68176 -> 0 bytes Lesson_8/README.md | 269 --------------------- Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.c | 88 ------- .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 -- Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.c | 44 ---- Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.inf | 22 -- Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_8/UefiLessonsPkg/UefiLessonsPkg.dsc | 32 --- Lesson_9/Conf/target.txt | 7 - Lesson_9/README.md | 148 ------------ Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 -- Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 -- Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.c | 102 -------- .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 -- Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.c | 44 ---- Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.inf | 22 -- Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 - .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 -- Lesson_9/UefiLessonsPkg/UefiLessonsPkg.dsc | 32 --- README.md | 20 +- 137 files changed, 2973 insertions(+), 2973 deletions(-) delete mode 100644 Lesson_0/README.md create mode 100644 Lesson_00/README.md create mode 100644 Lesson_01/README.md create mode 100644 Lesson_01/SimplestApp/SimplestApp.c create mode 100644 Lesson_01/SimplestApp/SimplestApp.inf create mode 100644 Lesson_02/README.md create mode 100644 Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_02/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_03/README.md create mode 100644 Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_03/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_04/README.md create mode 100644 Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_04/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_05/Conf/target.txt create mode 100644 Lesson_05/README.md create mode 100644 Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_05/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_06/Conf/target.txt create mode 100644 Lesson_06/Handle_Protocol_databases_scheme.jpg create mode 100644 Lesson_06/README.md create mode 100644 Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c create mode 100644 Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf create mode 100644 Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_07/Conf/target.txt create mode 100644 Lesson_07/README.md create mode 100644 Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c create mode 100644 Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf create mode 100644 Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_08/DevicePath.png create mode 100644 Lesson_08/README.md create mode 100644 Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.c create mode 100644 Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.inf create mode 100644 Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.c create mode 100644 Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.inf create mode 100644 Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_08/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lesson_09/Conf/target.txt create mode 100644 Lesson_09/README.md create mode 100644 Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.c create mode 100644 Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.inf create mode 100644 Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.c create mode 100644 Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.inf create mode 100644 Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lesson_09/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_1/README.md delete mode 100644 Lesson_1/SimplestApp/SimplestApp.c delete mode 100644 Lesson_1/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_2/README.md delete mode 100644 Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_2/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_3/README.md delete mode 100644 Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_4/README.md delete mode 100644 Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_4/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_5/Conf/target.txt delete mode 100644 Lesson_5/README.md delete mode 100644 Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_5/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_6/Conf/target.txt delete mode 100644 Lesson_6/Handle_Protocol_databases_scheme.jpg delete mode 100644 Lesson_6/README.md delete mode 100644 Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.c delete mode 100644 Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.inf delete mode 100644 Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_6/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_7/Conf/target.txt delete mode 100644 Lesson_7/README.md delete mode 100644 Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.c delete mode 100644 Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.inf delete mode 100644 Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_7/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_8/DevicePath.png delete mode 100644 Lesson_8/README.md delete mode 100644 Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.c delete mode 100644 Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.inf delete mode 100644 Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.c delete mode 100644 Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.inf delete mode 100644 Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_8/UefiLessonsPkg/UefiLessonsPkg.dsc delete mode 100644 Lesson_9/Conf/target.txt delete mode 100644 Lesson_9/README.md delete mode 100644 Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.c delete mode 100644 Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.inf delete mode 100644 Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.c delete mode 100644 Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.inf delete mode 100644 Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.c delete mode 100644 Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.inf delete mode 100644 Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.c delete mode 100644 Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.inf delete mode 100644 Lesson_9/UefiLessonsPkg/UefiLessonsPkg.dsc diff --git a/Lesson_0/README.md b/Lesson_0/README.md deleted file mode 100644 index a45b5ae..0000000 --- a/Lesson_0/README.md +++ /dev/null @@ -1,98 +0,0 @@ -First install necessary packages to your distro. -For the TianoCore compilation you'll need: -- nasm - The Netwide Assembler (NASM) is an assembler and disassembler for the Intel x86 architecture. It can be used to write 16-bit, 32-bit (IA-32) and 64-bit (x86-64) programs. NASM is considered to be one of the most popular assemblers for Linux, -- iasl - Intel ACPI compiler/decompiler. Advanced Configuration and Power Interface (ACPI) provides an open standard that operating systems can use to discover and configure computer hardware components, to perform power management and to perform status monitoring. UEFI firmware provides ACPI configuration tables to OS. ACPI specification can be found at https://uefi.org/specifications, -- uuid-dev - Universally Unique ID library. A universally unique identifier (UUID) is a 128-bit label used for identification of various components in UEFI. The term globally unique identifier (GUID) is also used, -- python3 - Python 3 interpreter is needed as build infrastructure includes python scripts. - -This is how you install these packages in Ubuntu: -``` -$ sudo apt-get install -y nasm iasl uuid-dev python3 -``` - -Then it is necessary to clone edk2 repo and update all its submodules: -``` -$ git clone https://github.com/tianocore/edk2 -$ cd edk2 -$ git submodule update --init -``` - -Just in case the size of the edk2 folder after that would be ~867M (as for 12-06-2021). - -Next we need to compile EDK2 build tools: -``` -make -C BaseTools -``` - -To initiate a build we need to source `edksetup.sh` script to get necessary variables into our environment: -``` -$ . edksetup.sh -Loading previous configuration from /<...>/edk2/Conf/BuildEnv.sh -Using EDK2 in-source Basetools -WORKSPACE: /<...>/edk2 -EDK_TOOLS_PATH: /<...>/edk2/BaseTools -CONF_PATH: /<...>/edk2/Conf -``` - -After that we could use `build` command to build EDK2 packages. -Try to execute help command to see all available options: -``` -build --help -``` - -Next we want to build the Open Virtual Machine Firmware (OVMF). OVMF is a port of tianocore firmware to the qemu virtual machine. This allows easy debugging and experimentation with UEFI firmware; either for testing OS booting or using the (included) EFI shell. We would be writing various EFI programs, and OVMF is an easy way to test them. We could install it with the package manager with something like `sudo apt-get install ovmf`, but it is not fun. - -To build OVMF execute: -``` -build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5 -``` - -If build is successful, result would be in the folder `Build/{Platform Name}/{TARGET}_{TOOL_CHAIN_TAG}/FV`. So in our case it would be: -``` -$ ls -lh Build/OvmfX64/RELEASE_GCC5/FV/OVMF* --rw-r--r-- 1 kostr kostr 4.0M Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd --rw-r--r-- 1 kostr kostr 3.5M Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd --rw-r--r-- 1 kostr kostr 528K Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd -``` - -The OVMF firmware (a UEFI implementation for QEMU) is split into two files: -- OVMF_CODE.fd contains the actual UEFI firmware, -- OVMF_VARS.fd is a "template" used to emulate persistent NVRAM storage. - -All VM instances can share the same system-wide, read-only OVMF_CODE.fd file from the ovmf package, but each instance needs a private, writable copy of OVMF_VARS.fd. - -Let's install QEMU to test our build artifacts: -``` -sudo apt-get install qemu-system-x86_64 -``` - -Lets execute QEMU to run our binaries: -``` -$ qemu-system-x86_64 -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd \ - -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd \ - -nographic \ - -net none -``` - -Hopefully you'll see UEFI Interactive Shell: -``` -ïI 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> -``` - -To exit QEMU run `CTRL+A - X` - -The QEMU run script can be simplified to: -``` -$ qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \ - -nographic \ - -net none -``` - -More info about OVMF can be found at https://github.com/tianocore/edk2/blob/master/OvmfPkg/README diff --git a/Lesson_00/README.md b/Lesson_00/README.md new file mode 100644 index 0000000..a45b5ae --- /dev/null +++ b/Lesson_00/README.md @@ -0,0 +1,98 @@ +First install necessary packages to your distro. +For the TianoCore compilation you'll need: +- nasm - The Netwide Assembler (NASM) is an assembler and disassembler for the Intel x86 architecture. It can be used to write 16-bit, 32-bit (IA-32) and 64-bit (x86-64) programs. NASM is considered to be one of the most popular assemblers for Linux, +- iasl - Intel ACPI compiler/decompiler. Advanced Configuration and Power Interface (ACPI) provides an open standard that operating systems can use to discover and configure computer hardware components, to perform power management and to perform status monitoring. UEFI firmware provides ACPI configuration tables to OS. ACPI specification can be found at https://uefi.org/specifications, +- uuid-dev - Universally Unique ID library. A universally unique identifier (UUID) is a 128-bit label used for identification of various components in UEFI. The term globally unique identifier (GUID) is also used, +- python3 - Python 3 interpreter is needed as build infrastructure includes python scripts. + +This is how you install these packages in Ubuntu: +``` +$ sudo apt-get install -y nasm iasl uuid-dev python3 +``` + +Then it is necessary to clone edk2 repo and update all its submodules: +``` +$ git clone https://github.com/tianocore/edk2 +$ cd edk2 +$ git submodule update --init +``` + +Just in case the size of the edk2 folder after that would be ~867M (as for 12-06-2021). + +Next we need to compile EDK2 build tools: +``` +make -C BaseTools +``` + +To initiate a build we need to source `edksetup.sh` script to get necessary variables into our environment: +``` +$ . edksetup.sh +Loading previous configuration from /<...>/edk2/Conf/BuildEnv.sh +Using EDK2 in-source Basetools +WORKSPACE: /<...>/edk2 +EDK_TOOLS_PATH: /<...>/edk2/BaseTools +CONF_PATH: /<...>/edk2/Conf +``` + +After that we could use `build` command to build EDK2 packages. +Try to execute help command to see all available options: +``` +build --help +``` + +Next we want to build the Open Virtual Machine Firmware (OVMF). OVMF is a port of tianocore firmware to the qemu virtual machine. This allows easy debugging and experimentation with UEFI firmware; either for testing OS booting or using the (included) EFI shell. We would be writing various EFI programs, and OVMF is an easy way to test them. We could install it with the package manager with something like `sudo apt-get install ovmf`, but it is not fun. + +To build OVMF execute: +``` +build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=RELEASE --tagname=GCC5 +``` + +If build is successful, result would be in the folder `Build/{Platform Name}/{TARGET}_{TOOL_CHAIN_TAG}/FV`. So in our case it would be: +``` +$ ls -lh Build/OvmfX64/RELEASE_GCC5/FV/OVMF* +-rw-r--r-- 1 kostr kostr 4.0M Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd +-rw-r--r-- 1 kostr kostr 3.5M Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd +-rw-r--r-- 1 kostr kostr 528K Jun 12 21:03 Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd +``` + +The OVMF firmware (a UEFI implementation for QEMU) is split into two files: +- OVMF_CODE.fd contains the actual UEFI firmware, +- OVMF_VARS.fd is a "template" used to emulate persistent NVRAM storage. + +All VM instances can share the same system-wide, read-only OVMF_CODE.fd file from the ovmf package, but each instance needs a private, writable copy of OVMF_VARS.fd. + +Let's install QEMU to test our build artifacts: +``` +sudo apt-get install qemu-system-x86_64 +``` + +Lets execute QEMU to run our binaries: +``` +$ qemu-system-x86_64 -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd \ + -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd \ + -nographic \ + -net none +``` + +Hopefully you'll see UEFI Interactive Shell: +``` +ïI 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> +``` + +To exit QEMU run `CTRL+A - X` + +The QEMU run script can be simplified to: +``` +$ qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \ + -nographic \ + -net none +``` + +More info about OVMF can be found at https://github.com/tianocore/edk2/blob/master/OvmfPkg/README diff --git a/Lesson_01/README.md b/Lesson_01/README.md new file mode 100644 index 0000000..2f7d3ce --- /dev/null +++ b/Lesson_01/README.md @@ -0,0 +1,138 @@ +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 includes `UefiApplicationEntryPoint` 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:\> +``` + + diff --git a/Lesson_01/SimplestApp/SimplestApp.c b/Lesson_01/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_01/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_01/SimplestApp/SimplestApp.inf b/Lesson_01/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_01/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_02/README.md b/Lesson_02/README.md new file mode 100644 index 0000000..c91e47e --- /dev/null +++ b/Lesson_02/README.md @@ -0,0 +1,154 @@ +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:\> +``` diff --git a/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_02/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_02/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_02/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..61378d6 --- /dev/null +++ b/Lesson_02/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,23 @@ +[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 + +[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 + diff --git a/Lesson_03/README.md b/Lesson_03/README.md new file mode 100644 index 0000000..f0aef2e --- /dev/null +++ b/Lesson_03/README.md @@ -0,0 +1,168 @@ +Finally we are ready to write our "Hello World" app. + +First we create a new edk2 module in our package directory similar to the our `SimplestApp` module: +``` +$ mkdir UefiLessonsPkg/HelloWorld +$ vi UefiLessonsPkg/HelloWorld/HelloWorld.inf +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint +``` +Don't forget to add our newly created app to the `Components` section of the package DSC file +``` +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf ++ UefiLessonsPkg/HelloWorld/HelloWorld.inf +``` +Next we need to write the source code file. Let's remember the code for our SimplestApp: +``` +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +``` +To print something to the console ("Hello World" message in our case) we need to use services from the `EFI_SYSTEM_TABLE` that is passed to the entry point of our app. + +The description of the `EFI_SYSTEM_TABLE` can be found in the UEFI specification (https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf). + +EFI_SYSTEM_TABLE is a struct that was populated by the UEFI firmware and contains pointers to the runtime and boot services tables. +``` +typedef struct { + EFI_TABLE_HEADER Hdr; + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + EFI_HANDLE ConsoleInHandle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + EFI_HANDLE StandardErrorHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; +``` +We are interested in the `ConOut` field. `ConOut` is abbreviaton for "Console Output" and according to the UEFI spec it is a pointer to the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` interface that is associated with `ConsoleOutHandle`. + +If we keep digging into UEFI spec we can find description of the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL`. +According to the spec `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` defines the minimum requirements for a text-based ConsoleOut device. + +As everything in UEFI it has GUID: +``` +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + {0x387477c2,0x69c7,0x11d2,\ + {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b}} +``` + +And the interface description is: +``` +typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { + EFI_TEXT_RESET Reset; + EFI_TEXT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + SIMPLE_TEXT_OUTPUT_MODE *Mode; +} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; +``` +Right now we are interested in a `OutputString` method: +``` +OutputString Displays the string on the device at the current cursor location. +``` +This is what we need. Let's look at the function description: +``` +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString() + +Summary +Writes a string to the output device. + +Prototype +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_STRING) ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +Parameters +This A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. +String The Null-terminated string to be displayed on the output device(s). +``` + +In edk2 `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` is defined in the header file: +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/SimpleTextOut.h + + +With all this knowledge we can write our source code file `UefiLessonsPkg/HelloWorld/HelloWorld.c`: +``` +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + return EFI_SUCCESS; +} +``` + +The `L""` signifies that the string is composed from CHAR16 symbols, as was required in spec. + +Let's compile our edk2 module: +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ + --arch=X64 \ + --buildtarget=RELEASE --tagname=GCC5 +``` + +Copy the app to our `UEFI_disk` folder and run OVMF: +``` +$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/HelloWorld.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 +``` + +``` +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:\> HelloWorld.efi +Hello World! +FS0:\> +``` diff --git a/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..399b0ac --- /dev/null +++ b/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..95924c5 --- /dev/null +++ b/Lesson_03/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,17 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + diff --git a/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_03/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_03/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_03/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..91a79e6 --- /dev/null +++ b/Lesson_03/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,26 @@ +[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 + + +[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 + UefiLessonsPkg/HelloWorld/HelloWorld.inf + + diff --git a/Lesson_04/README.md b/Lesson_04/README.md new file mode 100644 index 0000000..8892c28 --- /dev/null +++ b/Lesson_04/README.md @@ -0,0 +1,229 @@ +In this lesson we keep working on our 'Hello World' app. + +It is kinda tedious to write such a long string for a simple printf: +``` + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); +``` + +So let's try to simplify it. + +First in UEFI/edk2 you would be using a lot this `SystemTable` pointer as well as its filed `SystemTable->BootServices` and another main function parameter `ImageHandle`. + +So simplify access to these variables edk2 library create global defines for them gST, gBS, gImageHandle. + +You could look at the source of the UefiBootServicesTableLib.c: + +https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c + +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/UefiBootServicesTableLib.h + +``` +EFI_HANDLE gImageHandle = NULL; +EFI_SYSTEM_TABLE *gST = NULL; +EFI_BOOT_SERVICES *gBS = NULL; + +EFI_STATUS +EFIAPI +UefiBootServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache the Image Handle + // + gImageHandle = ImageHandle; + ASSERT (gImageHandle != NULL); + + // + // Cache pointer to the EFI System Table + // + gST = SystemTable; + ASSERT (gST != NULL); + + // + // Cache pointer to the EFI Boot Services Table + // + gBS = SystemTable->BootServices; + ASSERT (gBS != NULL); + + return EFI_SUCCESS; +} +``` + +Let's try to use them in our function: + +``` +gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); +``` + +And try to recompile: +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ + --arch=X64 \ + --buildtarget=RELEASE --tagname=GCC5 +``` + +Unfortunately this will not compile: +``` +/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c: In function ‘UefiMain’: +/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c:12:3: error: ‘gST’ undeclared (first use in this function) + 12 | gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + | ^~~ +``` + +This error message is familiar, we'are missing some `#include` in our file, so let's add it: +``` +#include +``` + +This library is already included in our *.dsc file, so we are good to go: +``` +[LibraryClasses] + ... + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + ... +``` + +Our source code file at this point is: +``` +// for gBS +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + return EFI_SUCCESS; +} +``` + +Test for the successful compilation: +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ + --arch=X64 \ + --buildtarget=RELEASE --tagname=GCC5 +``` + +In the case of printf we can simplify things even more. Print is such a common function, that there is a library function for it in edk2. Add this to our file: +``` +Print(L"Bye!\n"); +``` + +If we try to recompile we would get error message about missing `#include` once again: +``` +/home/kostr/tiano/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c: In function ‘UefiMain’: +/home/kostr/tiano/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c:13:3: error: implicit declaration of function ‘Print’ [-Werror=implicit-function-declaration] + 13 | Print(L"Bye!\n"); + | ^~~~~ +``` + +In this case header and source file for the `Print` function are: +- https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/UefiLib.h +- https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiLib/UefiLibPrint.c + +So let's include `UefiLib.h` in our file: +``` +#include +``` +And try to recompile. +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ + --arch=X64 \ + --buildtarget=RELEASE --tagname=GCC5 +``` + +Build would fail with a message: +``` +/home/kostr/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c:821: undefined reference to `Print' +collect2: error: ld returned 1 exit status +make: *** [GNUmakefile:307: /home/kostr/edk2/Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll] Error 1 +``` + +Compilation step was successful, but the linker have failed. This usually means that *.h file was in place, but the actual library wasn't linked. + +``` +$ grep UefiLib -r ./ --include=*.inf | grep LIBRARY_CLASS +./MdePkg/Library/UefiLib/UefiLib.inf: LIBRARY_CLASS = UefiLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE +``` + +Add this to our `UefiLessonsPkg/UefiLessonsPkg.dsc` file: +``` +[LibraryClasses] + ... ++ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf +``` +And this string to our `UefiLessonsPkg/HelloWorld/HelloWorld.inf` file: +``` +[LibraryClasses] + UefiApplicationEntryPoint ++ UefiLib +``` + +If we try to build, we will get `Failed` once again: +``` +/home/kostr/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 4000: Instance of library class [MemoryAllocationLib] is not found + in [/home/kostr/edk2/MdePkg/Library/UefiLib/UefiLib.inf] [X64] + consumed by module [/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.inf] +``` + +Try to find it: +``` +$ grep MemoryAllocationLib -r ./ --include=*.inf | grep LIBRARY_CLASS | grep MdePkg +./MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|PEIM PEI_CORE SEC +./MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|DXE_SMM_DRIVER +./MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER +``` + +Add this to our *.dsc file: +``` +[LibraryClasses] + ... ++ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf +``` + +After that we would get another build failure with the similar message. So we need to repeat this process of finding right library. In the end we would need to add two more libraries: +``` +[LibraryClasses] + ... ++ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf ++ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf +``` + +After that finally build would finish successfully. + +Test it: +``` +cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/HelloWorld.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 +``` +``` +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 1 seconds to skip startup.nsh or any other key to continue. +Shell> fs0: +FS0:\> HelloWorld.efi +Hello World! +Hello again! +Bye! +FS0:\> +``` diff --git a/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_04/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_04/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_04/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_04/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..0a2edbe --- /dev/null +++ b/Lesson_04/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,30 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + + diff --git a/Lesson_05/Conf/target.txt b/Lesson_05/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lesson_05/Conf/target.txt @@ -0,0 +1,7 @@ +ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc +TARGET = RELEASE +TARGET_ARCH = X64 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = GCC5 +BUILD_RULE_CONF = Conf/build_rule.txt + diff --git a/Lesson_05/README.md b/Lesson_05/README.md new file mode 100644 index 0000000..23130f4 --- /dev/null +++ b/Lesson_05/README.md @@ -0,0 +1,53 @@ +To build modules in our package we've used something like this: +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ + --arch=X64 \ + --buildtarget=RELEASE \ + --tagname=GCC5 +``` + +This is kinda long string. Let's simplify it. + +First we can omit `module` option from the command and always compile our package entirely with all its modules: + +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ + --arch=X64 \ + --buildtarget=RELEASE \ + --tagname=GCC5 +``` + +When we initiate our environment with: +``` +. edk2setup.sh +``` +`Conf` directory is created in the edk2 folder. This directory is populated with a bunch of files. +Also the `CONF_PATH` environment variable is created which points to the newly created `Conf` folder. + +Right now we are interested in the `Conf/target.txt` file. +By default it has many comments (lines that start with `#` symbol) and is prepopulated with these values: +``` +ACTIVE_PLATFORM = EmulatorPkg/EmulatorPkg.dsc +TARGET = DEBUG +TARGET_ARCH = IA32 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = VS2015x86 +BUILD_RULE_CONF = Conf/build_rule.txt +``` + +We can put all our build command options in this file to simplify our everyday life. +``` +ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc +TARGET = RELEASE +TARGET_ARCH = X64 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = GCC5 +BUILD_RULE_CONF = Conf/build_rule.txt +``` + +After that we could build our package with all its modules with the one single command: +``` +build +``` + diff --git a/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_05/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_05/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_05/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_05/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..0a2edbe --- /dev/null +++ b/Lesson_05/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,30 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + + diff --git a/Lesson_06/Conf/target.txt b/Lesson_06/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lesson_06/Conf/target.txt @@ -0,0 +1,7 @@ +ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc +TARGET = RELEASE +TARGET_ARCH = X64 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = GCC5 +BUILD_RULE_CONF = Conf/build_rule.txt + diff --git a/Lesson_06/Handle_Protocol_databases_scheme.jpg b/Lesson_06/Handle_Protocol_databases_scheme.jpg new file mode 100644 index 0000000..771a981 Binary files /dev/null and b/Lesson_06/Handle_Protocol_databases_scheme.jpg differ diff --git a/Lesson_06/README.md b/Lesson_06/README.md new file mode 100644 index 0000000..3bd7b83 --- /dev/null +++ b/Lesson_06/README.md @@ -0,0 +1,243 @@ +Let's create `ImageHandle` app in our `UefiLessonsPkg`. + +First generate a random GUID. +``` +$ uuidgen +b68d3472-70c7-4928-841b-6566032e0a23 +``` + +And then create *.inf and *.c file based on the code in our `HelloWorld` app: +``` +$ cat UefiLessonsPkg/ImageHandle/ImageHandle.inf +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageHandle + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageHandle.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib +``` +``` +$ cat UefiLessonsPkg/ImageHandle/ImageHandle.c +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +``` +Add a newly created app to our `UefiLessonsPkg/UefiLessonsPkg.dsc` file: +``` +[Components] + ... ++ UefiLessonsPkg/ImageHandle/ImageHandle.inf +``` + +Now let's get to work. + +Our main function in a *.c file has 2 input parameters `EFI_HANDLE ImageHandle` and `EFI_SYSTEM_TABLE *SystemTable`: +``` +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +``` +We've already started to explore the `EFI_SYSTEM_TABLE`. In this lesson let's look what `ImageHandle` is about. + +`ImageHandle` parameter is a handle of an image for the program itself. + +You can found a definition for a `EFI_HANDLE` type in a https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiBaseType.h +``` +/// +/// A collection of related interfaces. +/// +typedef VOID *EFI_HANDLE; +``` +So it is simply a pointer to a void. So it could be a pointer to anything. + +In a reality it is a pointer to this type of structure https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Hand/Handle.h : +``` +#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l') + +/// +/// IHANDLE - contains a list of protocol handles +/// +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; +``` +LIST_ENTRY is a double linked list. So with it we can traverse to any handle in the system. Sometimes it is called the Handle database. + +In case you wonder how LIST_ENTRY is defined look at the https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h : +``` +/// +/// LIST_ENTRY structure definition. +/// +typedef struct _LIST_ENTRY LIST_ENTRY; + +/// +/// _LIST_ENTRY structure definition. +/// +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; +``` +Each handle has a list of protocols attached to it. Protocol is like an interface - a set of functions and data fields. To track the list of protocols attached to a handle this field is used: +``` + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; +``` +It is another double linked list that points to these structures: +``` +#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c') + +/// +/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked +/// with a protocol interface structure +/// +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; +``` + +Effectively PROTOCOL_INTERFACE structure is only a proxy that points to an actual PROTOCOL_ENTRY structrure which are exist in a separate protocol database. +``` +#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e') + +/// +/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol +/// database. Each handler that supports this protocol is listed, along +/// with a list of registered notifies. +/// +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; +``` +It all sounds a little bit complicated so it is better to see it in a picture: +![Handle_Protocol_databases_scheme](Handle_Protocol_databases_scheme.jpg?raw=true "Handle/Protocol databases scheme") +Important information from the picture: +- HANDLE 0 has PROTOCOL_INTERFACE 0 (->PROTOCOL_ENTRY 0) and PROTOCOL_INTERFACE 1 (->PROTOCOL_ENTRY 1) +- HANDLE 1 has PROTOCOL_INTERFACE 2 (->PROTOCOL_ENTRY 2) and PROTOCOL_INTERFACE 3 (->PROTOCOL_ENTRY 1) +- HANDLE 2 has PROTOCOL_INTERFACE 4 (->PROTOCOL_ENTRY 1) +Besides that: +- All handles are interconnected with the help of `AllHandles` field in each `IHANDLE` structure +- All protocols are interconnected with the help of `AllEntries` field in each `PROTOCOL_ENTRY` structure +Red lines: +- Each handle has a double linked list of all its PROTOCOL_INTERFACES, which internally connected to each other through the `Link` field +Green lines: +- Each protocol entry effectively knows all the users (=PROTOCOL_INTERFACES) of it. + +Let's check that `EFI_HANDLE ImageHandle` effectively is the `IHANDLE` structure. + +To check this we will cast `ImageHandle` to `IHANDLE` and print its signature. + +``` +#include +#include + + +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + return EFI_SUCCESS; +} +``` + +Don't blame me for redefinition of `IHANDLE` structure. These structures (IHANDLE/PROTOCOL_ENTRY/PROTOCOL_INTERFACE) are private and not intended to be used outside of the `MdeModulePkg`. Even https://github.com/tianocore/edk2/blob/master/StandaloneMmPkg/Core/StandaloneMmCore.h redifines IHANDLE/PROTOCOL_ENTRY/PROTOCOL_INTERFACE. + +``` +$ . edksetup.sh +$ build +$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/ImageHandle.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 +``` + +``` +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:\> ImageHandle.efi +Signature: h n d l +``` + + + diff --git a/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..e869e28 --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c @@ -0,0 +1,30 @@ +#include +#include + + +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + return EFI_SUCCESS; +} diff --git a/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf new file mode 100644 index 0000000..34256ee --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageHandle + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageHandle.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..0d4fbb0 --- /dev/null +++ b/Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,31 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + UefiLessonsPkg/ImageHandle/ImageHandle.inf + + diff --git a/Lesson_07/Conf/target.txt b/Lesson_07/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lesson_07/Conf/target.txt @@ -0,0 +1,7 @@ +ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc +TARGET = RELEASE +TARGET_ARCH = X64 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = GCC5 +BUILD_RULE_CONF = Conf/build_rule.txt + diff --git a/Lesson_07/README.md b/Lesson_07/README.md new file mode 100644 index 0000000..66e8689 --- /dev/null +++ b/Lesson_07/README.md @@ -0,0 +1,229 @@ +Let's print GUID for all the protocols that are exist in our `IMAGE_HANDLE`. + +First understand what `EFI_GUID` internally means in the edk2 codebase: + +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiBaseType.h +``` +/// +/// 128-bit buffer containing a unique identifier value. +/// +typedef GUID EFI_GUID; +``` +`GUID` structure is defined in https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h : +``` +/// +/// 128 bit buffer containing a unique identifier value. +/// Unless otherwise specified, aligned on a 64 bit boundary. +/// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; +``` +Fortunately we don't have to manually print all these fields by hand. `Print` function has a format option `%g` to print GUIDs, so we could simply print GUIDs with a code like this: +``` +Print("GUID=%g\n", myGUID); +``` +More information about `Print` formating options can be found at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PrintLib.h + + +We want to print `EFI_GUID` field from the `PROTOCOL_ENTRY` structure which are referred from the `PROTOCOL_INTERFACE` structures. So we need to define both of these structures in our file for the same reason we've defined `IHANDLE` earlier. + +``` +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; +``` + +`PROTOCOL_INTERFACE` structures that are connected to any HANDLE are interlinked with each other with a help of a `LIST_ENTRY Link` field that connects them to a double linked list. + +As you may remember `LIST_ENTRY` is defined like this: +``` +/// +/// LIST_ENTRY structure definition. +/// +typedef struct _LIST_ENTRY LIST_ENTRY; + +/// +/// _LIST_ENTRY structure definition. +/// +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; +``` +Each of these fields inside these structure points to another `LIST_ENTRY` structure that is placed in another `PROTOCOL_INTERFACE`. + +So this connection looks like this: + +``` +typedef struct { typedef struct { + UINTN Signature; UINTN Signature; + struct LIST_ENTRY { |---------> struct LIST_ENTRY { + LIST_ENTRY *ForwardLink; -----------------| LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; LIST_ENTRY *BackLink; + } Link; } Link; + IHANDLE *Handle; IHANDLE *Handle; + LIST_ENTRY ByProtocol; LIST_ENTRY ByProtocol; + PROTOCOL_ENTRY *Protocol; PROTOCOL_ENTRY *Protocol; + VOID *Interface; VOID *Interface; + LIST_ENTRY OpenList; LIST_ENTRY OpenList; + UINTN OpenListCount; UINTN OpenListCount; +} PROTOCOL_INTERFACE; } PROTOCOL_INTERFACE; +``` + +But in reality we want a pointer not to `Link` field of another `PROTOCOL_INTERFACE` structure, we want a pointer to another `PROTCOL_INTERFACE` structure inself. + +Therefore one more thing that we would need is a couple of macros: +``` +#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +``` +These macros can be familiar to you if you've investigated linux kernel programming. This is where I got them from anyway. + +`contianer_of` macro helps to get a pointer to a structure if you have a pointer to one of its fields. + +If you want to understand how it works internally in C language I suggest you to look at the https://stackoverflow.com/questions/15832301/understanding-container-of-macro-in-the-linux-kernel + +With all of this information final code for our `UefiMain` function would look like this: +``` +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); + Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); + + LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; + LIST_ENTRY *CurrentLink = FirstLink; + do { + PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); + + Print(L"\n"); + Print(L"Current Link: %p\n", CurrentLink); + Print(L"Signature: %c %c %c %c\n", (MyProtocolInterface->Signature >> 0) & 0xff, + (MyProtocolInterface->Signature >> 8) & 0xff, + (MyProtocolInterface->Signature >> 16) & 0xff, + (MyProtocolInterface->Signature >> 24) & 0xff); + + Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); + Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); + Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); + CurrentLink = MyProtocolInterface->Link.ForwardLink; + } while (CurrentLink != FirstLink); + + return EFI_SUCCESS; +} +``` + +If we compile and run our app in OVMF (I hope at this time I don't need to repeat how to do it): +``` +FS0:\> ImageHandle.efi +h n d l +Back Protocol Interface Link: 68D4320 +Forward Protocol Interface Link: 6891520 + +Current Link: 6891520 +p i f c +Back Link: 6891430 +Forward Link: 6891B20 +GUID=752F3136-4E16-4FDC-A22A-E5F46812F4CA + +Current Link: 6891B20 +p i f c +Back Link: 6891520 +Forward Link: 68D4320 +GUID=BC62157E-3E33-4FEC-9920-2D3B36D750DF + +Current Link: 68D4320 +p i f c +Back Link: 6891B20 +Forward Link: 6891430 +GUID=5B1B31A1-9562-11D2-8E3F-00A0C969723B + +Current Link: 6891430 + ? ? ? +Back Link: 68D4320 +Forward Link: 6891520 +GUID=00000000-0000-0000-0000-000000000000 +``` + +Let's find first GUID by executing grep on the edk2 source: +``` +$ grep -i 752F3136 -r ./ --exclude-dir=Build +./MdePkg/Include/Protocol/ShellParameters.h: 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ +./MdePkg/MdePkg.dec: gEfiShellParametersProtocolGuid = { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca }} +``` + +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/ShellParameters.h +``` +#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ + { \ + 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ + } +``` +You can also see in in a https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec file: +``` + ## Include/Protocol/ShellParameters.h + gEfiShellParametersProtocolGuid = { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca }} +``` + +The next two GUIDs you can find in UEFI the specification. + +`EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL` - When installed, the Loaded Image Device Path Protocol specifies the device path that was used when a PE/COFF image was loaded through the EFI Boot Service LoadImage(). + +``` +#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ +{0xbc62157e,0x3e33,0x4fec,\ + {0x99,0x20,0x2d,0x3b,0x36,0xd7,0x50,0xdf}} +``` + +`EFI_LOADED_IMAGE_PROTOCOL` - Can be used on any image handle to obtain information about the loaded image. +``` +#define EFI_LOADED_IMAGE_PROTOCOL_GUID\ + {0x5B1B31A1,0x9562,0x11d2,\ + {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}} +``` + +The last `PROTOCOL_INTERFACE` structure doesn't have a valid "p i f c" signature (in my case it is 0x20 0x0E 0xED 0x06), so we don't need to look at its GUID. + diff --git a/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..bcf42e3 --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c @@ -0,0 +1,88 @@ +#include +#include + + +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; + + +#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); + Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); + + LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; + LIST_ENTRY *CurrentLink = FirstLink; + do { + PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); + + Print(L"\n"); + Print(L"Current Link: %p\n", CurrentLink); + Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, + (MyProtocolInterface->Signature >> 8) & 0xff, + (MyProtocolInterface->Signature >> 16) & 0xff, + (MyProtocolInterface->Signature >> 24) & 0xff); + + Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); + Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); + Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); + CurrentLink = MyProtocolInterface->Link.ForwardLink; + } while (CurrentLink != FirstLink); + + return EFI_SUCCESS; +} diff --git a/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf new file mode 100644 index 0000000..34256ee --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageHandle + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageHandle.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..0d4fbb0 --- /dev/null +++ b/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,31 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + UefiLessonsPkg/ImageHandle/ImageHandle.inf + + diff --git a/Lesson_08/DevicePath.png b/Lesson_08/DevicePath.png new file mode 100644 index 0000000..225226f Binary files /dev/null and b/Lesson_08/DevicePath.png differ diff --git a/Lesson_08/README.md b/Lesson_08/README.md new file mode 100644 index 0000000..fd31bcf --- /dev/null +++ b/Lesson_08/README.md @@ -0,0 +1,269 @@ +Let's explore protocols associated with our `ImageHandle` that we've discovered in the last lesson. + +If we try to grep GUIDs in the edk2 source code: +``` +$ grep -i bc62157e -r ./ --exclude-dir=Build +./MdePkg/Include/Protocol/LoadedImage.h: 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \ +./MdePkg/MdePkg.dec: gEfiLoadedImageDevicePathProtocolGuid = { 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf }} +$ grep -i 5B1B31A1 -r ./ --exclude-dir=Build +./MdePkg/Include/Protocol/LoadedImage.h: 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ +./MdePkg/MdePkg.dec: gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} +``` + +Link to the header file: https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/LoadedImage.h + +Description for one of these protocol structures can be found in the same file: +``` +/// +/// Can be used on any image handle to obtain information about the loaded image. +/// +typedef struct { + UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure. + ///< All future revisions will be backward compatible to the current revision. + EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from + ///< the firmware's boot manager. + EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer. + + // + // Source location of image + // + EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from. + EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle + ///< that the EFI Image was loaded from. + VOID *Reserved; ///< Reserved. DO NOT USE. + + // + // Images load options + // + UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions. + VOID *LoadOptions; ///< A pointer to the image's binary load options. + + // + // Location of where image was loaded + // + VOID *ImageBase; ///< The base address at which the image was loaded. + UINT64 ImageSize; ///< The size in bytes of the loaded image. + EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as. + EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as. + EFI_IMAGE_UNLOAD Unload; +} EFI_LOADED_IMAGE_PROTOCOL; +``` + +UEFI specification gives following description for this protocol: +``` +Each loaded image has an image handle that supports EFI_LOADED_IMAGE_PROTOCOL. When an image is started, it is passed the image handle for itself. The image can use the handle to obtain its relevant image data stored in the EFI_LOADED_IMAGE_PROTOCOL structure, such as its load options +``` + +Another GUID stands for the `EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL` - When installed, the Loaded Image Device Path Protocol specifies the device path that was used when a PE/COFF image was loaded through the EFI Boot Service LoadImage(). +The Loaded Image Device Path Protocol uses the same protocol interface structure as the Device Path Protocol. The only difference between the Device Path Protocol and the Loaded Image Device Path Protocol is the protocol GUID value. +The Loaded Image Device Path Protocol must be installed onto the image handle of a PE/COFF image loaded through the EFI Boot Service LoadImage(). A copy of the device path specified by the DevicePath parameter to the EFI Boot Service LoadImage() is made before it is installed onto the image handle. It is legal to call LoadImage() for a buffer in memory with a NULL DevicePath parameter. In this case, the Loaded Image Device Path Protocol is installed with a NULL interface pointer. + +So effectively if you want to look up the definition for this protocol you should search `EFI_DEVICE_PATH_PROTOCOL`. + +It is defined in edk2 sources here https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/DevicePath.h : +``` +/** + This protocol can be used on any device handle to obtain generic path/location + information concerning the physical device or logical device. If the handle does + not logically map to a physical device, the handle may not necessarily support + the device path protocol. The device path describes the location of the device + the handle is for. The size of the Device Path can be determined from the structures + that make up the Device Path. +**/ +typedef struct { + UINT8 Type; ///< 0x01 Hardware Device Path. + ///< 0x02 ACPI Device Path. + ///< 0x03 Messaging Device Path. + ///< 0x04 Media Device Path. + ///< 0x05 BIOS Boot Specification Device Path. + ///< 0x7F End of Hardware Device Path. + + UINT8 SubType; ///< Varies by Type + ///< 0xFF End Entire Device Path, or + ///< 0x01 End This Instance of a Device Path and start a new + ///< Device Path. + + UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define + ///< type of data. Size of data is included in Length. + +} EFI_DEVICE_PATH_PROTOCOL; +``` +This structure is like a header to an actual path data which immediately follows it for amount of `Length` bytes. +![Device path](DevicePath.png?raw=true "Device Path in memory") + + +Now we have understanding of all the protocol structures, it is time to know the right way of how to get to them. +The "raw" method that we've used in last lessons was purely educational. +UEFI has several functions to help to get the protocol structures in a code. + +`EFI_BOOT_SERVICES.HandleProtocol()` - Queries a handle to determine if it supports a specified protocol. + +UEFI docs: +``` +Prototype: + +typedef +EFI_STATUS +(EFIAPI *EFI_HANDLE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface +); + +Parameters: +Handle The handle being queried. If Handle isNULL, then EFI_INVALID_PARAMETER is returned. +Protocol The published unique identifier of the protocol. It is the caller’s responsibility to pass in a valid GUID. +Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. + NULL will be returned in *Interface if a structure is not associated with Protocol. + +Description: +The HandleProtocol() function queries Handle to determine if it supports Protocol. If it does, then on return Interface points to a pointer to the corresponding Protocol Interface. Interface can then be passed to any protocol service to identify the context of the request. + +Status Codes Returned: +EFI_SUCCESS The interface information for the specified protocol was returned. +EFI_UNSUPPORTED The device does not support the specified protocol. +EFI_INVALID_PARAMETER Handle is NULL.. +EFI_INVALID_PARAMETER Protocol is NULL. +EFI_INVALID_PARAMETER Interface is NULL. +``` + + +With all this info let's write source code for our new `ImageInfo` app: +``` +#include +#include + +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + if (Status == EFI_SUCCESS) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID**) &DevicePath + ); + + if (Status == EFI_SUCCESS) { + Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); + Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); + Print(L"Image Base: %X\n", LoadedImage->ImageBase); + Print(L"Image Size: %X\n", LoadedImage->ImageSize); + } else { + Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); + } + } else { + Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); + } + return EFI_SUCCESS; +} +``` + +Some new important things: +- `gBS` is a global variable which is a shortcut for the `SystemTable->BootServices` a table which contains UEFI services produced by UEFI firmware. These services are only valid in pre-OS environment opposed to the `gRT=SystemTable->RuntimeServices` +- `EFI_STATUS` variable can be printed with the help of "%r" formatting option (see https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PrintLib.h) +- `ConvertDevicePathToText` can be used to convert device path to a string. +It is defined here: +https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c +With a header file https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DevicePathLib.h : +``` +/** + Converts a device path to its text representation. + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. +**/ +CHAR16 * +EFIAPI +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); +``` + +Ok, let's try to compile our app. +``` +. edksetup.sh +build +``` + +Unfortunately build would fail: +``` +/home/kostr/tiano/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:16: undefined reference to `gEfiLoadedImageProtocolGuid' +/usr/bin/ld: /tmp/ImageInfo.dll.JKxzWu.ltrans0.ltrans.o:/home/kostr/tiano/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:24: undefined reference to `gEfiLoadedImageDevicePathProtocolGuid' +``` + +To solve this error add `Protocols` section to the `UefiLessonsPkg/ImageInfo/ImageInfo.inf` file: +``` +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES +``` + +The [Protocols] section of the EDK II INF file is a list of the global Protocol C Names that are used by the module developer. These C names are used by the parsing utility to lookup the actual GUID value of the PROTOCOL that is located in the EDK II package DEC files, and then emit a data structure to the module's AutoGen.c file (https://edk2-docs.gitbook.io/edk-ii-inf-specification/2_inf_overview/29_-protocols-_section). + + +`## CONSUMES` is used to indicate usage of this protocol. It has no value other than informational. You can encounter values like this for example in the edk2 codebase: +``` +## CONSUMES +## PRODUCES +## ALWAYS_CONSUMES +## ALWAYS_PRODUCES +## SOMETIMES_PRODUCES +## SOMETIMES_PRODUCES +## NOTIFY +``` + +After we add these protocols to the *.inf file, the build will succeed. + +In case you wonder, our GUID variables will go to a file `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/ImageInfo/ImageInfo/DEBUG/AutoGen.c` which is automatically generated by the build system: +``` +// Protocols +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadedImageDevicePathProtocolGuid = { 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf }}; +``` + +If we try to execute our app under OVMF we would get 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 5 seconds to skip startup.nsh or any other key to continue. +Shell> fs0: +FS0:\> ImageInfo.efi +Image device: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\ImageInfo.efi +Image file: \ImageInfo.efi +Image Base: 6885000 +Image Size: 5140 +``` diff --git a/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..bcf42e3 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.c @@ -0,0 +1,88 @@ +#include +#include + + +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; + + +#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); + Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); + + LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; + LIST_ENTRY *CurrentLink = FirstLink; + do { + PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); + + Print(L"\n"); + Print(L"Current Link: %p\n", CurrentLink); + Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, + (MyProtocolInterface->Signature >> 8) & 0xff, + (MyProtocolInterface->Signature >> 16) & 0xff, + (MyProtocolInterface->Signature >> 24) & 0xff); + + Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); + Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); + Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); + CurrentLink = MyProtocolInterface->Link.ForwardLink; + } while (CurrentLink != FirstLink); + + return EFI_SUCCESS; +} diff --git a/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.inf new file mode 100644 index 0000000..34256ee --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/ImageHandle/ImageHandle.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageHandle + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageHandle.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.c b/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.c new file mode 100644 index 0000000..c45570e --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.c @@ -0,0 +1,44 @@ +#include +#include + +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + if (Status == EFI_SUCCESS) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID**) &DevicePath + ); + + if (Status == EFI_SUCCESS) { + Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); + Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); // EFI_DEVICE_PATH_PROTOCOL *FilePath + Print(L"Image Base: %X\n", LoadedImage->ImageBase); + Print(L"Image Size: %X\n", LoadedImage->ImageSize); + } else { + Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); + } + } else { + Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); + } + return EFI_SUCCESS; +} diff --git a/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.inf b/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.inf new file mode 100644 index 0000000..0ce54a6 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/ImageInfo/ImageInfo.inf @@ -0,0 +1,22 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageInfo + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageInfo.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiLoadedImageDevicePathProtocolGuid + diff --git a/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_08/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_08/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..ff2edf6 --- /dev/null +++ b/Lesson_08/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,32 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + UefiLessonsPkg/ImageHandle/ImageHandle.inf + UefiLessonsPkg/ImageInfo/ImageInfo.inf + + diff --git a/Lesson_09/Conf/target.txt b/Lesson_09/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lesson_09/Conf/target.txt @@ -0,0 +1,7 @@ +ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc +TARGET = RELEASE +TARGET_ARCH = X64 +TOOL_CHAIN_CONF = Conf/tools_def.txt +TOOL_CHAIN_TAG = GCC5 +BUILD_RULE_CONF = Conf/build_rule.txt + diff --git a/Lesson_09/README.md b/Lesson_09/README.md new file mode 100644 index 0000000..3b838d8 --- /dev/null +++ b/Lesson_09/README.md @@ -0,0 +1,148 @@ +The methods that we've used to discover protocols for our image handle were purely educational. + +Let's try UEFI API functions to get the same result. + +To do this we will need to understand `ProtocolsPerHandle` function: +``` +EFI_BOOT_SERVICES.ProtocolsPerHandle() + +Summary: +Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool. + +Prototype: +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) ( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + +Parameters: +Handle The handle from which to retrieve the list of protocol interface GUIDs. +ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are installed on Handle. This buffer is allocated with a call to the Boot Service EFI_BOOT_SERVICES.AllocatePool(). It is the caller's responsibility to call the Boot Service EFI_BOOT_SERVICES.FreePool() when the caller no longer requires the contents of ProtocolBuffer. +ProtocolBufferCountA pointer to the number of GUID pointers present in ProtocolBuffer. + +Description: +The ProtocolsPerHandle() function retrieves the list of protocol interface GUIDs that are installed on Handle. The list is returned in ProtocolBuffer, and the number of GUID pointers in ProtocolBuffer is returned in ProtocolBufferCount. +If Handle is NULL or Handle is NULL, then EFI_INVALID_PARAMETER is returned. +If ProtocolBuffer is NULL, then EFI_INVALID_PAREMETER is returned. +If ProtocolBufferCount is NULL, then EFI_INVALID_PARAMETER is returned. +If there are not enough resources available to allocate ProtocolBuffer, then EFI_OUT_OF_RESOURCES is +returned. + +Status Codes Returned: +EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. +EFI_INVALID_PARAMETER Handle is NULL. +EFI_INVALID_PARAMETER ProtocolBuffer is NULL. +EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. +EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. +``` + +This description mentions that we need manually deallocate received ProtocolBuffer, so lel's also look to the suggessted `FreePool` function: + +``` +EFI_BOOT_SERVICES.FreePool() + +Summary: +Returns pool memory to the system. + +Prototype: +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_POOL) ( + IN VOID *Buffer +); + +Parameters: +Buffer Pointer to the buffer to free. + +Description: +The FreePool() function returns the memory specified by Buffer to the system. On return, the +memory’s type is EfiConventionalMemory. The Buffer that is freed must have been allocated by +AllocatePool(). + +Status Codes Returned: +EFI_SUCCESS The memory was returned to the system. +EFI_INVALID_PARAMETER Buffer was invalid +``` + +Now when we know how to use API, let's add this code at the end of our `ImageHandle` app: +``` +Print(L"________\n"); +EFI_GUID **ProtocolGuidArray; +UINTN ArrayCount; +EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle, + &ProtocolGuidArray, + &ArrayCount); + +if (Status == EFI_SUCCESS) { + for (int i=0; i +``` + +Some may have noticed, that we've used `FreePool`, but not a `gBS->FreePool`. It is legit because `FreePool` is defined in the https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c file: +``` +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = gBS->FreePool (Buffer); + ASSERT_EFI_ERROR (Status); +} +``` +This is shortcut is neccessary as `FreePool` have different library implementations: +``` +MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c +MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c +MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c +``` +This is the example of LibraryClass that can have several possible instances. In our case we use `UefiMemoryAllocationLib` instance. + +UefiLessonsPkg/UefiLessonsPkg.dsc: +``` +[LibraryClasses] + ... + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ... +``` + +Now if we build and execute our app under OVMF this code will give us: +``` +752F3136-4E16-4FDC-A22A-E5F46812F4CA +BC62157E-3E33-4FEC-9920-2D3B36D750DF +5B1B31A1-9562-11D2-8E3F-00A0C969723B +``` +Which are the same GUIDs we've discovered through hardcore raw walkthrough through the handle/protocol databases. + + + diff --git a/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,15 @@ +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return EFI_SUCCESS; +} diff --git a/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,18 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = HelloWorld + FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + HelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..6117243 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/ImageHandle/ImageHandle.c @@ -0,0 +1,102 @@ +#include +#include +#include + +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; + + +#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + IHANDLE* MyHandle = ImageHandle; + Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, + (MyHandle->Signature >> 8) & 0xff, + (MyHandle->Signature >> 16) & 0xff, + (MyHandle->Signature >> 24) & 0xff); + + Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); + Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); + + LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; + LIST_ENTRY *CurrentLink = FirstLink; + do { + PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); + + Print(L"\n"); + Print(L"Current Link: %p\n", CurrentLink); + Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, + (MyProtocolInterface->Signature >> 8) & 0xff, + (MyProtocolInterface->Signature >> 16) & 0xff, + (MyProtocolInterface->Signature >> 24) & 0xff); + + Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); + Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); + Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); + CurrentLink = MyProtocolInterface->Link.ForwardLink; + } while (CurrentLink != FirstLink); + + Print(L"________\n"); + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle, + &ProtocolGuidArray, + &ArrayCount); + + if (Status == EFI_SUCCESS) { + for (int i=0; i +#include + +#include +#include + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + if (Status == EFI_SUCCESS) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID**) &DevicePath + ); + + if (Status == EFI_SUCCESS) { + Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); + Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); // EFI_DEVICE_PATH_PROTOCOL *FilePath + Print(L"Image Base: %X\n", LoadedImage->ImageBase); + Print(L"Image Size: %X\n", LoadedImage->ImageSize); + } else { + Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); + } + } else { + Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); + } + return EFI_SUCCESS; +} diff --git a/Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.inf b/Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.inf new file mode 100644 index 0000000..0ce54a6 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/ImageInfo/ImageInfo.inf @@ -0,0 +1,22 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageInfo + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageInfo.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiLoadedImageDevicePathProtocolGuid + diff --git a/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + diff --git a/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[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 diff --git a/Lesson_09/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_09/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..ff2edf6 --- /dev/null +++ b/Lesson_09/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,32 @@ +[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 + + +[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 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + UefiLessonsPkg/ImageHandle/ImageHandle.inf + UefiLessonsPkg/ImageInfo/ImageInfo.inf + + diff --git a/Lesson_1/README.md b/Lesson_1/README.md deleted file mode 100644 index 2f7d3ce..0000000 --- a/Lesson_1/README.md +++ /dev/null @@ -1,138 +0,0 @@ -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 includes `UefiApplicationEntryPoint` 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:\> -``` - - diff --git a/Lesson_1/SimplestApp/SimplestApp.c b/Lesson_1/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_1/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_1/SimplestApp/SimplestApp.inf b/Lesson_1/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_1/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_2/README.md b/Lesson_2/README.md deleted file mode 100644 index c91e47e..0000000 --- a/Lesson_2/README.md +++ /dev/null @@ -1,154 +0,0 @@ -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:\> -``` diff --git a/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_2/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_2/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_2/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 61378d6..0000000 --- a/Lesson_2/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,23 +0,0 @@ -[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 - -[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 - diff --git a/Lesson_3/README.md b/Lesson_3/README.md deleted file mode 100644 index f0aef2e..0000000 --- a/Lesson_3/README.md +++ /dev/null @@ -1,168 +0,0 @@ -Finally we are ready to write our "Hello World" app. - -First we create a new edk2 module in our package directory similar to the our `SimplestApp` module: -``` -$ mkdir UefiLessonsPkg/HelloWorld -$ vi UefiLessonsPkg/HelloWorld/HelloWorld.inf -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint -``` -Don't forget to add our newly created app to the `Components` section of the package DSC file -``` -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf -+ UefiLessonsPkg/HelloWorld/HelloWorld.inf -``` -Next we need to write the source code file. Let's remember the code for our SimplestApp: -``` -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} -``` -To print something to the console ("Hello World" message in our case) we need to use services from the `EFI_SYSTEM_TABLE` that is passed to the entry point of our app. - -The description of the `EFI_SYSTEM_TABLE` can be found in the UEFI specification (https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf). - -EFI_SYSTEM_TABLE is a struct that was populated by the UEFI firmware and contains pointers to the runtime and boot services tables. -``` -typedef struct { - EFI_TABLE_HEADER Hdr; - CHAR16 *FirmwareVendor; - UINT32 FirmwareRevision; - EFI_HANDLE ConsoleInHandle; - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; - EFI_HANDLE ConsoleOutHandle; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; - EFI_HANDLE StandardErrorHandle; - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; - EFI_RUNTIME_SERVICES *RuntimeServices; - EFI_BOOT_SERVICES *BootServices; - UINTN NumberOfTableEntries; - EFI_CONFIGURATION_TABLE *ConfigurationTable; -} EFI_SYSTEM_TABLE; -``` -We are interested in the `ConOut` field. `ConOut` is abbreviaton for "Console Output" and according to the UEFI spec it is a pointer to the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` interface that is associated with `ConsoleOutHandle`. - -If we keep digging into UEFI spec we can find description of the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL`. -According to the spec `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` defines the minimum requirements for a text-based ConsoleOut device. - -As everything in UEFI it has GUID: -``` -#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ - {0x387477c2,0x69c7,0x11d2,\ - {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b}} -``` - -And the interface description is: -``` -typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { - EFI_TEXT_RESET Reset; - EFI_TEXT_STRING OutputString; - EFI_TEXT_TEST_STRING TestString; - EFI_TEXT_QUERY_MODE QueryMode; - EFI_TEXT_SET_MODE SetMode; - EFI_TEXT_SET_ATTRIBUTE SetAttribute; - EFI_TEXT_CLEAR_SCREEN ClearScreen; - EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; - EFI_TEXT_ENABLE_CURSOR EnableCursor; - SIMPLE_TEXT_OUTPUT_MODE *Mode; -} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; -``` -Right now we are interested in a `OutputString` method: -``` -OutputString Displays the string on the device at the current cursor location. -``` -This is what we need. Let's look at the function description: -``` -EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString() - -Summary -Writes a string to the output device. - -Prototype -typedef -EFI_STATUS -(EFIAPI *EFI_TEXT_STRING) ( - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, - IN CHAR16 *String - ); - -Parameters -This A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. -String The Null-terminated string to be displayed on the output device(s). -``` - -In edk2 `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` is defined in the header file: -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/SimpleTextOut.h - - -With all this knowledge we can write our source code file `UefiLessonsPkg/HelloWorld/HelloWorld.c`: -``` -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - return EFI_SUCCESS; -} -``` - -The `L""` signifies that the string is composed from CHAR16 symbols, as was required in spec. - -Let's compile our edk2 module: -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ - --arch=X64 \ - --buildtarget=RELEASE --tagname=GCC5 -``` - -Copy the app to our `UEFI_disk` folder and run OVMF: -``` -$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/HelloWorld.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 -``` - -``` -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:\> HelloWorld.efi -Hello World! -FS0:\> -``` diff --git a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 399b0ac..0000000 --- a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index 95924c5..0000000 --- a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,17 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - diff --git a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 91a79e6..0000000 --- a/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,26 +0,0 @@ -[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 - - -[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 - UefiLessonsPkg/HelloWorld/HelloWorld.inf - - diff --git a/Lesson_4/README.md b/Lesson_4/README.md deleted file mode 100644 index 8892c28..0000000 --- a/Lesson_4/README.md +++ /dev/null @@ -1,229 +0,0 @@ -In this lesson we keep working on our 'Hello World' app. - -It is kinda tedious to write such a long string for a simple printf: -``` - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); -``` - -So let's try to simplify it. - -First in UEFI/edk2 you would be using a lot this `SystemTable` pointer as well as its filed `SystemTable->BootServices` and another main function parameter `ImageHandle`. - -So simplify access to these variables edk2 library create global defines for them gST, gBS, gImageHandle. - -You could look at the source of the UefiBootServicesTableLib.c: - -https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c - -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/UefiBootServicesTableLib.h - -``` -EFI_HANDLE gImageHandle = NULL; -EFI_SYSTEM_TABLE *gST = NULL; -EFI_BOOT_SERVICES *gBS = NULL; - -EFI_STATUS -EFIAPI -UefiBootServicesTableLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - // - // Cache the Image Handle - // - gImageHandle = ImageHandle; - ASSERT (gImageHandle != NULL); - - // - // Cache pointer to the EFI System Table - // - gST = SystemTable; - ASSERT (gST != NULL); - - // - // Cache pointer to the EFI Boot Services Table - // - gBS = SystemTable->BootServices; - ASSERT (gBS != NULL); - - return EFI_SUCCESS; -} -``` - -Let's try to use them in our function: - -``` -gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); -``` - -And try to recompile: -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ - --arch=X64 \ - --buildtarget=RELEASE --tagname=GCC5 -``` - -Unfortunately this will not compile: -``` -/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c: In function ‘UefiMain’: -/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c:12:3: error: ‘gST’ undeclared (first use in this function) - 12 | gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - | ^~~ -``` - -This error message is familiar, we'are missing some `#include` in our file, so let's add it: -``` -#include -``` - -This library is already included in our *.dsc file, so we are good to go: -``` -[LibraryClasses] - ... - UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf - ... -``` - -Our source code file at this point is: -``` -// for gBS -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - return EFI_SUCCESS; -} -``` - -Test for the successful compilation: -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ - --arch=X64 \ - --buildtarget=RELEASE --tagname=GCC5 -``` - -In the case of printf we can simplify things even more. Print is such a common function, that there is a library function for it in edk2. Add this to our file: -``` -Print(L"Bye!\n"); -``` - -If we try to recompile we would get error message about missing `#include` once again: -``` -/home/kostr/tiano/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c: In function ‘UefiMain’: -/home/kostr/tiano/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.c:13:3: error: implicit declaration of function ‘Print’ [-Werror=implicit-function-declaration] - 13 | Print(L"Bye!\n"); - | ^~~~~ -``` - -In this case header and source file for the `Print` function are: -- https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/UefiLib.h -- https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiLib/UefiLibPrint.c - -So let's include `UefiLib.h` in our file: -``` -#include -``` -And try to recompile. -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ - --arch=X64 \ - --buildtarget=RELEASE --tagname=GCC5 -``` - -Build would fail with a message: -``` -/home/kostr/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c:821: undefined reference to `Print' -collect2: error: ld returned 1 exit status -make: *** [GNUmakefile:307: /home/kostr/edk2/Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll] Error 1 -``` - -Compilation step was successful, but the linker have failed. This usually means that *.h file was in place, but the actual library wasn't linked. - -``` -$ grep UefiLib -r ./ --include=*.inf | grep LIBRARY_CLASS -./MdePkg/Library/UefiLib/UefiLib.inf: LIBRARY_CLASS = UefiLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE -``` - -Add this to our `UefiLessonsPkg/UefiLessonsPkg.dsc` file: -``` -[LibraryClasses] - ... -+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf -``` -And this string to our `UefiLessonsPkg/HelloWorld/HelloWorld.inf` file: -``` -[LibraryClasses] - UefiApplicationEntryPoint -+ UefiLib -``` - -If we try to build, we will get `Failed` once again: -``` -/home/kostr/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 4000: Instance of library class [MemoryAllocationLib] is not found - in [/home/kostr/edk2/MdePkg/Library/UefiLib/UefiLib.inf] [X64] - consumed by module [/home/kostr/edk2/UefiLessonsPkg/HelloWorld/HelloWorld.inf] -``` - -Try to find it: -``` -$ grep MemoryAllocationLib -r ./ --include=*.inf | grep LIBRARY_CLASS | grep MdePkg -./MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|PEIM PEI_CORE SEC -./MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|DXE_SMM_DRIVER -./MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf: LIBRARY_CLASS = MemoryAllocationLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER -``` - -Add this to our *.dsc file: -``` -[LibraryClasses] - ... -+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf -``` - -After that we would get another build failure with the similar message. So we need to repeat this process of finding right library. In the end we would need to add two more libraries: -``` -[LibraryClasses] - ... -+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf -+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf -``` - -After that finally build would finish successfully. - -Test it: -``` -cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/HelloWorld.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 -``` -``` -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 1 seconds to skip startup.nsh or any other key to continue. -Shell> fs0: -FS0:\> HelloWorld.efi -Hello World! -Hello again! -Bye! -FS0:\> -``` diff --git a/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_4/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_4/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_4/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_4/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 0a2edbe..0000000 --- a/Lesson_4/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,30 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - - diff --git a/Lesson_5/Conf/target.txt b/Lesson_5/Conf/target.txt deleted file mode 100644 index c109dcf..0000000 --- a/Lesson_5/Conf/target.txt +++ /dev/null @@ -1,7 +0,0 @@ -ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc -TARGET = RELEASE -TARGET_ARCH = X64 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = GCC5 -BUILD_RULE_CONF = Conf/build_rule.txt - diff --git a/Lesson_5/README.md b/Lesson_5/README.md deleted file mode 100644 index 23130f4..0000000 --- a/Lesson_5/README.md +++ /dev/null @@ -1,53 +0,0 @@ -To build modules in our package we've used something like this: -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ - --arch=X64 \ - --buildtarget=RELEASE \ - --tagname=GCC5 -``` - -This is kinda long string. Let's simplify it. - -First we can omit `module` option from the command and always compile our package entirely with all its modules: - -``` -$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ - --arch=X64 \ - --buildtarget=RELEASE \ - --tagname=GCC5 -``` - -When we initiate our environment with: -``` -. edk2setup.sh -``` -`Conf` directory is created in the edk2 folder. This directory is populated with a bunch of files. -Also the `CONF_PATH` environment variable is created which points to the newly created `Conf` folder. - -Right now we are interested in the `Conf/target.txt` file. -By default it has many comments (lines that start with `#` symbol) and is prepopulated with these values: -``` -ACTIVE_PLATFORM = EmulatorPkg/EmulatorPkg.dsc -TARGET = DEBUG -TARGET_ARCH = IA32 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = VS2015x86 -BUILD_RULE_CONF = Conf/build_rule.txt -``` - -We can put all our build command options in this file to simplify our everyday life. -``` -ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc -TARGET = RELEASE -TARGET_ARCH = X64 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = GCC5 -BUILD_RULE_CONF = Conf/build_rule.txt -``` - -After that we could build our package with all its modules with the one single command: -``` -build -``` - diff --git a/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_5/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_5/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_5/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_5/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 0a2edbe..0000000 --- a/Lesson_5/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,30 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - - diff --git a/Lesson_6/Conf/target.txt b/Lesson_6/Conf/target.txt deleted file mode 100644 index c109dcf..0000000 --- a/Lesson_6/Conf/target.txt +++ /dev/null @@ -1,7 +0,0 @@ -ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc -TARGET = RELEASE -TARGET_ARCH = X64 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = GCC5 -BUILD_RULE_CONF = Conf/build_rule.txt - diff --git a/Lesson_6/Handle_Protocol_databases_scheme.jpg b/Lesson_6/Handle_Protocol_databases_scheme.jpg deleted file mode 100644 index 771a981..0000000 Binary files a/Lesson_6/Handle_Protocol_databases_scheme.jpg and /dev/null differ diff --git a/Lesson_6/README.md b/Lesson_6/README.md deleted file mode 100644 index 3bd7b83..0000000 --- a/Lesson_6/README.md +++ /dev/null @@ -1,243 +0,0 @@ -Let's create `ImageHandle` app in our `UefiLessonsPkg`. - -First generate a random GUID. -``` -$ uuidgen -b68d3472-70c7-4928-841b-6566032e0a23 -``` - -And then create *.inf and *.c file based on the code in our `HelloWorld` app: -``` -$ cat UefiLessonsPkg/ImageHandle/ImageHandle.inf -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageHandle - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageHandle.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib -``` -``` -$ cat UefiLessonsPkg/ImageHandle/ImageHandle.c -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} -``` -Add a newly created app to our `UefiLessonsPkg/UefiLessonsPkg.dsc` file: -``` -[Components] - ... -+ UefiLessonsPkg/ImageHandle/ImageHandle.inf -``` - -Now let's get to work. - -Our main function in a *.c file has 2 input parameters `EFI_HANDLE ImageHandle` and `EFI_SYSTEM_TABLE *SystemTable`: -``` -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -``` -We've already started to explore the `EFI_SYSTEM_TABLE`. In this lesson let's look what `ImageHandle` is about. - -`ImageHandle` parameter is a handle of an image for the program itself. - -You can found a definition for a `EFI_HANDLE` type in a https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiBaseType.h -``` -/// -/// A collection of related interfaces. -/// -typedef VOID *EFI_HANDLE; -``` -So it is simply a pointer to a void. So it could be a pointer to anything. - -In a reality it is a pointer to this type of structure https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Hand/Handle.h : -``` -#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l') - -/// -/// IHANDLE - contains a list of protocol handles -/// -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; -``` -LIST_ENTRY is a double linked list. So with it we can traverse to any handle in the system. Sometimes it is called the Handle database. - -In case you wonder how LIST_ENTRY is defined look at the https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h : -``` -/// -/// LIST_ENTRY structure definition. -/// -typedef struct _LIST_ENTRY LIST_ENTRY; - -/// -/// _LIST_ENTRY structure definition. -/// -struct _LIST_ENTRY { - LIST_ENTRY *ForwardLink; - LIST_ENTRY *BackLink; -}; -``` -Each handle has a list of protocols attached to it. Protocol is like an interface - a set of functions and data fields. To track the list of protocols attached to a handle this field is used: -``` - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; -``` -It is another double linked list that points to these structures: -``` -#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c') - -/// -/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked -/// with a protocol interface structure -/// -typedef struct { - UINTN Signature; - /// Link on IHANDLE.Protocols - LIST_ENTRY Link; - /// Back pointer - IHANDLE *Handle; - /// Link on PROTOCOL_ENTRY.Protocols - LIST_ENTRY ByProtocol; - /// The protocol ID - PROTOCOL_ENTRY *Protocol; - /// The interface value - VOID *Interface; - /// OPEN_PROTOCOL_DATA list - LIST_ENTRY OpenList; - UINTN OpenListCount; - -} PROTOCOL_INTERFACE; -``` - -Effectively PROTOCOL_INTERFACE structure is only a proxy that points to an actual PROTOCOL_ENTRY structrure which are exist in a separate protocol database. -``` -#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e') - -/// -/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol -/// database. Each handler that supports this protocol is listed, along -/// with a list of registered notifies. -/// -typedef struct { - UINTN Signature; - /// Link Entry inserted to mProtocolDatabase - LIST_ENTRY AllEntries; - /// ID of the protocol - EFI_GUID ProtocolID; - /// All protocol interfaces - LIST_ENTRY Protocols; - /// Registerd notification handlers - LIST_ENTRY Notify; -} PROTOCOL_ENTRY; -``` -It all sounds a little bit complicated so it is better to see it in a picture: -![Handle_Protocol_databases_scheme](Handle_Protocol_databases_scheme.jpg?raw=true "Handle/Protocol databases scheme") -Important information from the picture: -- HANDLE 0 has PROTOCOL_INTERFACE 0 (->PROTOCOL_ENTRY 0) and PROTOCOL_INTERFACE 1 (->PROTOCOL_ENTRY 1) -- HANDLE 1 has PROTOCOL_INTERFACE 2 (->PROTOCOL_ENTRY 2) and PROTOCOL_INTERFACE 3 (->PROTOCOL_ENTRY 1) -- HANDLE 2 has PROTOCOL_INTERFACE 4 (->PROTOCOL_ENTRY 1) -Besides that: -- All handles are interconnected with the help of `AllHandles` field in each `IHANDLE` structure -- All protocols are interconnected with the help of `AllEntries` field in each `PROTOCOL_ENTRY` structure -Red lines: -- Each handle has a double linked list of all its PROTOCOL_INTERFACES, which internally connected to each other through the `Link` field -Green lines: -- Each protocol entry effectively knows all the users (=PROTOCOL_INTERFACES) of it. - -Let's check that `EFI_HANDLE ImageHandle` effectively is the `IHANDLE` structure. - -To check this we will cast `ImageHandle` to `IHANDLE` and print its signature. - -``` -#include -#include - - -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - return EFI_SUCCESS; -} -``` - -Don't blame me for redefinition of `IHANDLE` structure. These structures (IHANDLE/PROTOCOL_ENTRY/PROTOCOL_INTERFACE) are private and not intended to be used outside of the `MdeModulePkg`. Even https://github.com/tianocore/edk2/blob/master/StandaloneMmPkg/Core/StandaloneMmCore.h redifines IHANDLE/PROTOCOL_ENTRY/PROTOCOL_INTERFACE. - -``` -$ . edksetup.sh -$ build -$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/ImageHandle.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 -``` - -``` -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:\> ImageHandle.efi -Signature: h n d l -``` - - - diff --git a/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_6/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.c deleted file mode 100644 index e869e28..0000000 --- a/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - - -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - return EFI_SUCCESS; -} diff --git a/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.inf deleted file mode 100644 index 34256ee..0000000 --- a/Lesson_6/UefiLessonsPkg/ImageHandle/ImageHandle.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageHandle - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageHandle.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_6/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_6/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_6/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 0d4fbb0..0000000 --- a/Lesson_6/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,31 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - UefiLessonsPkg/ImageHandle/ImageHandle.inf - - diff --git a/Lesson_7/Conf/target.txt b/Lesson_7/Conf/target.txt deleted file mode 100644 index c109dcf..0000000 --- a/Lesson_7/Conf/target.txt +++ /dev/null @@ -1,7 +0,0 @@ -ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc -TARGET = RELEASE -TARGET_ARCH = X64 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = GCC5 -BUILD_RULE_CONF = Conf/build_rule.txt - diff --git a/Lesson_7/README.md b/Lesson_7/README.md deleted file mode 100644 index 66e8689..0000000 --- a/Lesson_7/README.md +++ /dev/null @@ -1,229 +0,0 @@ -Let's print GUID for all the protocols that are exist in our `IMAGE_HANDLE`. - -First understand what `EFI_GUID` internally means in the edk2 codebase: - -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiBaseType.h -``` -/// -/// 128-bit buffer containing a unique identifier value. -/// -typedef GUID EFI_GUID; -``` -`GUID` structure is defined in https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h : -``` -/// -/// 128 bit buffer containing a unique identifier value. -/// Unless otherwise specified, aligned on a 64 bit boundary. -/// -typedef struct { - UINT32 Data1; - UINT16 Data2; - UINT16 Data3; - UINT8 Data4[8]; -} GUID; -``` -Fortunately we don't have to manually print all these fields by hand. `Print` function has a format option `%g` to print GUIDs, so we could simply print GUIDs with a code like this: -``` -Print("GUID=%g\n", myGUID); -``` -More information about `Print` formating options can be found at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PrintLib.h - - -We want to print `EFI_GUID` field from the `PROTOCOL_ENTRY` structure which are referred from the `PROTOCOL_INTERFACE` structures. So we need to define both of these structures in our file for the same reason we've defined `IHANDLE` earlier. - -``` -typedef struct { - UINTN Signature; - /// Link Entry inserted to mProtocolDatabase - LIST_ENTRY AllEntries; - /// ID of the protocol - EFI_GUID ProtocolID; - /// All protocol interfaces - LIST_ENTRY Protocols; - /// Registerd notification handlers - LIST_ENTRY Notify; -} PROTOCOL_ENTRY; - -typedef struct { - UINTN Signature; - /// Link on IHANDLE.Protocols - LIST_ENTRY Link; - /// Back pointer - IHANDLE *Handle; - /// Link on PROTOCOL_ENTRY.Protocols - LIST_ENTRY ByProtocol; - /// The protocol ID - PROTOCOL_ENTRY *Protocol; - /// The interface value - VOID *Interface; - /// OPEN_PROTOCOL_DATA list - LIST_ENTRY OpenList; - UINTN OpenListCount; - -} PROTOCOL_INTERFACE; -``` - -`PROTOCOL_INTERFACE` structures that are connected to any HANDLE are interlinked with each other with a help of a `LIST_ENTRY Link` field that connects them to a double linked list. - -As you may remember `LIST_ENTRY` is defined like this: -``` -/// -/// LIST_ENTRY structure definition. -/// -typedef struct _LIST_ENTRY LIST_ENTRY; - -/// -/// _LIST_ENTRY structure definition. -/// -struct _LIST_ENTRY { - LIST_ENTRY *ForwardLink; - LIST_ENTRY *BackLink; -}; -``` -Each of these fields inside these structure points to another `LIST_ENTRY` structure that is placed in another `PROTOCOL_INTERFACE`. - -So this connection looks like this: - -``` -typedef struct { typedef struct { - UINTN Signature; UINTN Signature; - struct LIST_ENTRY { |---------> struct LIST_ENTRY { - LIST_ENTRY *ForwardLink; -----------------| LIST_ENTRY *ForwardLink; - LIST_ENTRY *BackLink; LIST_ENTRY *BackLink; - } Link; } Link; - IHANDLE *Handle; IHANDLE *Handle; - LIST_ENTRY ByProtocol; LIST_ENTRY ByProtocol; - PROTOCOL_ENTRY *Protocol; PROTOCOL_ENTRY *Protocol; - VOID *Interface; VOID *Interface; - LIST_ENTRY OpenList; LIST_ENTRY OpenList; - UINTN OpenListCount; UINTN OpenListCount; -} PROTOCOL_INTERFACE; } PROTOCOL_INTERFACE; -``` - -But in reality we want a pointer not to `Link` field of another `PROTOCOL_INTERFACE` structure, we want a pointer to another `PROTCOL_INTERFACE` structure inself. - -Therefore one more thing that we would need is a couple of macros: -``` -#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) -``` -These macros can be familiar to you if you've investigated linux kernel programming. This is where I got them from anyway. - -`contianer_of` macro helps to get a pointer to a structure if you have a pointer to one of its fields. - -If you want to understand how it works internally in C language I suggest you to look at the https://stackoverflow.com/questions/15832301/understanding-container-of-macro-in-the-linux-kernel - -With all of this information final code for our `UefiMain` function would look like this: -``` -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); - Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); - - LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; - LIST_ENTRY *CurrentLink = FirstLink; - do { - PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); - - Print(L"\n"); - Print(L"Current Link: %p\n", CurrentLink); - Print(L"Signature: %c %c %c %c\n", (MyProtocolInterface->Signature >> 0) & 0xff, - (MyProtocolInterface->Signature >> 8) & 0xff, - (MyProtocolInterface->Signature >> 16) & 0xff, - (MyProtocolInterface->Signature >> 24) & 0xff); - - Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); - Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); - Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); - CurrentLink = MyProtocolInterface->Link.ForwardLink; - } while (CurrentLink != FirstLink); - - return EFI_SUCCESS; -} -``` - -If we compile and run our app in OVMF (I hope at this time I don't need to repeat how to do it): -``` -FS0:\> ImageHandle.efi -h n d l -Back Protocol Interface Link: 68D4320 -Forward Protocol Interface Link: 6891520 - -Current Link: 6891520 -p i f c -Back Link: 6891430 -Forward Link: 6891B20 -GUID=752F3136-4E16-4FDC-A22A-E5F46812F4CA - -Current Link: 6891B20 -p i f c -Back Link: 6891520 -Forward Link: 68D4320 -GUID=BC62157E-3E33-4FEC-9920-2D3B36D750DF - -Current Link: 68D4320 -p i f c -Back Link: 6891B20 -Forward Link: 6891430 -GUID=5B1B31A1-9562-11D2-8E3F-00A0C969723B - -Current Link: 6891430 - ? ? ? -Back Link: 68D4320 -Forward Link: 6891520 -GUID=00000000-0000-0000-0000-000000000000 -``` - -Let's find first GUID by executing grep on the edk2 source: -``` -$ grep -i 752F3136 -r ./ --exclude-dir=Build -./MdePkg/Include/Protocol/ShellParameters.h: 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ -./MdePkg/MdePkg.dec: gEfiShellParametersProtocolGuid = { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca }} -``` - -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/ShellParameters.h -``` -#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ - { \ - 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ - } -``` -You can also see in in a https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec file: -``` - ## Include/Protocol/ShellParameters.h - gEfiShellParametersProtocolGuid = { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca }} -``` - -The next two GUIDs you can find in UEFI the specification. - -`EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL` - When installed, the Loaded Image Device Path Protocol specifies the device path that was used when a PE/COFF image was loaded through the EFI Boot Service LoadImage(). - -``` -#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ -{0xbc62157e,0x3e33,0x4fec,\ - {0x99,0x20,0x2d,0x3b,0x36,0xd7,0x50,0xdf}} -``` - -`EFI_LOADED_IMAGE_PROTOCOL` - Can be used on any image handle to obtain information about the loaded image. -``` -#define EFI_LOADED_IMAGE_PROTOCOL_GUID\ - {0x5B1B31A1,0x9562,0x11d2,\ - {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}} -``` - -The last `PROTOCOL_INTERFACE` structure doesn't have a valid "p i f c" signature (in my case it is 0x20 0x0E 0xED 0x06), so we don't need to look at its GUID. - diff --git a/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_7/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.c deleted file mode 100644 index bcf42e3..0000000 --- a/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include - - -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; - -typedef struct { - UINTN Signature; - /// Link Entry inserted to mProtocolDatabase - LIST_ENTRY AllEntries; - /// ID of the protocol - EFI_GUID ProtocolID; - /// All protocol interfaces - LIST_ENTRY Protocols; - /// Registerd notification handlers - LIST_ENTRY Notify; -} PROTOCOL_ENTRY; - -typedef struct { - UINTN Signature; - /// Link on IHANDLE.Protocols - LIST_ENTRY Link; - /// Back pointer - IHANDLE *Handle; - /// Link on PROTOCOL_ENTRY.Protocols - LIST_ENTRY ByProtocol; - /// The protocol ID - PROTOCOL_ENTRY *Protocol; - /// The interface value - VOID *Interface; - /// OPEN_PROTOCOL_DATA list - LIST_ENTRY OpenList; - UINTN OpenListCount; - -} PROTOCOL_INTERFACE; - - -#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); - Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); - - LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; - LIST_ENTRY *CurrentLink = FirstLink; - do { - PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); - - Print(L"\n"); - Print(L"Current Link: %p\n", CurrentLink); - Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, - (MyProtocolInterface->Signature >> 8) & 0xff, - (MyProtocolInterface->Signature >> 16) & 0xff, - (MyProtocolInterface->Signature >> 24) & 0xff); - - Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); - Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); - Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); - CurrentLink = MyProtocolInterface->Link.ForwardLink; - } while (CurrentLink != FirstLink); - - return EFI_SUCCESS; -} diff --git a/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.inf deleted file mode 100644 index 34256ee..0000000 --- a/Lesson_7/UefiLessonsPkg/ImageHandle/ImageHandle.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageHandle - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageHandle.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_7/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_7/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_7/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index 0d4fbb0..0000000 --- a/Lesson_7/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,31 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - UefiLessonsPkg/ImageHandle/ImageHandle.inf - - diff --git a/Lesson_8/DevicePath.png b/Lesson_8/DevicePath.png deleted file mode 100644 index 225226f..0000000 Binary files a/Lesson_8/DevicePath.png and /dev/null differ diff --git a/Lesson_8/README.md b/Lesson_8/README.md deleted file mode 100644 index fd31bcf..0000000 --- a/Lesson_8/README.md +++ /dev/null @@ -1,269 +0,0 @@ -Let's explore protocols associated with our `ImageHandle` that we've discovered in the last lesson. - -If we try to grep GUIDs in the edk2 source code: -``` -$ grep -i bc62157e -r ./ --exclude-dir=Build -./MdePkg/Include/Protocol/LoadedImage.h: 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \ -./MdePkg/MdePkg.dec: gEfiLoadedImageDevicePathProtocolGuid = { 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf }} -$ grep -i 5B1B31A1 -r ./ --exclude-dir=Build -./MdePkg/Include/Protocol/LoadedImage.h: 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ -./MdePkg/MdePkg.dec: gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} -``` - -Link to the header file: https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/LoadedImage.h - -Description for one of these protocol structures can be found in the same file: -``` -/// -/// Can be used on any image handle to obtain information about the loaded image. -/// -typedef struct { - UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure. - ///< All future revisions will be backward compatible to the current revision. - EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from - ///< the firmware's boot manager. - EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer. - - // - // Source location of image - // - EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from. - EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle - ///< that the EFI Image was loaded from. - VOID *Reserved; ///< Reserved. DO NOT USE. - - // - // Images load options - // - UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions. - VOID *LoadOptions; ///< A pointer to the image's binary load options. - - // - // Location of where image was loaded - // - VOID *ImageBase; ///< The base address at which the image was loaded. - UINT64 ImageSize; ///< The size in bytes of the loaded image. - EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as. - EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as. - EFI_IMAGE_UNLOAD Unload; -} EFI_LOADED_IMAGE_PROTOCOL; -``` - -UEFI specification gives following description for this protocol: -``` -Each loaded image has an image handle that supports EFI_LOADED_IMAGE_PROTOCOL. When an image is started, it is passed the image handle for itself. The image can use the handle to obtain its relevant image data stored in the EFI_LOADED_IMAGE_PROTOCOL structure, such as its load options -``` - -Another GUID stands for the `EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL` - When installed, the Loaded Image Device Path Protocol specifies the device path that was used when a PE/COFF image was loaded through the EFI Boot Service LoadImage(). -The Loaded Image Device Path Protocol uses the same protocol interface structure as the Device Path Protocol. The only difference between the Device Path Protocol and the Loaded Image Device Path Protocol is the protocol GUID value. -The Loaded Image Device Path Protocol must be installed onto the image handle of a PE/COFF image loaded through the EFI Boot Service LoadImage(). A copy of the device path specified by the DevicePath parameter to the EFI Boot Service LoadImage() is made before it is installed onto the image handle. It is legal to call LoadImage() for a buffer in memory with a NULL DevicePath parameter. In this case, the Loaded Image Device Path Protocol is installed with a NULL interface pointer. - -So effectively if you want to look up the definition for this protocol you should search `EFI_DEVICE_PATH_PROTOCOL`. - -It is defined in edk2 sources here https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/DevicePath.h : -``` -/** - This protocol can be used on any device handle to obtain generic path/location - information concerning the physical device or logical device. If the handle does - not logically map to a physical device, the handle may not necessarily support - the device path protocol. The device path describes the location of the device - the handle is for. The size of the Device Path can be determined from the structures - that make up the Device Path. -**/ -typedef struct { - UINT8 Type; ///< 0x01 Hardware Device Path. - ///< 0x02 ACPI Device Path. - ///< 0x03 Messaging Device Path. - ///< 0x04 Media Device Path. - ///< 0x05 BIOS Boot Specification Device Path. - ///< 0x7F End of Hardware Device Path. - - UINT8 SubType; ///< Varies by Type - ///< 0xFF End Entire Device Path, or - ///< 0x01 End This Instance of a Device Path and start a new - ///< Device Path. - - UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define - ///< type of data. Size of data is included in Length. - -} EFI_DEVICE_PATH_PROTOCOL; -``` -This structure is like a header to an actual path data which immediately follows it for amount of `Length` bytes. -![Device path](DevicePath.png?raw=true "Device Path in memory") - - -Now we have understanding of all the protocol structures, it is time to know the right way of how to get to them. -The "raw" method that we've used in last lessons was purely educational. -UEFI has several functions to help to get the protocol structures in a code. - -`EFI_BOOT_SERVICES.HandleProtocol()` - Queries a handle to determine if it supports a specified protocol. - -UEFI docs: -``` -Prototype: - -typedef -EFI_STATUS -(EFIAPI *EFI_HANDLE_PROTOCOL) ( - IN EFI_HANDLE Handle, - IN EFI_GUID *Protocol, - OUT VOID **Interface -); - -Parameters: -Handle The handle being queried. If Handle isNULL, then EFI_INVALID_PARAMETER is returned. -Protocol The published unique identifier of the protocol. It is the caller’s responsibility to pass in a valid GUID. -Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. - NULL will be returned in *Interface if a structure is not associated with Protocol. - -Description: -The HandleProtocol() function queries Handle to determine if it supports Protocol. If it does, then on return Interface points to a pointer to the corresponding Protocol Interface. Interface can then be passed to any protocol service to identify the context of the request. - -Status Codes Returned: -EFI_SUCCESS The interface information for the specified protocol was returned. -EFI_UNSUPPORTED The device does not support the specified protocol. -EFI_INVALID_PARAMETER Handle is NULL.. -EFI_INVALID_PARAMETER Protocol is NULL. -EFI_INVALID_PARAMETER Interface is NULL. -``` - - -With all this info let's write source code for our new `ImageInfo` app: -``` -#include -#include - -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage - ); - - if (Status == EFI_SUCCESS) { - EFI_DEVICE_PATH_PROTOCOL* DevicePath; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID**) &DevicePath - ); - - if (Status == EFI_SUCCESS) { - Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); - Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); - Print(L"Image Base: %X\n", LoadedImage->ImageBase); - Print(L"Image Size: %X\n", LoadedImage->ImageSize); - } else { - Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); - } - } else { - Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); - } - return EFI_SUCCESS; -} -``` - -Some new important things: -- `gBS` is a global variable which is a shortcut for the `SystemTable->BootServices` a table which contains UEFI services produced by UEFI firmware. These services are only valid in pre-OS environment opposed to the `gRT=SystemTable->RuntimeServices` -- `EFI_STATUS` variable can be printed with the help of "%r" formatting option (see https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PrintLib.h) -- `ConvertDevicePathToText` can be used to convert device path to a string. -It is defined here: -https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c -With a header file https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DevicePathLib.h : -``` -/** - Converts a device path to its text representation. - @param DevicePath A Pointer to the device to be converted. - @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation - of the display node is used, where applicable. If DisplayOnly - is FALSE, then the longer text representation of the display node - is used. - @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text - representation for a device node can be used, where applicable. - @return A pointer to the allocated text representation of the device path or - NULL if DeviceNode is NULL or there was insufficient memory. -**/ -CHAR16 * -EFIAPI -ConvertDevicePathToText ( - IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, - IN BOOLEAN DisplayOnly, - IN BOOLEAN AllowShortcuts - ); -``` - -Ok, let's try to compile our app. -``` -. edksetup.sh -build -``` - -Unfortunately build would fail: -``` -/home/kostr/tiano/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:16: undefined reference to `gEfiLoadedImageProtocolGuid' -/usr/bin/ld: /tmp/ImageInfo.dll.JKxzWu.ltrans0.ltrans.o:/home/kostr/tiano/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:24: undefined reference to `gEfiLoadedImageDevicePathProtocolGuid' -``` - -To solve this error add `Protocols` section to the `UefiLessonsPkg/ImageInfo/ImageInfo.inf` file: -``` -[Protocols] - gEfiLoadedImageProtocolGuid ## CONSUMES - gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES -``` - -The [Protocols] section of the EDK II INF file is a list of the global Protocol C Names that are used by the module developer. These C names are used by the parsing utility to lookup the actual GUID value of the PROTOCOL that is located in the EDK II package DEC files, and then emit a data structure to the module's AutoGen.c file (https://edk2-docs.gitbook.io/edk-ii-inf-specification/2_inf_overview/29_-protocols-_section). - - -`## CONSUMES` is used to indicate usage of this protocol. It has no value other than informational. You can encounter values like this for example in the edk2 codebase: -``` -## CONSUMES -## PRODUCES -## ALWAYS_CONSUMES -## ALWAYS_PRODUCES -## SOMETIMES_PRODUCES -## SOMETIMES_PRODUCES -## NOTIFY -``` - -After we add these protocols to the *.inf file, the build will succeed. - -In case you wonder, our GUID variables will go to a file `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/ImageInfo/ImageInfo/DEBUG/AutoGen.c` which is automatically generated by the build system: -``` -// Protocols -GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiLoadedImageDevicePathProtocolGuid = { 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf }}; -``` - -If we try to execute our app under OVMF we would get 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 5 seconds to skip startup.nsh or any other key to continue. -Shell> fs0: -FS0:\> ImageInfo.efi -Image device: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\ImageInfo.efi -Image file: \ImageInfo.efi -Image Base: 6885000 -Image Size: 5140 -``` diff --git a/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_8/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.c deleted file mode 100644 index bcf42e3..0000000 --- a/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include - - -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; - -typedef struct { - UINTN Signature; - /// Link Entry inserted to mProtocolDatabase - LIST_ENTRY AllEntries; - /// ID of the protocol - EFI_GUID ProtocolID; - /// All protocol interfaces - LIST_ENTRY Protocols; - /// Registerd notification handlers - LIST_ENTRY Notify; -} PROTOCOL_ENTRY; - -typedef struct { - UINTN Signature; - /// Link on IHANDLE.Protocols - LIST_ENTRY Link; - /// Back pointer - IHANDLE *Handle; - /// Link on PROTOCOL_ENTRY.Protocols - LIST_ENTRY ByProtocol; - /// The protocol ID - PROTOCOL_ENTRY *Protocol; - /// The interface value - VOID *Interface; - /// OPEN_PROTOCOL_DATA list - LIST_ENTRY OpenList; - UINTN OpenListCount; - -} PROTOCOL_INTERFACE; - - -#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); - Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); - - LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; - LIST_ENTRY *CurrentLink = FirstLink; - do { - PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); - - Print(L"\n"); - Print(L"Current Link: %p\n", CurrentLink); - Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, - (MyProtocolInterface->Signature >> 8) & 0xff, - (MyProtocolInterface->Signature >> 16) & 0xff, - (MyProtocolInterface->Signature >> 24) & 0xff); - - Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); - Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); - Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); - CurrentLink = MyProtocolInterface->Link.ForwardLink; - } while (CurrentLink != FirstLink); - - return EFI_SUCCESS; -} diff --git a/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.inf deleted file mode 100644 index 34256ee..0000000 --- a/Lesson_8/UefiLessonsPkg/ImageHandle/ImageHandle.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageHandle - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageHandle.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.c b/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.c deleted file mode 100644 index c45570e..0000000 --- a/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage - ); - - if (Status == EFI_SUCCESS) { - EFI_DEVICE_PATH_PROTOCOL* DevicePath; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID**) &DevicePath - ); - - if (Status == EFI_SUCCESS) { - Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); - Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); // EFI_DEVICE_PATH_PROTOCOL *FilePath - Print(L"Image Base: %X\n", LoadedImage->ImageBase); - Print(L"Image Size: %X\n", LoadedImage->ImageSize); - } else { - Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); - } - } else { - Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); - } - return EFI_SUCCESS; -} diff --git a/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.inf b/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.inf deleted file mode 100644 index 0ce54a6..0000000 --- a/Lesson_8/UefiLessonsPkg/ImageInfo/ImageInfo.inf +++ /dev/null @@ -1,22 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageInfo - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageInfo.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - -[Protocols] - gEfiLoadedImageProtocolGuid - gEfiLoadedImageDevicePathProtocolGuid - diff --git a/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_8/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_8/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_8/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index ff2edf6..0000000 --- a/Lesson_8/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,32 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - UefiLessonsPkg/ImageHandle/ImageHandle.inf - UefiLessonsPkg/ImageInfo/ImageInfo.inf - - diff --git a/Lesson_9/Conf/target.txt b/Lesson_9/Conf/target.txt deleted file mode 100644 index c109dcf..0000000 --- a/Lesson_9/Conf/target.txt +++ /dev/null @@ -1,7 +0,0 @@ -ACTIVE_PLATFORM = UefiLessonsPkg/UefiLessonsPkg.dsc -TARGET = RELEASE -TARGET_ARCH = X64 -TOOL_CHAIN_CONF = Conf/tools_def.txt -TOOL_CHAIN_TAG = GCC5 -BUILD_RULE_CONF = Conf/build_rule.txt - diff --git a/Lesson_9/README.md b/Lesson_9/README.md deleted file mode 100644 index 3b838d8..0000000 --- a/Lesson_9/README.md +++ /dev/null @@ -1,148 +0,0 @@ -The methods that we've used to discover protocols for our image handle were purely educational. - -Let's try UEFI API functions to get the same result. - -To do this we will need to understand `ProtocolsPerHandle` function: -``` -EFI_BOOT_SERVICES.ProtocolsPerHandle() - -Summary: -Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool. - -Prototype: -typedef -EFI_STATUS -(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) ( - IN EFI_HANDLE Handle, - OUT EFI_GUID ***ProtocolBuffer, - OUT UINTN *ProtocolBufferCount - ); - -Parameters: -Handle The handle from which to retrieve the list of protocol interface GUIDs. -ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are installed on Handle. This buffer is allocated with a call to the Boot Service EFI_BOOT_SERVICES.AllocatePool(). It is the caller's responsibility to call the Boot Service EFI_BOOT_SERVICES.FreePool() when the caller no longer requires the contents of ProtocolBuffer. -ProtocolBufferCountA pointer to the number of GUID pointers present in ProtocolBuffer. - -Description: -The ProtocolsPerHandle() function retrieves the list of protocol interface GUIDs that are installed on Handle. The list is returned in ProtocolBuffer, and the number of GUID pointers in ProtocolBuffer is returned in ProtocolBufferCount. -If Handle is NULL or Handle is NULL, then EFI_INVALID_PARAMETER is returned. -If ProtocolBuffer is NULL, then EFI_INVALID_PAREMETER is returned. -If ProtocolBufferCount is NULL, then EFI_INVALID_PARAMETER is returned. -If there are not enough resources available to allocate ProtocolBuffer, then EFI_OUT_OF_RESOURCES is -returned. - -Status Codes Returned: -EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in - ProtocolBuffer. The number of protocol interface GUIDs was - returned in ProtocolBufferCount. -EFI_INVALID_PARAMETER Handle is NULL. -EFI_INVALID_PARAMETER ProtocolBuffer is NULL. -EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. -EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. -``` - -This description mentions that we need manually deallocate received ProtocolBuffer, so lel's also look to the suggessted `FreePool` function: - -``` -EFI_BOOT_SERVICES.FreePool() - -Summary: -Returns pool memory to the system. - -Prototype: -typedef -EFI_STATUS -(EFIAPI *EFI_FREE_POOL) ( - IN VOID *Buffer -); - -Parameters: -Buffer Pointer to the buffer to free. - -Description: -The FreePool() function returns the memory specified by Buffer to the system. On return, the -memory’s type is EfiConventionalMemory. The Buffer that is freed must have been allocated by -AllocatePool(). - -Status Codes Returned: -EFI_SUCCESS The memory was returned to the system. -EFI_INVALID_PARAMETER Buffer was invalid -``` - -Now when we know how to use API, let's add this code at the end of our `ImageHandle` app: -``` -Print(L"________\n"); -EFI_GUID **ProtocolGuidArray; -UINTN ArrayCount; -EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle, - &ProtocolGuidArray, - &ArrayCount); - -if (Status == EFI_SUCCESS) { - for (int i=0; i -``` - -Some may have noticed, that we've used `FreePool`, but not a `gBS->FreePool`. It is legit because `FreePool` is defined in the https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c file: -``` -/** - Frees a buffer that was previously allocated with one of the pool allocation functions in the - Memory Allocation Library. - - Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the - pool allocation services of the Memory Allocation Library. If it is not possible to free pool - resources, then this function will perform no actions. - - If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, - then ASSERT(). - - @param Buffer The pointer to the buffer to free. - -**/ -VOID -EFIAPI -FreePool ( - IN VOID *Buffer - ) -{ - EFI_STATUS Status; - - Status = gBS->FreePool (Buffer); - ASSERT_EFI_ERROR (Status); -} -``` -This is shortcut is neccessary as `FreePool` have different library implementations: -``` -MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c -MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c -MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c -``` -This is the example of LibraryClass that can have several possible instances. In our case we use `UefiMemoryAllocationLib` instance. - -UefiLessonsPkg/UefiLessonsPkg.dsc: -``` -[LibraryClasses] - ... - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - ... -``` - -Now if we build and execute our app under OVMF this code will give us: -``` -752F3136-4E16-4FDC-A22A-E5F46812F4CA -BC62157E-3E33-4FEC-9920-2D3B36D750DF -5B1B31A1-9562-11D2-8E3F-00A0C969723B -``` -Which are the same GUIDs we've discovered through hardcore raw walkthrough through the handle/protocol databases. - - - diff --git a/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.c deleted file mode 100644 index 1f05899..0000000 --- a/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); - gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); - Print(L"Bye!\n"); - return EFI_SUCCESS; -} diff --git a/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.inf deleted file mode 100644 index d65ca2e..0000000 --- a/Lesson_9/UefiLessonsPkg/HelloWorld/HelloWorld.inf +++ /dev/null @@ -1,18 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = HelloWorld - FILE_GUID = 2e55fa38-f148-42d3-af90-1be247323e30 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - HelloWorld.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - diff --git a/Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.c deleted file mode 100644 index 6117243..0000000 --- a/Lesson_9/UefiLessonsPkg/ImageHandle/ImageHandle.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include -#include - -typedef struct { - UINTN Signature; - /// All handles list of IHANDLE - LIST_ENTRY AllHandles; - /// List of PROTOCOL_INTERFACE's for this handle - LIST_ENTRY Protocols; - UINTN LocateRequest; - /// The Handle Database Key value when this handle was last created or modified - UINT64 Key; -} IHANDLE; - -typedef struct { - UINTN Signature; - /// Link Entry inserted to mProtocolDatabase - LIST_ENTRY AllEntries; - /// ID of the protocol - EFI_GUID ProtocolID; - /// All protocol interfaces - LIST_ENTRY Protocols; - /// Registerd notification handlers - LIST_ENTRY Notify; -} PROTOCOL_ENTRY; - -typedef struct { - UINTN Signature; - /// Link on IHANDLE.Protocols - LIST_ENTRY Link; - /// Back pointer - IHANDLE *Handle; - /// Link on PROTOCOL_ENTRY.Protocols - LIST_ENTRY ByProtocol; - /// The protocol ID - PROTOCOL_ENTRY *Protocol; - /// The interface value - VOID *Interface; - /// OPEN_PROTOCOL_DATA list - LIST_ENTRY OpenList; - UINTN OpenListCount; - -} PROTOCOL_INTERFACE; - - -#define offsetof(a,b) ((INTN)(&(((a*)(0))->b))) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - IHANDLE* MyHandle = ImageHandle; - Print(L"Signature: %c %c %c %c\n", (MyHandle->Signature >> 0) & 0xff, - (MyHandle->Signature >> 8) & 0xff, - (MyHandle->Signature >> 16) & 0xff, - (MyHandle->Signature >> 24) & 0xff); - - Print(L"Back Protocol Interface Link: %p\n", MyHandle->Protocols.BackLink); - Print(L"Forward Protocol Interface Link: %p\n", MyHandle->Protocols.ForwardLink); - - LIST_ENTRY *FirstLink = MyHandle->Protocols.ForwardLink; - LIST_ENTRY *CurrentLink = FirstLink; - do { - PROTOCOL_INTERFACE* MyProtocolInterface = container_of(CurrentLink, PROTOCOL_INTERFACE, Link); - - Print(L"\n"); - Print(L"Current Link: %p\n", CurrentLink); - Print(L"Signature: %x %x %x %x\n", (MyProtocolInterface->Signature >> 0) & 0xff, - (MyProtocolInterface->Signature >> 8) & 0xff, - (MyProtocolInterface->Signature >> 16) & 0xff, - (MyProtocolInterface->Signature >> 24) & 0xff); - - Print(L"Back Link: %p\n", MyProtocolInterface->Link.BackLink); - Print(L"Forward Link: %p\n", MyProtocolInterface->Link.ForwardLink); - Print(L"GUID=%g\n", MyProtocolInterface->Protocol->ProtocolID); - CurrentLink = MyProtocolInterface->Link.ForwardLink; - } while (CurrentLink != FirstLink); - - Print(L"________\n"); - EFI_GUID **ProtocolGuidArray; - UINTN ArrayCount; - EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle, - &ProtocolGuidArray, - &ArrayCount); - - if (Status == EFI_SUCCESS) { - for (int i=0; i -#include - -#include -#include - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage - ); - - if (Status == EFI_SUCCESS) { - EFI_DEVICE_PATH_PROTOCOL* DevicePath; - - Status = gBS->HandleProtocol( - ImageHandle, - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID**) &DevicePath - ); - - if (Status == EFI_SUCCESS) { - Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); - Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); // EFI_DEVICE_PATH_PROTOCOL *FilePath - Print(L"Image Base: %X\n", LoadedImage->ImageBase); - Print(L"Image Size: %X\n", LoadedImage->ImageSize); - } else { - Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); - } - } else { - Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); - } - return EFI_SUCCESS; -} diff --git a/Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.inf b/Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.inf deleted file mode 100644 index 0ce54a6..0000000 --- a/Lesson_9/UefiLessonsPkg/ImageInfo/ImageInfo.inf +++ /dev/null @@ -1,22 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = ImageInfo - FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - ImageInfo.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - -[Protocols] - gEfiLoadedImageProtocolGuid - gEfiLoadedImageDevicePathProtocolGuid - diff --git a/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.c deleted file mode 100644 index 8bdf500..0000000 --- a/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.c +++ /dev/null @@ -1,10 +0,0 @@ -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} - diff --git a/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.inf deleted file mode 100644 index 7d4bae2..0000000 --- a/Lesson_9/UefiLessonsPkg/SimplestApp/SimplestApp.inf +++ /dev/null @@ -1,16 +0,0 @@ -[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 diff --git a/Lesson_9/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_9/UefiLessonsPkg/UefiLessonsPkg.dsc deleted file mode 100644 index ff2edf6..0000000 --- a/Lesson_9/UefiLessonsPkg/UefiLessonsPkg.dsc +++ /dev/null @@ -1,32 +0,0 @@ -[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 - - -[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 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - -[Components] - UefiLessonsPkg/SimplestApp/SimplestApp.inf - UefiLessonsPkg/HelloWorld/HelloWorld.inf - UefiLessonsPkg/ImageHandle/ImageHandle.inf - UefiLessonsPkg/ImageInfo/ImageInfo.inf - - diff --git a/README.md b/README.md index baa1f19..cdaf7b1 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ These series of lessons are intendend to get you started with UEFI programming i Lessons description: -- Lesson 0: Getting started guide for TianoCore. Compile OVMF and run it in QEMU -- Lesson 1: Create a simplest app and run it in OVMF -- Lesson 2: Create a simplest package -- Lesson 3: Create `HelloWorld` app with the help of SystemTable services -- Lesson 4: Use edk2 libraries to simplify our `HelloWorld` app -- Lesson 5: Simplify build command with the help of files in the `Conf` folder -- Lesson 6: Handle/Protocol databases internals - Part 1: Theory and raw access to an app ImageHandle -- Lesson 7: Handle/Protocol databases internals - Part 2: Raw access to app protocols -- Lesson 8: `HandleProtocol` API function. Information from the `ImageHandle` protocols -- Lesson 9: Get ImageHandle protocols with the `ProtocolsPerHandle` API function +- Lesson 00: Getting started guide for TianoCore. Compile OVMF and run it in QEMU +- Lesson 01: Create a simplest app and run it in OVMF +- Lesson 02: Create a simplest package +- Lesson 03: Create `HelloWorld` app with the help of SystemTable services +- Lesson 04: Use edk2 libraries to simplify our `HelloWorld` app +- Lesson 05: Simplify build command with the help of files in the `Conf` folder +- Lesson 06: Handle/Protocol databases internals - Part 1: Theory and raw access to an app ImageHandle +- Lesson 07: Handle/Protocol databases internals - Part 2: Raw access to app protocols +- Lesson 08: `HandleProtocol` API function. Information from the `ImageHandle` protocols +- Lesson 09: Get ImageHandle protocols with the `ProtocolsPerHandle` API function - Lesson 10: `EFI_STATUS` type and `EFI_ERROR` macros - Lesson 11: Get EFI memory map information - Lesson 12: `EFI_SHELL_PARAMETERS_PROTOCOL`. Transform our EFI memory map to the Linux kernel style -- cgit v1.2.3-18-g5258