summaryrefslogtreecommitdiff
path: root/lib/uefi.c3l/src/err.c3
diff options
context:
space:
mode:
authorandromeda <andromeda@bsd.my.domain>2026-10-19 01:41:59 -0400
committerandromeda <andromeda@bsd.my.domain>2026-10-19 01:41:59 -0400
commit7ebe14b3275fba00662e0c0ceeabe96343d04c5a (patch)
treea594923a4073c1eb1db766d41da297a715220479 /lib/uefi.c3l/src/err.c3
init
Diffstat (limited to 'lib/uefi.c3l/src/err.c3')
-rw-r--r--lib/uefi.c3l/src/err.c3129
1 files changed, 129 insertions, 0 deletions
diff --git a/lib/uefi.c3l/src/err.c3 b/lib/uefi.c3l/src/err.c3
new file mode 100644
index 0000000..d21729b
--- /dev/null
+++ b/lib/uefi.c3l/src/err.c3
@@ -0,0 +1,129 @@
+/* EFI errors can actually be faults: they should raise exceptions
+ in the handling of a program, if the user so chooses to. */
+module uefi::efi_error;
+faultdef
+ NO_FAULT,
+ LOAD_ERROR,
+ INVALID_PARAMETER,
+ UNSUPPORTED,
+ BAD_BUFFER_SIZE,
+ BUFFER_TOO_SMALL,
+ NOT_READY,
+ DEVICE_ERROR,
+ WRITE_PROTECTED,
+ OUT_OF_RESOURCES,
+ VOLUME_CORRUPTED,
+ VOLUME_FULL,
+ NO_MEDIA,
+ MEDIA_CHANGED,
+ NOT_FOUND,
+ ACCESS_DENIED,
+ NO_RESPONSE,
+ NO_MAPPING,
+ TIMEOUT,
+ NOT_STARTED,
+ ALREADY_STARTED,
+ ABORTED,
+ ICMP_ERROR,
+ TFTP_ERROR,
+ PROTOCOL_ERROR,
+ INCOMPATIBLE_VERSION,
+ SECURITY_VIOLATION,
+ CRC_ERROR,
+ END_OF_MEDIA,
+ UNKNOWN_29, // NOTE: UEFI spec is missing this definition.
+ UNKNOWN_30, // NOTE: UEFI spec is missing this definition.
+ END_OF_FILE,
+ INVALID_LANGUAGE,
+ COMPROMISED_DATA,
+ IP_ADDRESS_CONFLICT,
+ HTTP_ERROR,
+ EFILIB_UNINITIALIZED, // Used for efilib calls when init() hasn't been called.
+ UNKNOWN_STATUS; /* Fallback for an unknown status code. */
+
+module uefi::efi_warning;
+faultdef
+ UNKNOWN_GLYPH, DELETE_FAILURE, WRITE_FAILURE, BUFFER_TOO_SMALL, STALE_DATA, FILE_SYSTEM, RESET_REQUIRED;
+
+
+module uefi;
+
+import uefi::efi_error;
+import uefi::efi_warning;
+
+/** EFI_STATUS enum (apx D of the UEFI 2.11 specification). */
+macro @efi_err($x) @private => (usz)((1l << ((usz::size * 8) - 1)) | $x);
+macro @efi_warn($x) @private => (usz)$x;
+
+enum EfiStatus : usz (usz raw, fault fault_type)
+{
+ SUCCESS { 0, efi_error::NO_FAULT },
+
+ LOAD_ERROR { @efi_err(1), efi_error::LOAD_ERROR },
+ INVALID_PARAMETER { @efi_err(2), efi_error::INVALID_PARAMETER },
+ UNSUPPORTED { @efi_err(3), efi_error::UNSUPPORTED },
+ BAD_BUFFER_SIZE { @efi_err(4), efi_error::BAD_BUFFER_SIZE },
+ BUFFER_TOO_SMALL { @efi_err(5), efi_error::BUFFER_TOO_SMALL },
+ NOT_READY { @efi_err(6), efi_error::NOT_READY },
+ DEVICE_ERROR { @efi_err(7), efi_error::DEVICE_ERROR },
+ WRITE_PROTECTED { @efi_err(8), efi_error::WRITE_PROTECTED },
+ OUT_OF_RESOURCES { @efi_err(9), efi_error::OUT_OF_RESOURCES },
+ VOLUME_CORRUPTED { @efi_err(10), efi_error::VOLUME_CORRUPTED },
+ VOLUME_FULL { @efi_err(11), efi_error::VOLUME_FULL },
+ NO_MEDIA { @efi_err(12), efi_error::NO_MEDIA },
+ MEDIA_CHANGED { @efi_err(13), efi_error::MEDIA_CHANGED },
+ NOT_FOUND { @efi_err(14), efi_error::NOT_FOUND },
+ ACCESS_DENIED { @efi_err(15), efi_error::ACCESS_DENIED },
+ NO_RESPONSE { @efi_err(16), efi_error::NO_RESPONSE },
+ NO_MAPPING { @efi_err(17), efi_error::NO_MAPPING },
+ TIMEOUT { @efi_err(18), efi_error::TIMEOUT },
+ NOT_STARTED { @efi_err(19), efi_error::NOT_STARTED },
+ ALREADY_STARTED { @efi_err(20), efi_error::ALREADY_STARTED },
+ ABORTED { @efi_err(21), efi_error::ABORTED },
+ ICMP_ERROR { @efi_err(22), efi_error::ICMP_ERROR },
+ TFTP_ERROR { @efi_err(23), efi_error::TFTP_ERROR },
+ PROTOCOL_ERROR { @efi_err(24), efi_error::PROTOCOL_ERROR },
+ INCOMPATIBLE_VERSION { @efi_err(25), efi_error::INCOMPATIBLE_VERSION },
+ SECURITY_VIOLATION { @efi_err(26), efi_error::SECURITY_VIOLATION },
+ CRC_ERROR { @efi_err(27), efi_error::CRC_ERROR },
+ END_OF_MEDIA { @efi_err(28), efi_error::END_OF_MEDIA },
+ UNKNOWN_29 { @efi_err(29), efi_error::UNKNOWN_29 }, /* NOTE: UEFI spec is missing this definition. */
+ UNKNOWN_30 { @efi_err(30), efi_error::UNKNOWN_30 }, /* NOTE: UEFI spec is missing this definition. */
+ END_OF_FILE { @efi_err(31), efi_error::END_OF_FILE },
+ INVALID_LANGUAGE { @efi_err(32), efi_error::INVALID_LANGUAGE },
+ COMPROMISED_DATA { @efi_err(33), efi_error::COMPROMISED_DATA },
+ IP_ADDRESS_CONFLICT { @efi_err(34), efi_error::IP_ADDRESS_CONFLICT },
+ HTTP_ERROR { @efi_err(35), efi_error::HTTP_ERROR },
+
+ WARN_UNKNOWN_GLYPH { @efi_warn(1), efi_warning::UNKNOWN_GLYPH },
+ WARN_DELETE_FAILURE { @efi_warn(2), efi_warning::DELETE_FAILURE },
+ WARN_WRITE_FAILURE { @efi_warn(3), efi_warning::WRITE_FAILURE },
+ WARN_BUFFER_TOO_SMALL { @efi_warn(4), efi_warning::BUFFER_TOO_SMALL },
+ WARN_STALE_DATA { @efi_warn(5), efi_warning::STALE_DATA },
+ WARN_FILE_SYSTEM { @efi_warn(6), efi_warning::FILE_SYSTEM },
+ WARN_RESET_REQUIRED { @efi_warn(7), efi_warning::RESET_REQUIRED },
+}
+
+
+// //////////////////////////////////////////////////////////////////////
+<*
+ Handle EFI errors when they occur.
+ @param status : `The EfiStatus code to check`
+ @param throw_on_warnings : `Return a ``true`` value on EFI_WARN_... codes`
+ @return ```false`` on success. ``true`` when ``throw_on_warnings`` is false and ``status`` is a warning. Returns a fault otherwise.`
+*>
+fn bool? efi_error(EfiStatus status, bool throw_on_warnings = true) @export("efi_error") @builtin
+{
+ switch
+ {
+ case status == SUCCESS: return false;
+
+ case status >= EfiStatus.WARN_UNKNOWN_GLYPH && status <= EfiStatus.WARN_RESET_REQUIRED:
+ return throw_on_warnings ? status.fault_type~ : true;
+
+ case status >= EfiStatus.LOAD_ERROR && status <= EfiStatus.HTTP_ERROR:
+ return status.fault_type~;
+ }
+
+ return efi_error::UNKNOWN_STATUS~;
+} \ No newline at end of file