Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / arch / x86 / platform / efi / quirks.c
index ed30e79347e86377198009dcafb1c0b26a9865df..ab50ada1d56e4f87f6fff3207995ea32312fb37b 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) "efi: " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -54,6 +56,33 @@ void efi_delete_dummy_variable(void)
                         0, NULL);
 }
 
+/*
+ * In the nonblocking case we do not attempt to perform garbage
+ * collection if we do not have enough free space. Rather, we do the
+ * bare minimum check and give up immediately if the available space
+ * is below EFI_MIN_RESERVE.
+ *
+ * This function is intended to be small and simple because it is
+ * invoked from crash handler paths.
+ */
+static efi_status_t
+query_variable_store_nonblocking(u32 attributes, unsigned long size)
+{
+       efi_status_t status;
+       u64 storage_size, remaining_size, max_size;
+
+       status = efi.query_variable_info_nonblocking(attributes, &storage_size,
+                                                    &remaining_size,
+                                                    &max_size);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       if (remaining_size - size < EFI_MIN_RESERVE)
+               return EFI_OUT_OF_RESOURCES;
+
+       return EFI_SUCCESS;
+}
+
 /*
  * Some firmware implementations refuse to boot if there's insufficient space
  * in the variable store. Ensure that we never use more than a safe limit.
@@ -61,7 +90,8 @@ void efi_delete_dummy_variable(void)
  * 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 efi_query_variable_store(u32 attributes, unsigned long size,
+                                     bool nonblocking)
 {
        efi_status_t status;
        u64 storage_size, remaining_size, max_size;
@@ -69,6 +99,9 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
        if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
                return 0;
 
+       if (nonblocking)
+               return query_variable_store_nonblocking(attributes, size);
+
        status = efi.query_variable_info(attributes, &storage_size,
                                         &remaining_size, &max_size);
        if (status != EFI_SUCCESS)
@@ -312,7 +345,7 @@ void __init efi_apply_memmap_quirks(void)
         * services.
         */
        if (!efi_runtime_supported()) {
-               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               pr_info("Setup done, disabling due to 32/64-bit mismatch\n");
                efi_unmap_memmap();
        }