aboutsummaryrefslogtreecommitdiffstats
path: root/Lessons/Lesson_07
diff options
context:
space:
mode:
authorKonstantin Aladyshev <aladyshev22@gmail.com>2021-07-10 00:04:40 +0300
committerKonstantin Aladyshev <aladyshev22@gmail.com>2021-07-10 00:04:40 +0300
commit6064c1e48b622f53538f4df9bdd402c607a87d51 (patch)
tree93d3c937b9568568307fd2ff7053a30c538ad72a /Lessons/Lesson_07
parenta9c375c80c3505be794ec2b5d5bb90de27ef0d42 (diff)
downloadUEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.tar.gz
UEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.tar.bz2
UEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.zip
Move lessons to separate folder
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Diffstat (limited to 'Lessons/Lesson_07')
-rw-r--r--Lessons/Lesson_07/Conf/target.txt7
-rw-r--r--Lessons/Lesson_07/README.md229
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.c15
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/HelloWorld/HelloWorld.inf18
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.c88
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/ImageHandle/ImageHandle.inf18
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.c10
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/SimplestApp/SimplestApp.inf16
-rw-r--r--Lessons/Lesson_07/UefiLessonsPkg/UefiLessonsPkg.dsc31
9 files changed, 432 insertions, 0 deletions
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 <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/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 <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;
+
+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
+
+