]> git.baikalelectronics.ru Git - kernel.git/commitdiff
efi/capsule-loader: Use page addresses rather than struct page pointers
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 2 Jun 2017 13:52:03 +0000 (13:52 +0000)
committerIngo Molnar <mingo@kernel.org>
Mon, 5 Jun 2017 15:50:41 +0000 (17:50 +0200)
To give some leeway to code that handles non-standard capsule headers,
let's keep an array of page addresses rather than struct page pointers.

This gives special implementations of efi_capsule_setup_info() the
opportunity to mangle the payload a bit before it is presented to the
firmware, without putting any knowledge of the nature of such quirks
into the generic code.

Tested-by: Bryan O'Donoghue <pure.logic@nexus-software.ie>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20170602135207.21708-10-ard.biesheuvel@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
drivers/firmware/efi/capsule-loader.c
drivers/firmware/efi/capsule.c
include/linux/efi.h

index cbc3526953d5b665e4dbda5fb1f72c6e0efd8060..ec8ac5c4dd84f93e386db9871946c81ea1dbc8d5 100644 (file)
 
 #define NO_FURTHER_WRITE_ACTION -1
 
+#ifndef phys_to_page
+#define phys_to_page(x)                pfn_to_page((x) >> PAGE_SHIFT)
+#endif
+
 /**
  * efi_free_all_buff_pages - free all previous allocated buffer pages
  * @cap_info: pointer to current instance of capsule_info structure
@@ -31,7 +35,7 @@
 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
 {
        while (cap_info->index > 0)
-               __free_page(cap_info->pages[--cap_info->index]);
+               __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
 
        cap_info->index = NO_FURTHER_WRITE_ACTION;
 }
@@ -161,12 +165,12 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
                        goto failed;
                }
 
-               cap_info->pages[cap_info->index++] = page;
+               cap_info->pages[cap_info->index++] = page_to_phys(page);
                cap_info->page_bytes_remain = PAGE_SIZE;
+       } else {
+               page = phys_to_page(cap_info->pages[cap_info->index - 1]);
        }
 
-       page = cap_info->pages[cap_info->index - 1];
-
        kbuff = kmap(page);
        kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
 
index e603ccf39d800a7d6e741c9eac84ab1d1129aa64..901b9306bf94a1195e35ccc2d869467327009e7d 100644 (file)
@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
  *
  * Return 0 on success, a converted EFI status code on failure.
  */
-int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
+int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
 {
        u32 imagesize = capsule->imagesize;
        efi_guid_t guid = capsule->guid;
@@ -249,10 +249,11 @@ int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
                sglist = kmap(sg_pages[i]);
 
                for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
-                       u64 sz = min_t(u64, imagesize, PAGE_SIZE);
+                       u64 sz = min_t(u64, imagesize,
+                                      PAGE_SIZE - (u64)*pages % PAGE_SIZE);
 
                        sglist[j].length = sz;
-                       sglist[j].data = page_to_phys(*pages++);
+                       sglist[j].data = *pages++;
 
                        imagesize -= sz;
                        count--;
index a7379a2b5680bbb509911841c032b99c6e0d2504..8269bcb8ccf7961bd01f52e39fc4d34d370f25d3 100644 (file)
@@ -143,7 +143,7 @@ struct capsule_info {
        long                    index;
        size_t                  count;
        size_t                  total_size;
-       struct page             **pages;
+       phys_addr_t             *pages;
        size_t                  page_bytes_remain;
 };
 
@@ -1415,7 +1415,7 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 flags,
                                 size_t size, int *reset);
 
 extern int efi_capsule_update(efi_capsule_header_t *capsule,
-                             struct page **pages);
+                             phys_addr_t *pages);
 
 #ifdef CONFIG_EFI_RUNTIME_MAP
 int efi_runtime_map_init(struct kobject *);