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: 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>
This commit is contained in:
parent
3fabd628d5
commit
2a457fb31d
@ -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 @@
|
|||||||
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,
|
|||||||
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,
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 {
|
|||||||
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,
|
|||||||
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 *);
|
||||||
|
Loading…
Reference in New Issue
Block a user