From 6064c1e48b622f53538f4df9bdd402c607a87d51 Mon Sep 17 00:00:00 2001 From: Konstantin Aladyshev Date: Sat, 10 Jul 2021 00:04:40 +0300 Subject: Move lessons to separate folder Signed-off-by: Konstantin Aladyshev --- Lessons/Lesson_07/Conf/target.txt | 7 + Lessons/Lesson_07/README.md | 229 +++++++++++++++++++++ .../UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 ++ .../UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 ++ .../UefiLessonsPkg/ImageHandle/ImageHandle.c | 88 ++++++++ .../UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 ++ .../UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 + .../UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 ++ .../Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc | 31 +++ 9 files changed, 432 insertions(+) create mode 100644 Lessons/Lesson_07/Conf/target.txt create mode 100644 Lessons/Lesson_07/README.md create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf create mode 100644 Lessons/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc (limited to 'Lessons/Lesson_07') diff --git a/Lessons/Lesson_07/Conf/target.txt b/Lessons/Lesson_07/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/README.md b/Lessons/Lesson_07/README.md new file mode 100644 index 0000000..66e8689 --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..bcf42e3 --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf new file mode 100644 index 0000000..34256ee --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lessons/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/Lessons/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lessons/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..0d4fbb0 --- /dev/null +++ b/Lessons/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 + + -- cgit v1.2.3-18-g5258