From c24c13f0050e016a136d0ac5f7446fab258913e9 Mon Sep 17 00:00:00 2001 From: Konstantin Aladyshev Date: Thu, 17 Jun 2021 00:10:34 +0300 Subject: Add lesson 10 --- Lesson_10/README.md | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 Lesson_10/README.md (limited to 'Lesson_10/README.md') 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