diff options
author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-19 21:03:52 +0300 |
---|---|---|
committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-19 21:07:18 +0300 |
commit | 949552d025a5968b3fd3e8d0ab399c9a85232def (patch) | |
tree | 8af798e27d6c609754379967551ccf666915ccd5 /Lesson_06 | |
parent | 722c0444a133c4b7f0a3ce49d6990ecaf14cdcf4 (diff) | |
download | UEFI-Lessons-949552d025a5968b3fd3e8d0ab399c9a85232def.tar.gz UEFI-Lessons-949552d025a5968b3fd3e8d0ab399c9a85232def.tar.bz2 UEFI-Lessons-949552d025a5968b3fd3e8d0ab399c9a85232def.zip |
Rename lesson numbers to XX notation
With XX notation lessons would be placed in a folder from first to last.
Diffstat (limited to 'Lesson_06')
-rw-r--r-- | Lesson_06/Conf/target.txt | 7 | ||||
-rw-r--r-- | Lesson_06/Handle_Protocol_databases_scheme.jpg | bin | 0 -> 59389 bytes | |||
-rw-r--r-- | Lesson_06/README.md | 243 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c | 30 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 | ||||
-rw-r--r-- | Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 |
10 files changed, 388 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 0000000..771a981 --- /dev/null +++ b/Lesson_06/Handle_Protocol_databases_scheme.jpg 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 <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +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 <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + + +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 <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +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 <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + + +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 + + |