summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2013-03-25 10:14:30 +0100
committerMatt Fleming <matt.fleming@intel.com>2013-04-09 12:34:05 +0200
commita6e4d5a03e9e3587e88aba687d8f225f4f04c792 (patch)
tree5159dd594f8c70ef964ec0fef74a6e8482f2606e /arch
parentefivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE (diff)
downloadlinux-a6e4d5a03e9e3587e88aba687d8f225f4f04c792.tar.xz
linux-a6e4d5a03e9e3587e88aba687d8f225f4f04c792.zip
x86, efivars: firmware bug workarounds should be in platform code
Let's not burden ia64 with checks in the common efivars code that we're not writing too much data to the variable store. That kind of thing is an x86 firmware bug, plain and simple. efi_query_variable_store() provides platforms with a wrapper in which they can perform checks and workarounds for EFI variable storage bugs. Cc: H. Peter Anvin <hpa@zytor.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/platform/efi/efi.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf3f9d8..c89c245eff40 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -999,3 +999,28 @@ u64 efi_mem_attributes(unsigned long phys_addr)
}
return 0;
}
+
+/*
+ * Some firmware has serious problems when using more than 50% of the EFI
+ * variable store, i.e. it triggers bugs that can brick machines. Ensure that
+ * we never use more than this safe limit.
+ *
+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
+ * store.
+ */
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+ efi_status_t status;
+ u64 storage_size, remaining_size, max_size;
+
+ status = efi.query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ if (!storage_size || size > remaining_size || size > max_size ||
+ (remaining_size - size) < (storage_size / 2))
+ return EFI_OUT_OF_RESOURCES;
+
+ return EFI_SUCCESS;
+}