Commit 2a457fb3 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Ingo Molnar

efi/capsule-loader: Use page addresses rather than struct page pointers

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: default avatarBryan O'Donoghue <pure.logic@nexus-software.ie>
Signed-off-by: default avatarArd 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.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 3fabd628
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
#define NO_FURTHER_WRITE_ACTION -1 #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 * efi_free_all_buff_pages - free all previous allocated buffer pages
* @cap_info: pointer to current instance of capsule_info structure * @cap_info: pointer to current instance of capsule_info structure
...@@ -31,7 +35,7 @@ ...@@ -31,7 +35,7 @@
static void efi_free_all_buff_pages(struct capsule_info *cap_info) static void efi_free_all_buff_pages(struct capsule_info *cap_info)
{ {
while (cap_info->index > 0) 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; cap_info->index = NO_FURTHER_WRITE_ACTION;
} }
...@@ -161,12 +165,12 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff, ...@@ -161,12 +165,12 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
goto failed; 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; 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 = kmap(page);
kbuff += PAGE_SIZE - cap_info->page_bytes_remain; kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
......
...@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule, ...@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
* *
* Return 0 on success, a converted EFI status code on failure. * 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; u32 imagesize = capsule->imagesize;
efi_guid_t guid = capsule->guid; efi_guid_t guid = capsule->guid;
...@@ -249,10 +249,11 @@ int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages) ...@@ -249,10 +249,11 @@ int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
sglist = kmap(sg_pages[i]); sglist = kmap(sg_pages[i]);
for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) { 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].length = sz;
sglist[j].data = page_to_phys(*pages++); sglist[j].data = *pages++;
imagesize -= sz; imagesize -= sz;
count--; count--;
......
...@@ -143,7 +143,7 @@ struct capsule_info { ...@@ -143,7 +143,7 @@ struct capsule_info {
long index; long index;
size_t count; size_t count;
size_t total_size; size_t total_size;
struct page **pages; phys_addr_t *pages;
size_t page_bytes_remain; size_t page_bytes_remain;
}; };
...@@ -1415,7 +1415,7 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 flags, ...@@ -1415,7 +1415,7 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 flags,
size_t size, int *reset); size_t size, int *reset);
extern int efi_capsule_update(efi_capsule_header_t *capsule, extern int efi_capsule_update(efi_capsule_header_t *capsule,
struct page **pages); phys_addr_t *pages);
#ifdef CONFIG_EFI_RUNTIME_MAP #ifdef CONFIG_EFI_RUNTIME_MAP
int efi_runtime_map_init(struct kobject *); int efi_runtime_map_init(struct kobject *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment