aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lessons_uncategorized/Lesson_RegisterProtocolNotify/README.md470
-rw-r--r--README.md1
-rw-r--r--UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c99
-rw-r--r--UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf28
-rw-r--r--UefiLessonsPkg/UefiLessonsPkg.dsc1
-rw-r--r--bin/ProtocolEventDriver.efibin0 -> 9344 bytes
6 files changed, 599 insertions, 0 deletions
diff --git a/Lessons_uncategorized/Lesson_RegisterProtocolNotify/README.md b/Lessons_uncategorized/Lesson_RegisterProtocolNotify/README.md
new file mode 100644
index 0000000..72f4e65
--- /dev/null
+++ b/Lessons_uncategorized/Lesson_RegisterProtocolNotify/README.md
@@ -0,0 +1,470 @@
+In this lesson we would investigate the `EFI_BOOT_SERVICES.RegisterProtocolNotify()` function. This API can be usefull to create callbacks that are executed when certain protocols are installed in the system.
+
+For our investigation let's create a simple driver `ProtocolEventDriver`:
+```
+./createNewDriver.sh ProtocolEventDriver
+```
+
+Add the following code to create a callback function `NotifyFunc` executed when the local `EFI_EVENT Event` is signaled:
+```cpp
+EFI_EVENT Event;
+UINTN NotifyData = 0;
+
+VOID EFIAPI NotifyFunc(EFI_EVENT Event, VOID* Context)
+{
+ ...
+}
+
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverUnload (
+ EFI_HANDLE ImageHandle
+ )
+{
+ gBS->CloseEvent(Event);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ &NotifyFunc,
+ &NotifyData,
+ &Event);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! CreateEvent returned: %r\n", Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+```
+
+Here we pass `UINTN NotifyData` to the callback function. Let's increment it inside the callback code, so we can understand how many times the callback was called:
+```cpp
+ if (Context == NULL)
+ return;
+
+ Print(L"\nEvent is signaled! Context = %d\n", *(UINTN*)Context);
+ *(UINTN*)Context += 1;
+```
+
+Right now no one can signal our event, therefore the callback code would never be executed. Let's register the protocol install notifier. Here we would monitor installation of our own `SIMPLE_CLASS_PROTOCOL` which we've created in the earlier lesson.
+
+In case you don't remember check out the protocol API in the `UefiLessonsPkg/Include/Protocol/SimpleClass.h`
+```cpp
+typedef
+EFI_STATUS
+(EFIAPI* SIMPLE_CLASS_GET_NUMBER)(
+ UINTN* Number
+ );
+
+
+typedef
+EFI_STATUS
+(EFIAPI* SIMPLE_CLASS_SET_NUMBER)(
+ UINTN Number
+ );
+
+
+struct _SIMPLE_CLASS_PROTOCOL {
+ SIMPLE_CLASS_GET_NUMBER GetNumber;
+ SIMPLE_CLASS_SET_NUMBER SetNumber;
+};
+```
+
+In the nutshell this protocol is a simple abstraction to the `UINTN Number` field.
+
+Now to the `RegisterProtocolNotify()`. Here is its description from the UEFI specification:
+```
+EFI_BOOT_SERVICES.RegisterProtocolNotify()
+
+Summary:
+Creates an event that is to be signaled whenever an interface is installed for a specified protocol.
+
+Prototype:
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+);
+
+Parameters:
+Protocol - The numeric ID of the protocol for which the event is to be registered
+Event - Event that is to be signaled whenever a protocol interface is registered for Protocol.
+ The same EFI_EVENT may be used for multiple protocol notify registrations
+Registration - A pointer to a memory location to receive the registration value. This value must be saved and used by the notification function
+ of Event to retrieve the list of handles that have added a protocol interface of type Protocol
+
+Description:
+The RegisterProtocolNotify() function creates an event that is to be signaled whenever a protocol interface is installed for Protocol by InstallProtocolInterface() or EFI_BOOT_SERVICES.ReinstallProtocolInterface().
+
+Once Event has been signaled, the EFI_BOOT_SERVICES.LocateHandle() function can be called to identify the newly installed, or reinstalled, handles that support Protocol. The Registration parameter in EFI_BOOT_SERVICES.RegisterProtocolNotify() corresponds to the SearchKey parameter in LocateHandle().
+```
+
+And this is how we would use it:
+```cpp
+#include <Protocol/SimpleClass.h>
+
+STATIC VOID *mRegistrationTracker;
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ ...
+
+ Status = gBS->RegisterProtocolNotify(&gSimpleClassProtocolGuid,
+ Event,
+ &mRegistrationTracker);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! RegisterProtocolNotify returned: %r\n", Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+```
+Don't mind the `Registration` parameter for now, we'll investigate it later.
+
+Also don't forget to add the necessary code to the `INF` file to be able to use our `SIMPLE_CLASS_PROTOCOL` in the driver code:
+```
+[Packages]
+ ...
+ UefiLessonsPkg/UefiLessonsPkg.dec
+
+[Protocols]
+ gSimpleClassProtocolGuid
+```
+
+Now when we load `SimpleClassProtocol.efi` driver (created in the earlier lesson) that installs the `SIMPLE_CLASS_PROTOCOL` protocol we would see that our callback code is executed:
+```
+FS0:\> load ProtocolEventDriver.efi
+Image 'FS0:\ProtocolEventDriver.efi' loaded at 6415000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 0
+, handle=640FB98
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 640C000 - Success
+```
+
+The strings
+```
+Hello from SimpleClassProtocol driver
+, handle=640FB98
+```
+
+Are printed from the `SimpleClassProtocol` driver. Here is its code:
+```cpp
+EFI_STATUS
+EFIAPI
+SimpleClassProtocolDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ Print(L"Hello from SimpleClassProtocol driver");
+
+ EFI_STATUS Status = gBS->InstallMultipleProtocolInterfaces(
+ &mSimpleClassHandle,
+ &gSimpleClassProtocolGuid,
+ &mSimpleClass,
+ NULL
+ );
+ if (!EFI_ERROR(Status))
+ Print(L", handle=%p\n", mSimpleClassHandle);
+ else
+ Print(L"\n", mSimpleClassHandle);
+
+ return Status;
+}
+```
+
+You can see how the `\nEvent is signaled! Context = 0\n` from the `ProtocolEventDriver` was printed in between the prints of `SimpleClassProtocol` driver. That means that as soon as the `SIMPLE_CLASS_PROTOCOL` was installed, our callback was executed interrupting the `SimpleClassProtocol` driver code.
+
+You can execute the `load SimpleClassProtocol.efi` again and see that our callback would be called on each protocol install:
+```
+FS0:\> load ProtocolEventDriver.efi
+Image 'FS0:\ProtocolEventDriver.efi' loaded at 6415000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 0
+, handle=640FB98
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 640C000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 1
+, handle=641AB18
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 6408000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 2
+, handle=6419918
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 63E3000 - Success
+```
+
+You can also see that as we've coded earlier, the `UINTN NotifyData` (aka `Context`) is incremented on each callback execution.
+
+Now let's check the `dh` output:
+```
+FS0:\> dh
+...
+A4: ImageDevicePath(..C1)/\ProtocolEventDriver.efi) LoadedImage(\ProtocolEventDriver.efi)
+A5: ImageDevicePath(..C1)/\SimpleClassProtocol.efi) LoadedImage(\SimpleClassProtocol.efi)
+A6: B5510EEA-6F11-4E4B-AD0F-35CE17BD7A67
+A7: ImageDevicePath(..C1)/\SimpleClassProtocol.efi) LoadedImage(\SimpleClassProtocol.efi)
+A8: B5510EEA-6F11-4E4B-AD0F-35CE17BD7A67
+A9: ImageDevicePath(..C1)/\SimpleClassProtocol.efi) LoadedImage(\SimpleClassProtocol.efi)
+AA: B5510EEA-6F11-4E4B-AD0F-35CE17BD7A67
+```
+You can see that each `load SimpleClassProtocol.efi` command installs a separate `SIMPLE_CLASS_PROTOCOL` protocol to the system.
+
+Now let's try to actually use the `SIMPLE_CLASS_PROTOCOL` inside the callback function. We would use the `gBS->LocateProtocol` to find the protocol and perform `+5` operation on its internal number via the protocol `SIMPLE_CLASS_GET_NUMBER/SIMPLE_CLASS_SET_NUMBER` functions.
+```cpp
+VOID EFIAPI NotifyFunc(EFI_EVENT Event, VOID* Context)
+{
+ ...
+
+ EFI_STATUS Status;
+ SIMPLE_CLASS_PROTOCOL* SimpleClass;
+ Status = gBS->LocateProtocol(&gSimpleClassProtocolGuid,
+ NULL,
+ (VOID**)&SimpleClass);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! LocateProtocol returned: %r\n", Status);
+ return;
+ }
+
+ UINTN Number;
+ Status = SimpleClass->GetNumber(&Number);
+ if (!EFI_ERROR(Status)) {
+ Print(L"Current number = %d\n", Number);
+ } else {
+ Print(L"Error! Can't get number: %r\n", Status);
+ return;
+ }
+
+ Status = SimpleClass->SetNumber(Number+5);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! Can't set number: %r\n", Status);
+ return;
+ }
+}
+```
+
+This is what we would get from this code:
+```
+FS0:\> load ProtocolEventDriver.efi
+Image 'FS0:\ProtocolEventDriver.efi' loaded at 6415000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 0
+Current number = 0
+, handle=640FB98
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 640C000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 1
+Current number = 5
+, handle=646A818
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 6408000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 2
+Current number = 10
+, handle=6419918
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 63E3000 - Success
+```
+
+You can see the problem here. Each time we perform `load SimpleClassProtocol.efi` we install additional protocol to the system. We saw that in the `dh` command output.
+But `gBS->LocateProtocol` always finds the first installed protocol. So how can we call the callback code on the newly installed protocol that caused the callback in the first place?
+
+To fix that we can utilize `Registration` parameter of the `RegisterProtocolNotify/LocateProtocol` functions.
+
+With it the `LocateProtocol` function would return the next handle that is new for the registration.
+
+Here is a description of the `EFI_BOOT_SERVICES.LocateProtocol()` function from the specification. We've already saw it, and used it many times, but now pay attention to the `Registration` parameter:
+```
+EFI_BOOT_SERVICES.LocateProtocol()
+
+Summary:
+Returns the first protocol instance that matches the given protocol.
+
+Prototype:
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOCATE_PROTOCOL) (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+);
+
+Parameters:
+Protocol - Provides the protocol to search for
+Registration - Optional registration key returned from EFI_BOOT_SERVICES.RegisterProtocolNotify(). If Registration is NULL, then it is ignored
+Interface - On return, a pointer to the first interface that matches Protocol and Registration
+
+Description:
+The LocateProtocol() function finds the first device handle that support Protocol, and returns a pointer to the protocol interface from that handle in Interface. If no protocol instances are found, then Interface is set to NULL.
+
+If Registration is not NULL, and there are no new handles for Registration, then EFI_NOT_FOUND is returned.
+```
+
+All we need to do now to fix the problem is to use `mRegistrationTracker` instead of `NULL` in the `gBS->LocateProtocol` call. In the nutshell the registration variable is used in 3 places:
+```cpp
+STATIC VOID *mRegistrationTracker; // <-----
+
+VOID EFIAPI NotifyFunc(EFI_EVENT Event, VOID* Context)
+{
+ ...
+ Status = gBS->LocateProtocol(&gSimpleClassProtocolGuid,
+ mRegistrationTracker, // <-----
+ (VOID**)&SimpleClass);
+ ...
+}
+
+...
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ ...
+ Status = gBS->RegisterProtocolNotify(&gSimpleClassProtocolGuid,
+ Event,
+ &mRegistrationTracker); // <-----
+ ...
+}
+```
+
+Now on each callback we would work with the newly installed protocol:
+```
+FS0:\> load ProtocolEventDriver.efi
+Image 'FS0:\ProtocolEventDriver.efi' loaded at 6415000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 0
+Current number = 0
+, handle=640FB98
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 640C000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 1
+Current number = 0
+, handle=646C218
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 6408000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 2
+Current number = 0
+, handle=6419918
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 63E3000 - Success
+```
+
+# `EfiCreateProtocolNotifyEvent`
+
+To ease creation process of the protocol notification callbacks the [UefiLib](https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/UefiLib.h) offers a `EfiCreateProtocolNotifyEvent` function:
+```cpp
+/**
+ Creates and returns a notification event and registers that event with all the protocol
+ instances specified by ProtocolGuid.
+
+ This function causes the notification function to be executed for every protocol of type
+ ProtocolGuid instance that exists in the system when this function is invoked. If there are
+ no instances of ProtocolGuid in the handle database at the time this function is invoked,
+ then the notification function is still executed one time. In addition, every time a protocol
+ of type ProtocolGuid instance is installed or reinstalled, the notification function is also
+ executed. This function returns the notification event that was created.
+ If ProtocolGuid is NULL, then ASSERT().
+ If NotifyTpl is not a legal TPL value, then ASSERT().
+ If NotifyFunction is NULL, then ASSERT().
+ If Registration is NULL, then ASSERT().
+
+
+ @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.
+ @param NotifyTpl Supplies the task priority level of the event notifications.
+ @param NotifyFunction Supplies the function to notify when the event is signaled.
+ @param NotifyContext The context parameter to pass to NotifyFunction.
+ @param Registration A pointer to a memory location to receive the registration value.
+ This value is passed to LocateHandle() to obtain new handles that
+ have been added that support the ProtocolGuid-specified protocol.
+
+ @return The notification event that was created.
+
+**/
+EFI_EVENT
+EFIAPI
+EfiCreateProtocolNotifyEvent (
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext OPTIONAL,
+ OUT VOID **Registration
+ )
+```
+
+This API abstracts the calling of `CreateEvent/RegisterProtocolNotify` functions.
+
+Keep in mind that `EfiCreateProtocolNotifyEvent` also immediately signals the callback function `NotifyFunction` manually right after the `RegisterProtocolNotify` call. So your notification function can be executed even if there are no target protocols in the system.
+
+You can see how the `EfiCreateProtocolNotifyEvent` can simplify our main code:
+```cpp
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ Event = EfiCreateProtocolNotifyEvent(&gSimpleClassProtocolGuid,
+ TPL_NOTIFY,
+ &NotifyFunc,
+ &NotifyData,
+ &mRegistrationTracker);
+ return EFI_SUCCESS;
+}
+```
+
+If you'll test this application you'll see that opposed to our own code before, here the created event is signaled one time even when there are no `SIMPLE_CLASS_PROTOCOL` protocols in the system.
+```
+FS0:\> load ProtocolEventDriver.efi
+
+Event is signaled! Context = 0 <-------
+Error! LocateProtocol returned: Not Found <-------
+Image 'FS0:\ProtocolEventDriver.efi' loaded at 6415000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 1
+Current number = 0
+, handle=640FB98
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 640C000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 2
+Current number = 0
+, handle=641A918
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 6408000 - Success
+FS0:\> load SimpleClassProtocol.efi
+Hello from SimpleClassProtocol driver
+Event is signaled! Context = 3
+Current number = 0
+, handle=6419918
+Image 'FS0:\SimpleClassProtocol.efi' loaded at 63E3000 - Success
+```
diff --git a/README.md b/README.md
index 00e7da6..69e9d1e 100644
--- a/README.md
+++ b/README.md
@@ -78,6 +78,7 @@ These series of lessons are intendend to get you started with UEFI programming i
- [Lesson 72](Lessons/Lesson_72): Dynamically add elements to HII forms with a help of a `label` keyword
- [Lesson 73](Lessons/Lesson_73): Setting defaults for the VFR questions: `default`/`defaultstore`/`resetbutton` keywords
_____
+- [Lesson XX](Lessons_uncategorized/Lesson_RegisterProtocolNotify): Register protocol installation callbacks with the `EFI_BOOT_SERVICES.RegisterProtocolNotify()` and `EfiCreateProtocolNotifyEvent` functions
- [Lesson XX](Lessons_uncategorized/Lesson_Configuration_Language_1): UEFI Configuration language. Dump current HII Database settings with the `EFI_HII_CONFIG_ROUTING_PROTOCOL.ExportConfig()` function
- [Lesson XX](Lessons_uncategorized/Lesson_Configuration_Language_2): UEFI Configuration language. Create a function to prettify configuration string data
- [Lesson XX](Lessons_uncategorized/Lesson_Configuration_Language_3): UEFI Configuration language. Extract individual form element configurations with the `EFI_HII_CONFIG_ROUTING_PROTOCOL.ExtractConfig()` function
diff --git a/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c
new file mode 100644
index 0000000..02ed0f9
--- /dev/null
+++ b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/SimpleClass.h>
+
+EFI_EVENT Event;
+STATIC VOID *mRegistrationTracker;
+UINTN NotifyData = 0;
+
+VOID EFIAPI NotifyFunc(EFI_EVENT Event, VOID* Context)
+{
+ if (Context == NULL)
+ return;
+
+ Print(L"\nEvent is signaled! Context = %d\n", *(UINTN*)Context);
+ *(UINTN*)Context += 1;
+
+ SIMPLE_CLASS_PROTOCOL* SimpleClass;
+ EFI_STATUS Status;
+ Status = gBS->LocateProtocol(&gSimpleClassProtocolGuid,
+ // NULL,
+ mRegistrationTracker,
+ (VOID**)&SimpleClass);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! LocateProtocol returned: %r\n", Status);
+ return;
+ }
+
+ UINTN Number;
+ Status = SimpleClass->GetNumber(&Number);
+ if (!EFI_ERROR(Status)) {
+ Print(L"Current number = %d\n", Number);
+ } else {
+ Print(L"Error! Can't get number: %r\n", Status);
+ return;
+ }
+
+ Status = SimpleClass->SetNumber(Number+5);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! Can't set number: %r\n", Status);
+ return;
+ }
+}
+
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverUnload (
+ EFI_HANDLE ImageHandle
+ )
+{
+ gBS->CloseEvent(Event);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ProtocolEventDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ EFI_STATUS Status;
+
+ Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ &NotifyFunc,
+ &NotifyData,
+ &Event);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! CreateEvent returned: %r\n", Status);
+ return Status;
+ }
+
+ Status = gBS->RegisterProtocolNotify(&gSimpleClassProtocolGuid,
+ Event,
+ &mRegistrationTracker);
+ if (EFI_ERROR(Status)) {
+ Print(L"Error! RegisterProtocolNotify returned: %r\n", Status);
+ return Status;
+ }
+
+/*
+ Event = EfiCreateProtocolNotifyEvent(&gSimpleClassProtocolGuid,
+ TPL_NOTIFY,
+ &NotifyFunc,
+ &NotifyData,
+ &mRegistrationTracker);
+*/
+ return EFI_SUCCESS;
+}
diff --git a/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf
new file mode 100644
index 0000000..b05651f
--- /dev/null
+++ b/UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf
@@ -0,0 +1,28 @@
+##
+# Copyright (c) 2024, Konstantin Aladyshev <aladyshev22@gmail.com>
+#
+# SPDX-License-Identifier: MIT
+##
+
+[Defines]
+ INF_VERSION = 1.25
+ BASE_NAME = ProtocolEventDriver
+ FILE_GUID = 0b59d62a-3250-42eb-9859-364faf5bc9c8
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ProtocolEventDriverEntryPoint
+ UNLOAD_IMAGE = ProtocolEventDriverUnload
+
+[Sources]
+ ProtocolEventDriver.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiLessonsPkg/UefiLessonsPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gSimpleClassProtocolGuid
diff --git a/UefiLessonsPkg/UefiLessonsPkg.dsc b/UefiLessonsPkg/UefiLessonsPkg.dsc
index d0cc2df..970b5a6 100644
--- a/UefiLessonsPkg/UefiLessonsPkg.dsc
+++ b/UefiLessonsPkg/UefiLessonsPkg.dsc
@@ -93,6 +93,7 @@
UefiLessonsPkg/SetSku/SetSku.inf
UefiLessonsPkg/HiddenSettings/HiddenSettings.inf
UefiLessonsPkg/ShowHIIext/ShowHIIext.inf
+ UefiLessonsPkg/ProtocolEventDriver/ProtocolEventDriver.inf
#[PcdsFixedAtBuild]
# gUefiLessonsPkgTokenSpaceGuid.PcdInt8|0x88|UINT8|0x3B81CDF1
diff --git a/bin/ProtocolEventDriver.efi b/bin/ProtocolEventDriver.efi
new file mode 100644
index 0000000..cd568ff
--- /dev/null
+++ b/bin/ProtocolEventDriver.efi
Binary files differ