Pablo Greco d6c4c4
From c8218e9b3c38fcd36a2d06eec09952a0c6cee9e0 Mon Sep 17 00:00:00 2001
Pablo Greco d6c4c4
From: Peter Jones <pjones@redhat.com>
Pablo Greco d6c4c4
Date: Mon, 2 Oct 2017 18:22:13 -0400
Pablo Greco d6c4c4
Subject: [PATCH 2/3] Add efi_status_to_str() and rework efi_status_to_err().
Pablo Greco d6c4c4
Pablo Greco d6c4c4
This adds efi_status_to_str() for use when printing efi_status_t
Pablo Greco d6c4c4
messages, and reworks efi_status_to_err() so that the two use a common
Pablo Greco d6c4c4
list of errors.
Pablo Greco d6c4c4
Pablo Greco d6c4c4
Signed-off-by: Peter Jones <pjones@redhat.com>
Pablo Greco d6c4c4
---
Pablo Greco d6c4c4
 include/linux/efi.h        |   3 ++
Pablo Greco d6c4c4
 drivers/firmware/efi/efi.c | 122 ++++++++++++++++++++++++++++++++++-----------
Pablo Greco d6c4c4
 2 files changed, 95 insertions(+), 30 deletions(-)
Pablo Greco d6c4c4
Pablo Greco d6c4c4
diff --git a/include/linux/efi.h b/include/linux/efi.h
Pablo Greco d6c4c4
index 18b16bf5ce1..436b3c93c3d 100644
Pablo Greco d6c4c4
--- a/include/linux/efi.h
Pablo Greco d6c4c4
+++ b/include/linux/efi.h
Pablo Greco d6c4c4
@@ -42,6 +42,8 @@
Pablo Greco d6c4c4
 #define EFI_ABORTED		(21 | (1UL << (BITS_PER_LONG-1)))
Pablo Greco d6c4c4
 #define EFI_SECURITY_VIOLATION	(26 | (1UL << (BITS_PER_LONG-1)))
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
+#define EFI_IS_ERROR(x)		((x) & (1UL << (BITS_PER_LONG-1)))
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
 typedef unsigned long efi_status_t;
Pablo Greco d6c4c4
 typedef u8 efi_bool_t;
Pablo Greco d6c4c4
 typedef u16 efi_char16_t;		/* UNICODE character */
Pablo Greco d6c4c4
@@ -1183,6 +1185,7 @@ static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {}
Pablo Greco d6c4c4
 #endif
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
 extern int efi_status_to_err(efi_status_t status);
