This RFC patch introduces a UEFI error message printer that translates
UEFI status codes from hexadecimal values into human-readable strings.

The idea is inspired by the GNU C Library's "perror()" function, which 
translates
"errno" values into descriptive error messages. Similarly, this implementation 
eliminates
the need for conditional statements when printing UEFI error messages. In 
short, it's a "perror"-like
mechanism tailored for UEFI status codes in GRUB.

The function takes three parameter:
  - "grub_err_t err": if the caller desires to set errno. Caller can safely
    return errno if it wants to return status code.
  - "const char *s": a null-terminated string that further
    describes the error context, like the reason of failure.
  - "EFI_STATUS status": the UEFI status code returned by a call to UEFI
    service, to translate to string.

Additionally, if this patch is accepted, it maybe better if we propogate
this function throughout UEFI subsystem. That would mean replacing some
grub_error() calls to this function as it is the one who is calling it
internally, putting on UEFI service calls in case of failure to check and print
status codes. Then the caller can safely return "grub_errno" if there
were a failure. The benefit would be clearer, and more descriptive error 
messages,
instead of raw hex codes and reduction of the amount of code needed for
printing error messages like conditional statements. This will improve user 
experience, 
debugging clarity and code readability.

Looking forward for your feedback and what community think of this idea
and the code. Additionally i left something i felt worth dicussing with
the commuinty, which is if translation is ideal on this context.

Best regard
khaalid

Signed-off-by: Khalid Ali <khaliidca...@gmail.com>
---
 grub-core/kern/efi/err.c | 81 ++++++++++++++++++++++++++++++++++++++++
 include/grub/efi/api.h   |  6 +++
 include/grub/efi/efi.h   |  3 ++
 3 files changed, 90 insertions(+)
 create mode 100644 grub-core/kern/efi/err.c

diff --git a/grub-core/kern/efi/err.c b/grub-core/kern/efi/err.c
new file mode 100644
index 000000000..b870b26ba
--- /dev/null
+++ b/grub-core/kern/efi/err.c
@@ -0,0 +1,81 @@
+/* err.c - uefi specific error handling routine */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2025 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+struct grub_efi_err
+{
+    grub_efi_status_t status;
+    const char *error_msg;
+};
+
+/* EFI error table: keep entries sorted alphabetically. */
+static const struct grub_efi_err grub_efi_err_table[] = 
+{
+    {GRUB_EFI_ABORTED, "aborted"},
+    {GRUB_EFI_ACCESS_DENIED, "access denied"},
+    {GRUB_EFI_ALREADY_STARTED, "already started"},
+    {GRUB_EFI_BAD_BUFFER_SIZE, "bad buffer size"},
+    {GRUB_EFI_BUFFER_TOO_SMALL, "buffer too small"},
+    {GRUB_EFI_CRC_ERROR, "crc error"},
+    {GRUB_EFI_DEVICE_ERROR, "device error"},
+    {GRUB_EFI_END_OF_FILE, "end of file"},
+    {GRUB_EFI_END_OF_MEDIA, "end of media"},
+    {GRUB_EFI_HTTP_ERROR, "http error"},
+    {GRUB_EFI_ICMP_ERROR, "icmp error"},
+    {GRUB_EFI_INCOMPATIBLE_VERSION, "incompatible version"},
+    {GRUB_EFI_INVALID_PARAMETER, "invalid parameter"},
+    {GRUB_EFI_IP_ADDRESS_CONFLICT, "ip address conflict"},
+    {GRUB_EFI_LOAD_ERROR, "load error"},
+    {GRUB_EFI_MEDIA_CHANGED, "media changed"},
+    {GRUB_EFI_NO_MAPPING, "no mapping"},
+    {GRUB_EFI_NO_MEDIA, "no media"},
+    {GRUB_EFI_NO_RESPONSE, "no response"},
+    {GRUB_EFI_NOT_FOUND, "not found"},
+    {GRUB_EFI_NOT_READY, "not ready"},
+    {GRUB_EFI_NOT_STARTED, "not started"},
+    {GRUB_EFI_OUT_OF_RESOURCES, "out of resources"},
+    {GRUB_EFI_PROTOCOL_ERROR, "protocol error"},
+    {GRUB_EFI_SECURITY_VIOLATION, "security violation"},
+    {GRUB_EFI_SUCCESS, "success"},
+    {GRUB_EFI_TFTP_ERROR, "tftp error"},
+    {GRUB_EFI_TIMEOUT, "timed out"},
+    {GRUB_EFI_UNSPECIFIED_TIMEZONE, "unspecified timezone"},
+    {GRUB_EFI_UNSUPPORTED, "unsupported"},
+    {GRUB_EFI_VOLUME_CORRUPTED, "volume corrupted"},
+    {GRUB_EFI_VOLUME_FULL, "volume full"},
+    {GRUB_EFI_WRITE_PROTECTED, "write protected"}
+};
+
+void
+grub_efi_perror(grub_err_t err, const char *s, grub_efi_status_t status)
+{
+    for (grub_size_t i = 0; i < ARRAY_SIZE(grub_efi_err_table); i++) 
+    {
+        if (grub_efi_err_table[i].status == status)
+        {
+            grub_error (err, "%s : %s", s, grub_efi_err_table[i].error_msg);
+            return; /* we got what we needed, that is enough*/
+        } 
+    }
+    grub_error (err, "%s : unknown error", s);
+}
\ No newline at end of file
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index b686e8afe..f74bc0287 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -632,6 +632,12 @@ typedef grub_efi_uintn_t grub_efi_status_t;
 #define GRUB_EFI_INCOMPATIBLE_VERSION  GRUB_EFI_ERROR_CODE (25)
 #define GRUB_EFI_SECURITY_VIOLATION    GRUB_EFI_ERROR_CODE (26)
 #define GRUB_EFI_CRC_ERROR             GRUB_EFI_ERROR_CODE (27)
+#define GRUB_EFI_END_OF_MEDIA GRUB_EFI_ERROR_CODE (28)
+#define GRUB_EFI_END_OF_FILE GRUB_EFI_ERROR_CODE (31)
+#define GRUB_EFI_INVALID_LANGUAGE GRUB_EFI_ERROR_CODE (32)
+#define GRUB_EFI_COMPROMISED_DATA GRUB_EFI_ERROR_CODE (33)
+#define GRUB_EFI_IP_ADDRESS_CONFLICT GRUB_EFI_ERROR_CODE (34)
+#define GRUB_EFI_HTTP_ERROR GRUB_EFI_ERROR_CODE (35)
 
 #define GRUB_EFI_WARN_UNKNOWN_GLYPH    GRUB_EFI_WARNING_CODE (1)
 #define GRUB_EFI_WARN_DELETE_FAILURE   GRUB_EFI_WARNING_CODE (2)
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index a5cd99e5a..8e91eaad4 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -122,6 +122,9 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) 
(grub_efi_handle_t hnd,
 void *
 EXPORT_FUNC (grub_efi_find_configuration_table) (const grub_guid_t 
*target_guid);
 
+void
+EXPORT_FUNC (grub_efi_perror) (grub_err_t err, const char *s, 
grub_efi_status_t status);
+
 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || 
defined(__loongarch__)
 void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
 grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
-- 
2.49.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to