--- /dev/null
+From c5ba30a73ebcca1b4068363ca08410fa3729ebeb Mon Sep 17 00:00:00 2001
+From: Sergey Vlasov <vsu@altlinux.ru>
+Date: Tue, 16 Apr 2013 18:31:09 +0400
+Subject: efi: Export efi_query_variable_store() for efivars.ko
+
+From: Sergey Vlasov <vsu@altlinux.ru>
+
+commit 3668011d4ad556224f7c012c1e870a6eaa0e59da upstream.
+
+Fixes build with CONFIG_EFI_VARS=m which was broken after the commit
+"x86, efivars: firmware bug workarounds should be in platform code".
+
+Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/platform/efi/efi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -990,3 +990,4 @@ efi_status_t efi_query_variable_store(u3
+
+ return EFI_SUCCESS;
+ }
++EXPORT_SYMBOL_GPL(efi_query_variable_store);
--- /dev/null
+From a93bc0c6e07ed9bac44700280e65e2945d864fd4 Mon Sep 17 00:00:00 2001
+From: Seiji Aguchi <seiji.aguchi@hds.com>
+Date: Tue, 12 Feb 2013 13:04:41 -0800
+Subject: efi_pstore: Introducing workqueue updating sysfs
+
+From: Seiji Aguchi <seiji.aguchi@hds.com>
+
+commit a93bc0c6e07ed9bac44700280e65e2945d864fd4 upstream.
+
+[Problem]
+efi_pstore creates sysfs entries, which enable users to access to NVRAM,
+in a write callback. If a kernel panic happens in an interrupt context,
+it may fail because it could sleep due to dynamic memory allocations during
+creating sysfs entries.
+
+[Patch Description]
+This patch removes sysfs operations from a write callback by introducing
+a workqueue updating sysfs entries which is scheduled after the write
+callback is called.
+
+Also, the workqueue is kicked in a just oops case.
+A system will go down in other cases such as panic, clean shutdown and emergency
+restart. And we don't need to create sysfs entries because there is no chance for
+users to access to them.
+
+efi_pstore will be robust against a kernel panic in an interrupt context with this patch.
+
+Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
+Acked-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+[xr: Backported to 3.4:
+ - Adjust contest
+ - Remove repeated definition of helper function variable_is_present]
+Signed-off-by: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/firmware/efivars.c | 61 +++++++++++++++++++++++++++++++++++++++++----
+ include/linux/efi.h | 3 +-
+ 2 files changed, 58 insertions(+), 6 deletions(-)
+
+--- a/drivers/firmware/efivars.c
++++ b/drivers/firmware/efivars.c
+@@ -154,6 +154,13 @@ efivar_create_sysfs_entry(struct efivars
+ efi_char16_t *variable_name,
+ efi_guid_t *vendor_guid);
+
++/*
++ * Prototype for workqueue functions updating sysfs entry
++ */
++
++static void efivar_update_sysfs_entries(struct work_struct *);
++static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
++
+ /* Return the number of unicode characters in data */
+ static unsigned long
+ utf16_strnlen(efi_char16_t *s, size_t maxlength)
+@@ -839,11 +846,8 @@ static int efi_pstore_write(enum pstore_
+ if (found)
+ efivar_unregister(found);
+
+- if (size)
+- ret = efivar_create_sysfs_entry(efivars,
+- utf16_strsize(efi_name,
+- DUMP_NAME_LEN * 2),
+- efi_name, &vendor);
++ if (reason == KMSG_DUMP_OOPS)
++ schedule_work(&efivar_work);
+
+ *id = part;
+ return ret;
+@@ -1044,6 +1048,53 @@ static bool variable_is_present(efi_char
+ return found;
+ }
+
++static void efivar_update_sysfs_entries(struct work_struct *work)
++{
++ struct efivars *efivars = &__efivars;
++ efi_guid_t vendor;
++ efi_char16_t *variable_name;
++ unsigned long variable_name_size = 1024;
++ efi_status_t status = EFI_NOT_FOUND;
++ bool found;
++
++ /* Add new sysfs entries */
++ while (1) {
++ variable_name = kzalloc(variable_name_size, GFP_KERNEL);
++ if (!variable_name) {
++ pr_err("efivars: Memory allocation failed.\n");
++ return;
++ }
++
++ spin_lock_irq(&efivars->lock);
++ found = false;
++ while (1) {
++ variable_name_size = 1024;
++ status = efivars->ops->get_next_variable(
++ &variable_name_size,
++ variable_name,
++ &vendor);
++ if (status != EFI_SUCCESS) {
++ break;
++ } else {
++ if (!variable_is_present(variable_name,
++ &vendor)) {
++ found = true;
++ break;
++ }
++ }
++ }
++ spin_unlock_irq(&efivars->lock);
++
++ if (!found) {
++ kfree(variable_name);
++ break;
++ } else
++ efivar_create_sysfs_entry(efivars,
++ variable_name_size,
++ variable_name, &vendor);
++ }
++}
++
+ /*
+ * Returns the size of variable_name, in bytes, including the
+ * terminating NULL character, or variable_name_size if no NULL
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -666,7 +666,8 @@ struct efivars {
+ * 1) ->list - adds, removals, reads, writes
+ * 2) ops.[gs]et_variable() calls.
+ * It must not be held when creating sysfs entries or calling kmalloc.
+- * ops.get_next_variable() is only called from register_efivars(),
++ * ops.get_next_variable() is only called from register_efivars()
++ * or efivar_update_sysfs_entries(),
+ * which is protected by the BKL, so that path is safe.
+ */
+ spinlock_t lock;
--- /dev/null
+From a1e16e8184d48763a7036a672e44998e4d3fe182 Mon Sep 17 00:00:00 2001
+From: Seth Forshee <seth.forshee@canonical.com>
+Date: Mon, 11 Mar 2013 16:17:50 -0500
+Subject: efivars: Add module parameter to disable use as a pstore backend
+
+From: Seth Forshee <seth.forshee@canonical.com>
+
+commit ec0971ba5372a4dfa753f232449d23a8fd98490e upstream.
+
+We know that with some firmware implementations writing too much data to
+UEFI variables can lead to bricking machines. Recent changes attempt to
+address this issue, but for some it may still be prudent to avoid
+writing large amounts of data until the solution has been proven on a
+wide variety of hardware.
+
+Crash dumps or other data from pstore can potentially be a large data
+source. Add a pstore_module parameter to efivars to allow disabling its
+use as a backend for pstore. Also add a config option,
+CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE, to allow setting the default
+value of this paramter to true (i.e. disabled by default).
+
+Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
+Cc: Josh Boyer <jwboyer@redhat.com>
+Cc: Matthew Garrett <mjg59@srcf.ucam.org>
+Cc: Seiji Aguchi <seiji.aguchi@hds.com>
+Cc: Tony Luck <tony.luck@intel.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firmware/Kconfig | 9 +++++++++
+ drivers/firmware/efivars.c | 8 +++++++-
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -62,6 +62,15 @@ config EFI_VARS_PSTORE
+ will allow writing console messages, crash dumps, or anything
+ else supported by pstore to EFI variables.
+
++config EFI_VARS_PSTORE_DEFAULT_DISABLE
++ bool "Disable using efivars as a pstore backend by default"
++ depends on EFI_VARS_PSTORE
++ default n
++ help
++ Saying Y here will disable the use of efivars as a storage
++ backend for pstore by default. This setting can be overridden
++ using the efivars module's pstore_disable parameter.
++
+ config EFI_PCDP
+ bool "Console device selection via EFI PCDP or HCDP table"
+ depends on ACPI && EFI && IA64
+--- a/drivers/firmware/efivars.c
++++ b/drivers/firmware/efivars.c
+@@ -92,6 +92,11 @@ MODULE_VERSION(EFIVARS_VERSION);
+
+ #define DUMP_NAME_LEN 52
+
++static bool efivars_pstore_disable =
++ IS_ENABLED(EFI_VARS_PSTORE_DEFAULT_DISABLE);
++
++module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
++
+ /*
+ * The maximum size of VariableName + Data = 1024
+ * Therefore, it's reasonable to save that much
+@@ -1350,7 +1355,8 @@ int register_efivars(struct efivars *efi
+ if (error)
+ unregister_efivars(efivars);
+
+- efivar_pstore_register(efivars);
++ if (!efivars_pstore_disable)
++ efivar_pstore_register(efivars);
+
+ out:
+ kfree(variable_name);
--- /dev/null
+From f9c0efa2e87f6fb07738c097985eb04932ffca90 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 22 Mar 2013 19:56:51 +0000
+Subject: efivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit ca0ba26fbbd2d81c43085df49ce0abfe34535a90 upstream.
+
+The 'CONFIG_' prefix is not implicit in IS_ENABLED().
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Seth Forshee <seth.forshee@canonical.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firmware/efivars.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/firmware/efivars.c
++++ b/drivers/firmware/efivars.c
+@@ -93,7 +93,7 @@ MODULE_VERSION(EFIVARS_VERSION);
+ #define DUMP_NAME_LEN 52
+
+ static bool efivars_pstore_disable =
+- IS_ENABLED(EFI_VARS_PSTORE_DEFAULT_DISABLE);
++ IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
+
+ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
+
--- /dev/null
+From 134c3faa909c12ae1b9c3a37a5e733b1f6c3dfab Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <matthew.garrett@nebula.com>
+Date: Sat, 1 Jun 2013 16:06:20 -0400
+Subject: Modify UEFI anti-bricking code
+
+From: Matthew Garrett <matthew.garrett@nebula.com>
+
+commit f8b8404337de4e2466e2e1139ea68b1f8295974f upstream.
+
+This patch reworks the UEFI anti-bricking code, including an effective
+reversion of cc5a080c and 31ff2f20. It turns out that calling
+QueryVariableInfo() from boot services results in some firmware
+implementations jumping to physical addresses even after entering virtual
+mode, so until we have 1:1 mappings for UEFI runtime space this isn't
+going to work so well.
+
+Reverting these gets us back to the situation where we'd refuse to create
+variables on some systems because they classify deleted variables as "used"
+until the firmware triggers a garbage collection run, which they won't do
+until they reach a lower threshold. This results in it being impossible to
+install a bootloader, which is unhelpful.
+
+Feedback from Samsung indicates that the firmware doesn't need more than
+5KB of storage space for its own purposes, so that seems like a reasonable
+threshold. However, there's still no guarantee that a platform will attempt
+garbage collection merely because it drops below this threshold. It seems
+that this is often only triggered if an attempt to write generates a
+genuine EFI_OUT_OF_RESOURCES error. We can force that by attempting to
+create a variable larger than the remaining space. This should fail, but if
+it somehow succeeds we can then immediately delete it.
+
+I've tested this on the UEFI machines I have available, but I don't have
+a Samsung and so can't verify that it avoids the bricking problem.
+
+Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
+Signed-off-by: Lee, Chun-Y <jlee@suse.com> [ dummy variable cleanup ]
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+[bwh: Backported to 3.2: the reverted changes were never applied here]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/platform/efi/efi.c | 79 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 68 insertions(+), 11 deletions(-)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -50,6 +50,13 @@
+
+ #define EFI_DEBUG 1
+
++#define EFI_MIN_RESERVE 5120
++
++#define EFI_DUMMY_GUID \
++ EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
++
++static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
++
+ struct efi __read_mostly efi = {
+ .mps = EFI_INVALID_TABLE_ADDR,
+ .acpi = EFI_INVALID_TABLE_ADDR,
+@@ -932,6 +939,13 @@ void __init efi_enter_virtual_mode(void)
+ runtime_code_page_mkexec();
+
+ kfree(new_memmap);
++
++ /* clean DUMMY object */
++ efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
++ EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS |
++ EFI_VARIABLE_RUNTIME_ACCESS,
++ 0, NULL);
+ }
+
+ /*
+@@ -983,22 +997,65 @@ efi_status_t efi_query_variable_store(u3
+ efi_status_t status;
+ u64 storage_size, remaining_size, max_size;
+
++ if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
++ return 0;
++
+ status = efi.query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+ if (status != EFI_SUCCESS)
+ return status;
+
+- if (!max_size && remaining_size > size)
+- printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
+- " is returning MaxVariableSize=0\n");
+-
+- if (!storage_size || size > remaining_size ||
+- (max_size && size > max_size))
+- return EFI_OUT_OF_RESOURCES;
+-
+- if (!efi_no_storage_paranoia &&
+- (remaining_size - size) < (storage_size / 2))
+- return EFI_OUT_OF_RESOURCES;
++ /*
++ * Some firmware implementations refuse to boot if there's insufficient
++ * space in the variable store. We account for that by refusing the
++ * write if permitting it would reduce the available space to under
++ * 5KB. This figure was provided by Samsung, so should be safe.
++ */
++ if ((remaining_size - size < EFI_MIN_RESERVE) &&
++ !efi_no_storage_paranoia) {
++
++ /*
++ * Triggering garbage collection may require that the firmware
++ * generate a real EFI_OUT_OF_RESOURCES error. We can force
++ * that by attempting to use more space than is available.
++ */
++ unsigned long dummy_size = remaining_size + 1024;
++ void *dummy = kmalloc(dummy_size, GFP_ATOMIC);
++
++ status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
++ EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS |
++ EFI_VARIABLE_RUNTIME_ACCESS,
++ dummy_size, dummy);
++
++ if (status == EFI_SUCCESS) {
++ /*
++ * This should have failed, so if it didn't make sure
++ * that we delete it...
++ */
++ efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
++ EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS |
++ EFI_VARIABLE_RUNTIME_ACCESS,
++ 0, dummy);
++ }
++
++ /*
++ * The runtime code may now have triggered a garbage collection
++ * run, so check the variable info again
++ */
++ status = efi.query_variable_info(attributes, &storage_size,
++ &remaining_size, &max_size);
++
++ if (status != EFI_SUCCESS)
++ return status;
++
++ /*
++ * There still isn't enough room, so return an error
++ */
++ if (remaining_size - size < EFI_MIN_RESERVE)
++ return EFI_OUT_OF_RESOURCES;
++ }
+
+ return EFI_SUCCESS;
+ }
efi-be-more-paranoid-about-available-space-when-creating-variables.patch
efivars-pstore-do-not-check-size-when-erasing-variable.patch
efivars-allow-disabling-use-as-a-pstore-backend.patch
+efivars-add-module-parameter-to-disable-use-as-a-pstore-backend.patch
+efivars-fix-check-for-config_efi_vars_pstore_default_disable.patch
+efi_pstore-introducing-workqueue-updating-sysfs.patch
+x86-efivars-firmware-bug-workarounds-should-be-in-platform-code.patch
+x86-efi-check-max_size-only-if-it-is-non-zero.patch
+efi-export-efi_query_variable_store-for-efivars.ko.patch
+x86-efi-implement-efi_no_storage_paranoia-parameter.patch
+modify-uefi-anti-bricking-code.patch
+x86-efi-fix-dummy-variable-buffer-allocation.patch
--- /dev/null
+From b12bcd7b3fe04a5fcca945aaf5b74181d9a223f4 Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Wed, 10 Apr 2013 10:59:34 +0200
+Subject: x86,efi: Check max_size only if it is non-zero.
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 7791c8423f1f7f4dad94e753bae67461d5b80be8 upstream.
+
+Some EFI implementations return always a MaximumVariableSize of 0,
+check against max_size only if it is non-zero.
+My Intel DQ67SW desktop board has such an implementation.
+
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/platform/efi/efi.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -979,7 +979,12 @@ efi_status_t efi_query_variable_store(u3
+ if (status != EFI_SUCCESS)
+ return status;
+
+- if (!storage_size || size > remaining_size || size > max_size ||
++ if (!max_size && remaining_size > size)
++ printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
++ " is returning MaxVariableSize=0\n");
++
++ if (!storage_size || size > remaining_size ||
++ (max_size && size > max_size) ||
+ (remaining_size - size) < (storage_size / 2))
+ return EFI_OUT_OF_RESOURCES;
+
--- /dev/null
+From b35b16d2be61943373f16ceb6184a66da84ab229 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 16 Jun 2013 21:27:12 +0100
+Subject: x86/efi: Fix dummy variable buffer allocation
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit b8cb62f82103083a6e8fa5470bfe634a2c06514d upstream.
+
+1. Check for allocation failure
+2. Clear the buffer contents, as they may actually be written to flash
+3. Don't leak the buffer
+
+Compile-tested only.
+
+[ Tested successfully on my buggy ASUS machine - Matt ]
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/platform/efi/efi.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -1020,7 +1020,10 @@ efi_status_t efi_query_variable_store(u3
+ * that by attempting to use more space than is available.
+ */
+ unsigned long dummy_size = remaining_size + 1024;
+- void *dummy = kmalloc(dummy_size, GFP_ATOMIC);
++ void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
++
++ if (!dummy)
++ return EFI_OUT_OF_RESOURCES;
+
+ status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+ EFI_VARIABLE_NON_VOLATILE |
+@@ -1040,6 +1043,8 @@ efi_status_t efi_query_variable_store(u3
+ 0, dummy);
+ }
+
++ kfree(dummy);
++
+ /*
+ * The runtime code may now have triggered a garbage collection
+ * run, so check the variable info again
--- /dev/null
+From 2a068400fcef7b1563d60f294b584b728236307f Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Wed, 17 Apr 2013 01:00:53 +0200
+Subject: x86,efi: Implement efi_no_storage_paranoia parameter
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 8c58bf3eec3b8fc8162fe557e9361891c20758f2 upstream.
+
+Using this parameter one can disable the storage_size/2 check if
+he is really sure that the UEFI does sane gc and fulfills the spec.
+
+This parameter is useful if a devices uses more than 50% of the
+storage by default.
+The Intel DQSW67 desktop board is such a sucker for exmaple.
+
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/kernel-parameters.txt | 6 ++++++
+ arch/x86/platform/efi/efi.c | 14 +++++++++++++-
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -773,6 +773,12 @@ bytes respectively. Such letter suffixes
+ edd= [EDD]
+ Format: {"off" | "on" | "skip[mbr]"}
+
++ efi_no_storage_paranoia [EFI; X86]
++ Using this parameter you can use more than 50% of
++ your efi variable storage. Use this parameter only if
++ you are really sure that your UEFI does sane gc and
++ fulfills the spec otherwise your board may brick.
++
+ eisa_irq_edge= [PARISC,HW]
+ See header of drivers/parisc/eisa.c.
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -102,6 +102,15 @@ static int __init setup_add_efi_memmap(c
+ }
+ early_param("add_efi_memmap", setup_add_efi_memmap);
+
++static bool efi_no_storage_paranoia;
++
++static int __init setup_storage_paranoia(char *arg)
++{
++ efi_no_storage_paranoia = true;
++ return 0;
++}
++early_param("efi_no_storage_paranoia", setup_storage_paranoia);
++
+
+ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+ {
+@@ -984,7 +993,10 @@ efi_status_t efi_query_variable_store(u3
+ " is returning MaxVariableSize=0\n");
+
+ if (!storage_size || size > remaining_size ||
+- (max_size && size > max_size) ||
++ (max_size && size > max_size))
++ return EFI_OUT_OF_RESOURCES;
++
++ if (!efi_no_storage_paranoia &&
+ (remaining_size - size) < (storage_size / 2))
+ return EFI_OUT_OF_RESOURCES;
+
--- /dev/null
+From a6e4d5a03e9e3587e88aba687d8f225f4f04c792 Mon Sep 17 00:00:00 2001
+From: Matt Fleming <matt.fleming@intel.com>
+Date: Mon, 25 Mar 2013 09:14:30 +0000
+Subject: x86, efivars: firmware bug workarounds should be in platform code
+
+From: Matt Fleming <matt.fleming@intel.com>
+
+commit a6e4d5a03e9e3587e88aba687d8f225f4f04c792 upstream.
+
+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>
+[xr: Backported to 3.4: adjust context]
+Signed-off-by: Rui Xiang <rui.xiang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/platform/efi/efi.c | 25 +++++++++++++++++++++++++
+ drivers/firmware/efivars.c | 18 +++---------------
+ include/linux/efi.h | 9 ++++++++-
+ 3 files changed, 36 insertions(+), 16 deletions(-)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -960,3 +960,28 @@ u64 efi_mem_attributes(unsigned long phy
+ }
+ 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;
++}
+--- a/drivers/firmware/efivars.c
++++ b/drivers/firmware/efivars.c
+@@ -425,24 +425,12 @@ static efi_status_t
+ check_var_size_locked(struct efivars *efivars, u32 attributes,
+ unsigned long size)
+ {
+- u64 storage_size, remaining_size, max_size;
+- efi_status_t status;
+ const struct efivar_operations *fops = efivars->ops;
+
+- if (!efivars->ops->query_variable_info)
++ if (!efivars->ops->query_variable_store)
+ return EFI_UNSUPPORTED;
+
+- status = fops->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 status;
++ return fops->query_variable_store(attributes, size);
+ }
+
+ static ssize_t
+@@ -1445,7 +1433,7 @@ efivars_init(void)
+ ops.get_variable = efi.get_variable;
+ ops.set_variable = efi.set_variable;
+ ops.get_next_variable = efi.get_next_variable;
+- ops.query_variable_info = efi.query_variable_info;
++ ops.query_variable_store = efi_query_variable_store;
+ error = register_efivars(&__efivars, &ops, efi_kobj);
+ if (error)
+ goto err_put;
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -262,6 +262,7 @@ typedef efi_status_t efi_query_capsule_c
+ unsigned long count,
+ u64 *max_size,
+ int *reset_type);
++typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size);
+
+ /*
+ * EFI Configuration Table and GUID definitions
+@@ -503,8 +504,14 @@ extern void efi_gettimeofday (struct tim
+ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
+ #ifdef CONFIG_X86
+ extern void efi_free_boot_services(void);
++extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
+ #else
+ static inline void efi_free_boot_services(void) {}
++
++static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
++{
++ return EFI_SUCCESS;
++}
+ #endif
+ extern u64 efi_get_iobase (void);
+ extern u32 efi_mem_type (unsigned long phys_addr);
+@@ -657,7 +664,7 @@ struct efivar_operations {
+ efi_get_variable_t *get_variable;
+ efi_get_next_variable_t *get_next_variable;
+ efi_set_variable_t *set_variable;
+- efi_query_variable_info_t *query_variable_info;
++ efi_query_variable_store_t *query_variable_store;
+ };
+
+ struct efivars {