Pablo Greco d6c4c4
+extern const char *efi_status_to_str(efi_status_t status);
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
 /*
Pablo Greco d6c4c4
  * Variable Attributes
Pablo Greco d6c4c4
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
Pablo Greco d6c4c4
index 557a47829d0..e8f9c7d84e9 100644
Pablo Greco d6c4c4
--- a/drivers/firmware/efi/efi.c
Pablo Greco d6c4c4
+++ b/drivers/firmware/efi/efi.c
Pablo Greco d6c4c4
@@ -31,6 +31,7 @@
Pablo Greco d6c4c4
 #include <linux/ucs2_string.h>
Pablo Greco d6c4c4
 #include <linux/memblock.h>
Pablo Greco d6c4c4
 #include <linux/security.h>
Pablo Greco d6c4c4
+#include <linux/bsearch.h>
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
 #include <asm/early_ioremap.h>
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
@@ -865,40 +866,101 @@ int efi_mem_type(unsigned long phys_addr)
Pablo Greco d6c4c4
 }
Pablo Greco d6c4c4
 #endif
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
+struct efi_error_code {
Pablo Greco d6c4c4
+	efi_status_t status;
Pablo Greco d6c4c4
+	int errno;
Pablo Greco d6c4c4
+	const char *description;
Pablo Greco d6c4c4
+};
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
+static const struct efi_error_code efi_error_codes[] = {
Pablo Greco d6c4c4
+	{ EFI_SUCCESS, 0, "Success"},
Pablo Greco d6c4c4
+#if 0
Pablo Greco d6c4c4
+	{ EFI_LOAD_ERROR, -EPICK_AN_ERRNO, "Load Error"},
Pablo Greco d6c4c4
+#endif
Pablo Greco d6c4c4
+	{ EFI_INVALID_PARAMETER, -EINVAL, "Invalid Parameter"},
Pablo Greco d6c4c4
+	{ EFI_UNSUPPORTED, -ENOSYS, "Unsupported"},
Pablo Greco d6c4c4
+	{ EFI_BAD_BUFFER_SIZE, -ENOSPC, "Bad Buffer Size"},
Pablo Greco d6c4c4
+	{ EFI_BUFFER_TOO_SMALL, -ENOSPC, "Buffer Too Small"},
Pablo Greco d6c4c4
+	{ EFI_NOT_READY, -EAGAIN, "Not Ready"},
Pablo Greco d6c4c4
+	{ EFI_DEVICE_ERROR, -EIO, "Device Error"},
Pablo Greco d6c4c4
+	{ EFI_WRITE_PROTECTED, -EROFS, "Write Protected"},
Pablo Greco d6c4c4
+	{ EFI_OUT_OF_RESOURCES, -ENOMEM, "Out of Resources"},
Pablo Greco d6c4c4
+#if 0
Pablo Greco d6c4c4
+	{ EFI_VOLUME_CORRUPTED, -EPICK_AN_ERRNO, "Volume Corrupt"},
Pablo Greco d6c4c4
+	{ EFI_VOLUME_FULL, -EPICK_AN_ERRNO, "Volume Full"},
Pablo Greco d6c4c4
+	{ EFI_NO_MEDIA, -EPICK_AN_ERRNO, "No Media"},
Pablo Greco d6c4c4
+	{ EFI_MEDIA_CHANGED, -EPICK_AN_ERRNO, "Media changed"},
Pablo Greco d6c4c4
+#endif
Pablo Greco d6c4c4
+	{ EFI_NOT_FOUND, -ENOENT, "Not Found"},
Pablo Greco d6c4c4
+#if 0
Pablo Greco d6c4c4
+	{ EFI_ACCESS_DENIED, -EPICK_AN_ERRNO, "Access Denied"},
Pablo Greco d6c4c4
+	{ EFI_NO_RESPONSE, -EPICK_AN_ERRNO, "No Response"},
Pablo Greco d6c4c4
+	{ EFI_NO_MAPPING, -EPICK_AN_ERRNO, "No mapping"},
Pablo Greco d6c4c4
+	{ EFI_TIMEOUT, -EPICK_AN_ERRNO, "Time out"},
Pablo Greco d6c4c4
+	{ EFI_NOT_STARTED, -EPICK_AN_ERRNO, "Not started"},
Pablo Greco d6c4c4
+	{ EFI_ALREADY_STARTED, -EPICK_AN_ERRNO, "Already started"},
Pablo Greco d6c4c4
+#endif
Pablo Greco d6c4c4
+	{ EFI_ABORTED, -EINTR, "Aborted"},
Pablo Greco d6c4c4
+#if 0
Pablo Greco d6c4c4
+	{ EFI_ICMP_ERROR, -EPICK_AN_ERRNO, "ICMP Error"},
Pablo Greco d6c4c4
+	{ EFI_TFTP_ERROR, -EPICK_AN_ERRNO, "TFTP Error"},
Pablo Greco d6c4c4
+	{ EFI_PROTOCOL_ERROR, -EPICK_AN_ERRNO, "Protocol Error"},
Pablo Greco d6c4c4
+	{ EFI_INCOMPATIBLE_VERSION, -EPICK_AN_ERRNO, "Incompatible Version"},
Pablo Greco d6c4c4
+#endif
Pablo Greco d6c4c4
+	{ EFI_SECURITY_VIOLATION, -EACCES, "Security Policy Violation"},
Pablo Greco d6c4c4
+#if 0
Pablo Greco d6c4c4
+	{ EFI_CRC_ERROR, -EPICK_AN_ERRNO, "CRC Error"},
Pablo Greco d6c4c4
+	{ EFI_END_OF_MEDIA, -EPICK_AN_ERRNO, "End of Media"},
Pablo Greco d6c4c4
+	{ EFI_END_OF_FILE, -EPICK_AN_ERRNO, "End of File"},
Pablo Greco d6c4c4
+	{ EFI_INVALID_LANGUAGE, -EPICK_AN_ERRNO, "Invalid Languages"},
Pablo Greco d6c4c4
+	{ EFI_COMPROMISED_DATA, -EPICK_AN_ERRNO, "Compromised Data"},
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
+	// warnings
Pablo Greco d6c4c4
+	{ EFI_WARN_UNKOWN_GLYPH, -EPICK_AN_ERRNO, "Warning Unknown Glyph"},
Pablo Greco d6c4c4
+	{ EFI_WARN_DELETE_FAILURE, -EPICK_AN_ERRNO, "Warning Delete Failure"},
Pablo Greco d6c4c4
+	{ EFI_WARN_WRITE_FAILURE, -EPICK_AN_ERRNO, "Warning Write Failure"},
Pablo Greco d6c4c4
+	{ EFI_WARN_BUFFER_TOO_SMALL, -EPICK_AN_ERRNO, "Warning Buffer Too Small"},
Pablo Greco d6c4c4
+#endif
Pablo Greco d6c4c4
+};
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
+static int
Pablo Greco d6c4c4
+efi_status_cmp_bsearch(const void *key, const void *item)
Pablo Greco d6c4c4
+{
Pablo Greco d6c4c4
+	u64 status = (u64)(uintptr_t)key;
Pablo Greco d6c4c4
+	struct efi_error_code *code = (struct efi_error_code *)item;
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
+	if (status < code->status)
Pablo Greco d6c4c4
+		return -1;
Pablo Greco d6c4c4
+	if (status > code->status)
Pablo Greco d6c4c4
+		return 1;
Pablo Greco d6c4c4
+	return 0;
Pablo Greco d6c4c4
+}
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
 int efi_status_to_err(efi_status_t status)
Pablo Greco d6c4c4
 {
Pablo Greco d6c4c4
-	int err;
Pablo Greco d6c4c4
+	struct efi_error_code *found;
Pablo Greco d6c4c4
+	size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
-	switch (status) {
Pablo Greco d6c4c4
-	case EFI_SUCCESS:
Pablo Greco d6c4c4
-		err = 0;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_INVALID_PARAMETER:
Pablo Greco d6c4c4
-		err = -EINVAL;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_OUT_OF_RESOURCES:
Pablo Greco d6c4c4
-		err = -ENOSPC;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_DEVICE_ERROR:
Pablo Greco d6c4c4
-		err = -EIO;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_WRITE_PROTECTED:
Pablo Greco d6c4c4
-		err = -EROFS;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_SECURITY_VIOLATION:
Pablo Greco d6c4c4
-		err = -EACCES;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_NOT_FOUND:
Pablo Greco d6c4c4
-		err = -ENOENT;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	case EFI_ABORTED:
Pablo Greco d6c4c4
-		err = -EINTR;
Pablo Greco d6c4c4
-		break;
Pablo Greco d6c4c4
-	default:
Pablo Greco d6c4c4
-		err = -EINVAL;
Pablo Greco d6c4c4
-	}
Pablo Greco d6c4c4
+	found = bsearch((void *)(uintptr_t)status, efi_error_codes,
Pablo Greco d6c4c4
+			sizeof(struct efi_error_code), num,
Pablo Greco d6c4c4
+			efi_status_cmp_bsearch);
Pablo Greco d6c4c4
+	if (!found)
Pablo Greco d6c4c4
+		return -EINVAL;
Pablo Greco d6c4c4
+	return found->errno;
Pablo Greco d6c4c4
+}
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
-	return err;
Pablo Greco d6c4c4
+const char *
Pablo Greco d6c4c4
+efi_status_to_str(efi_status_t status)
Pablo Greco d6c4c4
+{
Pablo Greco d6c4c4
+	struct efi_error_code *found;
Pablo Greco d6c4c4
+	size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);
Pablo Greco d6c4c4
+
Pablo Greco d6c4c4
+	found = bsearch((void *)(uintptr_t)status, efi_error_codes,
Pablo Greco d6c4c4
+			sizeof(struct efi_error_code), num,
Pablo Greco d6c4c4
+			efi_status_cmp_bsearch);
Pablo Greco d6c4c4
+	if (!found)
Pablo Greco d6c4c4
+		return "Unknown error code";
Pablo Greco d6c4c4
+	return found->description;
Pablo Greco d6c4c4
 }
Pablo Greco d6c4c4
 
Pablo Greco d6c4c4
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
Pablo Greco d6c4c4
-- 
Pablo Greco d6c4c4
2.15.0
Pablo Greco d6c4c4