Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add efi_status_to_str() and rework efi_status_to_err().
jira LE-2629
feature Fedora EFI status status
ommit 7a60169d168d6aae70aca10b7b71070666068529
commit-source https://gitlab.com/cki-project/kernel-ark/

This adds efi_status_to_str() for use when printing efi_status_t
messages, and reworks efi_status_to_err() so that the two use a common
list of errors.

Upstream Status: RHEL only
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
  • Loading branch information
vathpela authored and bmastbergen committed Jun 16, 2025
commit 750b50e02840a7dcc2aac41a8ceef07c5b2e2445
124 changes: 93 additions & 31 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/memblock.h>
#include <linux/security.h>
#include <linux/notifier.h>
#include <linux/bsearch.h>

#include <asm/early_ioremap.h>

Expand Down Expand Up @@ -995,40 +996,101 @@ int efi_mem_type(unsigned long phys_addr)
return -EINVAL;
}

struct efi_error_code {
efi_status_t status;
int errno;
const char *description;
};

static const struct efi_error_code efi_error_codes[] = {
{ EFI_SUCCESS, 0, "Success"},
#if 0
{ EFI_LOAD_ERROR, -EPICK_AN_ERRNO, "Load Error"},
#endif
{ EFI_INVALID_PARAMETER, -EINVAL, "Invalid Parameter"},
{ EFI_UNSUPPORTED, -ENOSYS, "Unsupported"},
{ EFI_BAD_BUFFER_SIZE, -ENOSPC, "Bad Buffer Size"},
{ EFI_BUFFER_TOO_SMALL, -ENOSPC, "Buffer Too Small"},
{ EFI_NOT_READY, -EAGAIN, "Not Ready"},
{ EFI_DEVICE_ERROR, -EIO, "Device Error"},
{ EFI_WRITE_PROTECTED, -EROFS, "Write Protected"},
{ EFI_OUT_OF_RESOURCES, -ENOMEM, "Out of Resources"},
#if 0
{ EFI_VOLUME_CORRUPTED, -EPICK_AN_ERRNO, "Volume Corrupt"},
{ EFI_VOLUME_FULL, -EPICK_AN_ERRNO, "Volume Full"},
{ EFI_NO_MEDIA, -EPICK_AN_ERRNO, "No Media"},
{ EFI_MEDIA_CHANGED, -EPICK_AN_ERRNO, "Media changed"},
#endif
{ EFI_NOT_FOUND, -ENOENT, "Not Found"},
#if 0
{ EFI_ACCESS_DENIED, -EPICK_AN_ERRNO, "Access Denied"},
{ EFI_NO_RESPONSE, -EPICK_AN_ERRNO, "No Response"},
{ EFI_NO_MAPPING, -EPICK_AN_ERRNO, "No mapping"},
{ EFI_TIMEOUT, -EPICK_AN_ERRNO, "Time out"},
{ EFI_NOT_STARTED, -EPICK_AN_ERRNO, "Not started"},
{ EFI_ALREADY_STARTED, -EPICK_AN_ERRNO, "Already started"},
#endif
{ EFI_ABORTED, -EINTR, "Aborted"},
#if 0
{ EFI_ICMP_ERROR, -EPICK_AN_ERRNO, "ICMP Error"},
{ EFI_TFTP_ERROR, -EPICK_AN_ERRNO, "TFTP Error"},
{ EFI_PROTOCOL_ERROR, -EPICK_AN_ERRNO, "Protocol Error"},
{ EFI_INCOMPATIBLE_VERSION, -EPICK_AN_ERRNO, "Incompatible Version"},
#endif
{ EFI_SECURITY_VIOLATION, -EACCES, "Security Policy Violation"},
#if 0
{ EFI_CRC_ERROR, -EPICK_AN_ERRNO, "CRC Error"},
{ EFI_END_OF_MEDIA, -EPICK_AN_ERRNO, "End of Media"},
{ EFI_END_OF_FILE, -EPICK_AN_ERRNO, "End of File"},
{ EFI_INVALID_LANGUAGE, -EPICK_AN_ERRNO, "Invalid Languages"},
{ EFI_COMPROMISED_DATA, -EPICK_AN_ERRNO, "Compromised Data"},

// warnings
{ EFI_WARN_UNKOWN_GLYPH, -EPICK_AN_ERRNO, "Warning Unknown Glyph"},
{ EFI_WARN_DELETE_FAILURE, -EPICK_AN_ERRNO, "Warning Delete Failure"},
{ EFI_WARN_WRITE_FAILURE, -EPICK_AN_ERRNO, "Warning Write Failure"},
{ EFI_WARN_BUFFER_TOO_SMALL, -EPICK_AN_ERRNO, "Warning Buffer Too Small"},
#endif
};

static int
efi_status_cmp_bsearch(const void *key, const void *item)
{
u64 status = (u64)(uintptr_t)key;
struct efi_error_code *code = (struct efi_error_code *)item;

if (status < code->status)
return -1;
if (status > code->status)
return 1;
return 0;
}

int efi_status_to_err(efi_status_t status)
{
int err;

switch (status) {
case EFI_SUCCESS:
err = 0;
break;
case EFI_INVALID_PARAMETER:
err = -EINVAL;
break;
case EFI_OUT_OF_RESOURCES:
err = -ENOSPC;
break;
case EFI_DEVICE_ERROR:
err = -EIO;
break;
case EFI_WRITE_PROTECTED:
err = -EROFS;
break;
case EFI_SECURITY_VIOLATION:
err = -EACCES;
break;
case EFI_NOT_FOUND:
err = -ENOENT;
break;
case EFI_ABORTED:
err = -EINTR;
break;
default:
err = -EINVAL;
}
struct efi_error_code *found;
size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);

return err;
found = bsearch((void *)(uintptr_t)status, efi_error_codes,
sizeof(struct efi_error_code), num,
efi_status_cmp_bsearch);
if (!found)
return -EINVAL;
return found->errno;
}

const char *
efi_status_to_str(efi_status_t status)
{
struct efi_error_code *found;
size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);

found = bsearch((void *)(uintptr_t)status, efi_error_codes,
sizeof(struct efi_error_code), num,
efi_status_cmp_bsearch);
if (!found)
return "Unknown error code";
return found->description;
}
EXPORT_SYMBOL_GPL(efi_status_to_err);

Expand Down
3 changes: 3 additions & 0 deletions include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ struct screen_info;
#define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1)))
#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))

#define EFI_IS_ERROR(x) ((x) & (1UL << (BITS_PER_LONG-1)))

typedef unsigned long efi_status_t;
typedef u8 efi_bool_t;
typedef u16 efi_char16_t; /* UNICODE character */
Expand Down Expand Up @@ -933,6 +935,7 @@ static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {}
#endif

extern int efi_status_to_err(efi_status_t status);
extern const char *efi_status_to_str(efi_status_t status);

/*
* Variable Attributes
Expand Down