From: "Lee, Chun-Yi" <jlee@suse.com>
Date: Tue, 1 Dec 2015 01:04:32 +0800
Subject: [PATCH] x86/efi: Fix invalid parameter error when getting hibernation
key
Patch-mainline: Not yet, will send to linux-efi again
References: fate#316350, bsc#956284
There have some UEFI firmware checks the initial value of input
parameter when getting a EFI variable then emits EFI_INVALID_PARAMETER.
This patch fixed issue by assigning initial value of attributes and
size parameter.
In addition, this patch removes useless "Regenerating hibernation key"
message and prints fail message for get/set hibernation key.
Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
---
arch/x86/boot/compressed/eboot.c | 23 +++++++++++++++--------
arch/x86/boot/compressed/efi_random.c | 19 -------------------
include/linux/efi.h | 24 ++++++++++++++++++++++++
3 files changed, 39 insertions(+), 27 deletions(-)
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1139,8 +1139,8 @@ free_mem_map:
static void setup_hibernation_keys(struct boot_params *params)
{
unsigned long key_size;
- unsigned long attributes;
- unsigned long ignore;
+ unsigned long attributes = 0;
+ unsigned long buff_size;
struct setup_data *setup_data, *hibernation_setup_data;
struct hibernation_keys *keys;
bool regen_key = false;
@@ -1158,6 +1158,7 @@ static void setup_hibernation_keys(struc
memset(hibernation_setup_data, 0, size);
keys = (struct hibernation_keys *) hibernation_setup_data->data;
+ key_size = sizeof(keys->hibernation_key);
status = efi_call_early(get_variable, HIBERNATION_KEY,
&EFI_HIBERNATION_GUID, &attributes,
@@ -1173,15 +1174,18 @@ static void setup_hibernation_keys(struc
status = EFI_NOT_FOUND;
} else
goto clean_fail;
+ } else if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) {
+ efi_printk(sys_table, "Failed to get hibernation key: ");
+ efi_printk(sys_table, efi_status_to_str(status));
+ efi_printk(sys_table, "\n");
}
+ buff_size = sizeof(regen_key);
reg_status = efi_call_early(get_variable, HIBERNATION_KEY_REGEN_FLAG,
- &EFI_HIBERNATION_GUID, &attributes, &ignore,
- ®en_key);
+ &EFI_HIBERNATION_GUID, &attributes,
+ &buff_size, ®en_key);
if ((status != EFI_SUCCESS) ||
(reg_status == EFI_SUCCESS && regen_key)) {
- efi_printk(sys_table, "Regenerating hibernation key\n");
-
efi_get_random_key(sys_table, params, keys->hibernation_key,
HIBERNATION_DIGEST_SIZE);
@@ -1191,8 +1195,11 @@ static void setup_hibernation_keys(struc
HIBERNATION_KEY_ATTRIBUTE,
HIBERNATION_DIGEST_SIZE,
keys->hibernation_key);
- if (status != EFI_SUCCESS)
- efi_printk(sys_table, "Failed to set hibernation key\n");
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "Failed to set hibernation key: ");
+ efi_printk(sys_table, efi_status_to_str(status));
+ efi_printk(sys_table, "\n");
+ }
efi_call_early(get_variable, HIBERNATION_KEY,
&EFI_HIBERNATION_GUID,
--- a/arch/x86/boot/compressed/efi_random.c
+++ b/arch/x86/boot/compressed/efi_random.c
@@ -5,25 +5,6 @@
#include <asm/archrandom.h>
#include <asm/efi.h>
-#define EFI_STATUS_STR(_status) \
-case EFI_##_status: \
- return "EFI_" __stringify(_status);
-
-static char *efi_status_to_str(efi_status_t status)
-{
- switch (status) {
- EFI_STATUS_STR(SUCCESS)
- EFI_STATUS_STR(INVALID_PARAMETER)
- EFI_STATUS_STR(OUT_OF_RESOURCES)
- EFI_STATUS_STR(DEVICE_ERROR)
- EFI_STATUS_STR(WRITE_PROTECTED)
- EFI_STATUS_STR(SECURITY_VIOLATION)
- EFI_STATUS_STR(NOT_FOUND)
- }
-
- return "";
-}
-
static efi_status_t efi_locate_rng(efi_system_table_t *sys_table,
void ***rng_handle)
{
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -44,6 +44,30 @@ typedef u16 efi_char16_t; /* UNICODE ch
typedef u64 efi_physical_addr_t;
typedef void *efi_handle_t;
+#define EFI_STATUS_STR(_status) \
+case EFI_##_status: \
+ return "EFI_" __stringify(_status);
+
+static inline char *efi_status_to_str(efi_status_t status)
+{
+ switch (status) {
+ EFI_STATUS_STR(SUCCESS)
+ EFI_STATUS_STR(LOAD_ERROR)
+ EFI_STATUS_STR(INVALID_PARAMETER)
+ EFI_STATUS_STR(UNSUPPORTED)
+ EFI_STATUS_STR(BAD_BUFFER_SIZE)
+ EFI_STATUS_STR(BUFFER_TOO_SMALL)
+ EFI_STATUS_STR(NOT_READY)
+ EFI_STATUS_STR(DEVICE_ERROR)
+ EFI_STATUS_STR(WRITE_PROTECTED)
+ EFI_STATUS_STR(OUT_OF_RESOURCES)
+ EFI_STATUS_STR(NOT_FOUND)
+ EFI_STATUS_STR(SECURITY_VIOLATION)
+ }
+
+ return "";
+}
+
typedef struct {
u8 b[16];
} efi_guid_t;