aboutsummaryrefslogtreecommitdiffstats
path: root/Lesson_06
diff options
context:
space:
mode:
Diffstat (limited to 'Lesson_06')
-rw-r--r--Lesson_06/Conf/target.txt7
-rw-r--r--Lesson_06/Handle_Protocol_databases_scheme.jpgbin0 -> 59389 bytes
-rw-r--r--Lesson_06/README.md243
-rw-r--r--Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.c15
-rw-r--r--Lesson_06/UefiLessonsPkg/HelloWorld/HelloWorld.inf18
-rw-r--r--Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.c30
-rw-r--r--Lesson_06/UefiLessonsPkg/ImageHandle/ImageHandle.inf18
-rw-r--r--Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.c10
-rw-r--r--Lesson_06/UefiLessonsPkg/SimplestApp/SimplestApp.inf16
-rw-r--r--Lesson_06/UefiLessonsPkg/UefiLessonsPkg.dsc31
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
new file mode 100644
index 0000000..771a981
--- /dev/null
+++ b/Lesson_06/Handle_Protocol_databases_scheme.jpg
Binary files 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 <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
+
+