diff options
author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-17 00:10:34 +0300 |
---|---|---|
committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-17 00:10:34 +0300 |
commit | c24c13f0050e016a136d0ac5f7446fab258913e9 (patch) | |
tree | ec022976c89332282864799286c4ceff5d3d1d80 | |
parent | c23e8552475e9bf06a031c22bf94915eddc17764 (diff) | |
download | UEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.tar.gz UEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.tar.bz2 UEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.zip |
Add lesson 10
-rw-r--r-- | Lesson_10/Conf/target.txt | 7 | ||||
-rw-r--r-- | Lesson_10/README.md | 156 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/HelloWorld/HelloWorld.c | 15 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 18 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.c | 105 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.inf | 18 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.c | 44 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.inf | 22 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 | ||||
-rw-r--r-- | Lesson_10/UefiLessonsPkg/UefiLessonsPkg.dsc | 32 | ||||
-rw-r--r-- | README.md | 1 |
12 files changed, 444 insertions, 0 deletions
diff --git a/Lesson_10/Conf/target.txt b/Lesson_10/Conf/target.txt new file mode 100644 index 0000000..c109dcf --- /dev/null +++ b/Lesson_10/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_10/README.md b/Lesson_10/README.md new file mode 100644 index 0000000..cca1dc5 --- /dev/null +++ b/Lesson_10/README.md @@ -0,0 +1,156 @@ + +It is common in UEFI code to use construct like this: +``` +if (!EFI_ERROR(Status) { + ... +} else { + ... +} +``` + +For the internal implementation of EFI_STATUS functionality look at the files: +MdePkg/Include/Uefi/UefiBaseType.h +MdePkg/Include/Base.h + +``` +#define EFI_ERROR(A) RETURN_ERROR(A) + +... + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +... + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; +``` + +So the `EFI_ERROR` macro simply test if a passed value is negative which is the same fact for a signed integer that is has high bit set. + +Enumration of possible EFI_STATUS values is in the file MdePkg/Include/Uefi/UefiBaseType.h +``` +/// +/// Enumeration of EFI_STATUS. +///@{ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE +#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA +#define EFI_HTTP_ERROR RETURN_HTTP_ERROR + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA +#define EFI_WARN_FILE_SYSTEM RETURN_WARN_FILE_SYSTEM +``` + +If you want to see how they encoded look at the MdePkg\Include\Base.h : +``` +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +<...> + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) +``` + +Let's use `EFI_ERROR` macro in our code and test error printing with the help of `%r` Print formatting option. + +We could test error display with a passing `NULL` pointer instead of ImageHandle: +``` +Print(L"________\n"); +EFI_GUID **ProtocolGuidArray; +UINTN ArrayCount; +EFI_STATUS Status = gBS->ProtocolsPerHandle(NULL, + &ProtocolGuidArray, + &ArrayCount); + +if (!EFI_ERROR(Status)) { + for (int i=0; i<ArrayCount; i++) { + Print(L"%g\n", ProtocolGuidArray[i]); + } + FreePool(ProtocolGuidArray); +} else { + Print(L"ProtocolsPerHandle error: %r\n", Status); +} +``` + +This would give us this message in OVMF: +``` +ProtocolsPerHandle error: Invalid Parameter +``` diff --git a/Lesson_10/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_10/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..1f05899 --- /dev/null +++ b/Lesson_10/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_10/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_10/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..d65ca2e --- /dev/null +++ b/Lesson_10/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_10/UefiLessonsPkg/ImageHandle/ImageHandle.c b/Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.c new file mode 100644 index 0000000..32e9c43 --- /dev/null +++ b/Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.c @@ -0,0 +1,105 @@ +#include <Library/MemoryAllocationLib.h> +#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); + + Print(L"________\n"); + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + //EFI_STATUS Status = gBS->ProtocolsPerHandle(NULL, // Use this to test %r Print formatting option + EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle, + &ProtocolGuidArray, + &ArrayCount); + + if (!EFI_ERROR(Status)) { + for (int i=0; i<ArrayCount; i++) { + Print(L"%g\n", ProtocolGuidArray[i]); + } + FreePool(ProtocolGuidArray); + } else { + Print(L"ProtocolsPerHandle error: %r\n", Status); + } + + return EFI_SUCCESS; +} diff --git a/Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.inf b/Lesson_10/UefiLessonsPkg/ImageHandle/ImageHandle.inf new file mode 100644 index 0000000..34256ee --- /dev/null +++ b/Lesson_10/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_10/UefiLessonsPkg/ImageInfo/ImageInfo.c b/Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.c new file mode 100644 index 0000000..c45570e --- /dev/null +++ b/Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.c @@ -0,0 +1,44 @@ +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/LoadedImage.h> +#include <Library/DevicePathLib.h> + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + if (Status == EFI_SUCCESS) { + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID**) &DevicePath + ); + + if (Status == EFI_SUCCESS) { + Print(L"Image device: %s\n", ConvertDevicePathToText(DevicePath, FALSE, TRUE)); + Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath, FALSE, TRUE)); // EFI_DEVICE_PATH_PROTOCOL *FilePath + Print(L"Image Base: %X\n", LoadedImage->ImageBase); + Print(L"Image Size: %X\n", LoadedImage->ImageSize); + } else { + Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n", Status); + } + } else { + Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n", Status); + } + return EFI_SUCCESS; +} diff --git a/Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.inf b/Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.inf new file mode 100644 index 0000000..0ce54a6 --- /dev/null +++ b/Lesson_10/UefiLessonsPkg/ImageInfo/ImageInfo.inf @@ -0,0 +1,22 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ImageInfo + FILE_GUID = b68d3472-70c7-4928-841b-6566032e0a23 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +[Sources] + ImageInfo.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiLoadedImageDevicePathProtocolGuid + diff --git a/Lesson_10/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_10/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_10/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_10/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_10/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_10/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_10/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_10/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..ff2edf6 --- /dev/null +++ b/Lesson_10/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,32 @@ +[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 + UefiLessonsPkg/ImageInfo/ImageInfo.inf + + @@ -12,3 +12,4 @@ Lessons description: - Lesson 7: Handle/Protocol databases internals - Part 2: Raw access to app protocols - Lesson 8: `HandleProtocol` API function. Information from the `ImageHandle` protocols - Lesson 9: Get ImageHandle protocols with the `ProtocolsPerHandle` API function +- Lesson 10: `EFI_STATUS` type and `EFI_ERROR` macros |