Blob Blame History Raw
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,
-				    &regen_key);
+				    &EFI_HIBERNATION_GUID, &attributes,
+				    &buff_size, &regen_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;