aboutsummaryrefslogtreecommitdiffstats
path: root/Lesson_10/README.md
diff options
context:
space:
mode:
authorKonstantin Aladyshev <aladyshev22@gmail.com>2021-06-17 00:10:34 +0300
committerKonstantin Aladyshev <aladyshev22@gmail.com>2021-06-17 00:10:34 +0300
commitc24c13f0050e016a136d0ac5f7446fab258913e9 (patch)
treeec022976c89332282864799286c4ceff5d3d1d80 /Lesson_10/README.md
parentc23e8552475e9bf06a031c22bf94915eddc17764 (diff)
downloadUEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.tar.gz
UEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.tar.bz2
UEFI-Lessons-c24c13f0050e016a136d0ac5f7446fab258913e9.zip
Add lesson 10
Diffstat (limited to 'Lesson_10/README.md')
-rw-r--r--Lesson_10/README.md156
1 files changed, 156 insertions, 0 deletions
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
+```