From: Greg Kroah-Hartman Date: Thu, 5 Jun 2014 00:31:49 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.14.6~22 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9aad733d6e1f2f5a071a912fee36fdd2266c7e5b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: efi-export-efi_query_variable_store-for-efivars.ko.patch efi_pstore-introducing-workqueue-updating-sysfs.patch efivars-add-module-parameter-to-disable-use-as-a-pstore-backend.patch efivars-fix-check-for-config_efi_vars_pstore_default_disable.patch modify-uefi-anti-bricking-code.patch x86-efi-check-max_size-only-if-it-is-non-zero.patch x86-efi-fix-dummy-variable-buffer-allocation.patch x86-efi-implement-efi_no_storage_paranoia-parameter.patch x86-efivars-firmware-bug-workarounds-should-be-in-platform-code.patch --- diff --git a/queue-3.4/efi-export-efi_query_variable_store-for-efivars.ko.patch b/queue-3.4/efi-export-efi_query_variable_store-for-efivars.ko.patch new file mode 100644 index 00000000000..f827a94a380 --- /dev/null +++ b/queue-3.4/efi-export-efi_query_variable_store-for-efivars.ko.patch @@ -0,0 +1,29 @@ +From c5ba30a73ebcca1b4068363ca08410fa3729ebeb Mon Sep 17 00:00:00 2001 +From: Sergey Vlasov +Date: Tue, 16 Apr 2013 18:31:09 +0400 +Subject: efi: Export efi_query_variable_store() for efivars.ko + +From: Sergey Vlasov + +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 +Signed-off-by: Matt Fleming +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.4/efi_pstore-introducing-workqueue-updating-sysfs.patch b/queue-3.4/efi_pstore-introducing-workqueue-updating-sysfs.patch new file mode 100644 index 00000000000..0754cc33b1c --- /dev/null +++ b/queue-3.4/efi_pstore-introducing-workqueue-updating-sysfs.patch @@ -0,0 +1,136 @@ +From a93bc0c6e07ed9bac44700280e65e2945d864fd4 Mon Sep 17 00:00:00 2001 +From: Seiji Aguchi +Date: Tue, 12 Feb 2013 13:04:41 -0800 +Subject: efi_pstore: Introducing workqueue updating sysfs + +From: Seiji Aguchi + +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 +Acked-by: Matt Fleming +Signed-off-by: Tony Luck +[xr: Backported to 3.4: + - Adjust contest + - Remove repeated definition of helper function variable_is_present] +Signed-off-by: Rui Xiang +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-3.4/efivars-add-module-parameter-to-disable-use-as-a-pstore-backend.patch b/queue-3.4/efivars-add-module-parameter-to-disable-use-as-a-pstore-backend.patch new file mode 100644 index 00000000000..a4f82459b88 --- /dev/null +++ b/queue-3.4/efivars-add-module-parameter-to-disable-use-as-a-pstore-backend.patch @@ -0,0 +1,79 @@ +From a1e16e8184d48763a7036a672e44998e4d3fe182 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 11 Mar 2013 16:17:50 -0500 +Subject: efivars: Add module parameter to disable use as a pstore backend + +From: Seth Forshee + +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 +Cc: Josh Boyer +Cc: Matthew Garrett +Cc: Seiji Aguchi +Cc: Tony Luck +Signed-off-by: Matt Fleming +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.4/efivars-fix-check-for-config_efi_vars_pstore_default_disable.patch b/queue-3.4/efivars-fix-check-for-config_efi_vars_pstore_default_disable.patch new file mode 100644 index 00000000000..4bdce594080 --- /dev/null +++ b/queue-3.4/efivars-fix-check-for-config_efi_vars_pstore_default_disable.patch @@ -0,0 +1,32 @@ +From f9c0efa2e87f6fb07738c097985eb04932ffca90 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Fri, 22 Mar 2013 19:56:51 +0000 +Subject: efivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE + +From: Ben Hutchings + +commit ca0ba26fbbd2d81c43085df49ce0abfe34535a90 upstream. + +The 'CONFIG_' prefix is not implicit in IS_ENABLED(). + +Signed-off-by: Ben Hutchings +Cc: Seth Forshee +Signed-off-by: Matt Fleming +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-3.4/modify-uefi-anti-bricking-code.patch b/queue-3.4/modify-uefi-anti-bricking-code.patch new file mode 100644 index 00000000000..735a75f24c8 --- /dev/null +++ b/queue-3.4/modify-uefi-anti-bricking-code.patch @@ -0,0 +1,153 @@ +From 134c3faa909c12ae1b9c3a37a5e733b1f6c3dfab Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sat, 1 Jun 2013 16:06:20 -0400 +Subject: Modify UEFI anti-bricking code + +From: Matthew Garrett + +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 +Signed-off-by: Lee, Chun-Y [ dummy variable cleanup ] +Signed-off-by: Matt Fleming +[bwh: Backported to 3.2: the reverted changes were never applied here] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-3.4/series b/queue-3.4/series index b604498b4c2..be3ce7f4617 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -144,3 +144,12 @@ efivars-disable-external-interrupt-while-holding-efivars-lock.patch 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 diff --git a/queue-3.4/x86-efi-check-max_size-only-if-it-is-non-zero.patch b/queue-3.4/x86-efi-check-max_size-only-if-it-is-non-zero.patch new file mode 100644 index 00000000000..60974ae41c2 --- /dev/null +++ b/queue-3.4/x86-efi-check-max_size-only-if-it-is-non-zero.patch @@ -0,0 +1,39 @@ +From b12bcd7b3fe04a5fcca945aaf5b74181d9a223f4 Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Wed, 10 Apr 2013 10:59:34 +0200 +Subject: x86,efi: Check max_size only if it is non-zero. + +From: Richard Weinberger + +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 +Signed-off-by: Matt Fleming +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-3.4/x86-efi-fix-dummy-variable-buffer-allocation.patch b/queue-3.4/x86-efi-fix-dummy-variable-buffer-allocation.patch new file mode 100644 index 00000000000..32d70010ca3 --- /dev/null +++ b/queue-3.4/x86-efi-fix-dummy-variable-buffer-allocation.patch @@ -0,0 +1,49 @@ +From b35b16d2be61943373f16ceb6184a66da84ab229 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 16 Jun 2013 21:27:12 +0100 +Subject: x86/efi: Fix dummy variable buffer allocation + +From: Ben Hutchings + +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 +Signed-off-by: Matt Fleming +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-3.4/x86-efi-implement-efi_no_storage_paranoia-parameter.patch b/queue-3.4/x86-efi-implement-efi_no_storage_paranoia-parameter.patch new file mode 100644 index 00000000000..63466e6cd9c --- /dev/null +++ b/queue-3.4/x86-efi-implement-efi_no_storage_paranoia-parameter.patch @@ -0,0 +1,73 @@ +From 2a068400fcef7b1563d60f294b584b728236307f Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Wed, 17 Apr 2013 01:00:53 +0200 +Subject: x86,efi: Implement efi_no_storage_paranoia parameter + +From: Richard Weinberger + +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 +Signed-off-by: Matt Fleming +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-3.4/x86-efivars-firmware-bug-workarounds-should-be-in-platform-code.patch b/queue-3.4/x86-efivars-firmware-bug-workarounds-should-be-in-platform-code.patch new file mode 100644 index 00000000000..aa14771ab23 --- /dev/null +++ b/queue-3.4/x86-efivars-firmware-bug-workarounds-should-be-in-platform-code.patch @@ -0,0 +1,131 @@ +From a6e4d5a03e9e3587e88aba687d8f225f4f04c792 Mon Sep 17 00:00:00 2001 +From: Matt Fleming +Date: Mon, 25 Mar 2013 09:14:30 +0000 +Subject: x86, efivars: firmware bug workarounds should be in platform code + +From: Matt Fleming + +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 +Cc: Matthew Garrett +Signed-off-by: Matt Fleming +[xr: Backported to 3.4: adjust context] +Signed-off-by: Rui Xiang +Signed-off-by: Greg Kroah-Hartman +--- + 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 {