Skip to content

Commit

Permalink
efi/capsule-loader: Use a cached copy of the capsule header
Browse files Browse the repository at this point in the history
Instead of kmapping the capsule data twice, copy the capsule header
into the capsule info struct we keep locally. This is an improvement
by itself, but will also enable handling of non-standard header formats
more easily.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
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-7-ard.biesheuvel@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ard Biesheuvel authored and Ingo Molnar committed Jun 5, 2017
1 parent 41b0c37 commit 82c3768
Showing 1 changed file with 17 additions and 24 deletions.
41 changes: 17 additions & 24 deletions drivers/firmware/efi/capsule-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
#define NO_FURTHER_WRITE_ACTION -1

struct capsule_info {
bool header_obtained;
int reset_type;
long index;
size_t count;
size_t total_size;
struct page **pages;
size_t page_bytes_remain;
efi_capsule_header_t header;
int reset_type;
long index;
size_t count;
size_t total_size;
struct page **pages;
size_t page_bytes_remain;
};

/**
Expand Down Expand Up @@ -56,7 +56,6 @@ static void efi_free_all_buff_pages(struct capsule_info *cap_info)
static int efi_capsule_setup_info(struct capsule_info *cap_info,
void *kbuff, size_t hdr_bytes)
{
efi_capsule_header_t *cap_hdr;
size_t pages_needed;
int ret;
void *temp_page;
Expand All @@ -66,32 +65,33 @@ static int efi_capsule_setup_info(struct capsule_info *cap_info,
return 0;

/* Reset back to the correct offset of header */
cap_hdr = kbuff - cap_info->count;
pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
kbuff -= cap_info->count;
memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));
pages_needed = ALIGN(cap_info->header.imagesize, PAGE_SIZE) / PAGE_SIZE;

if (pages_needed == 0) {
pr_err("invalid capsule size");
return -EINVAL;
}

/* Check if the capsule binary supported */
ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
cap_hdr->imagesize,
ret = efi_capsule_supported(cap_info->header.guid,
cap_info->header.flags,
cap_info->header.imagesize,
&cap_info->reset_type);
if (ret) {
pr_err("capsule not supported\n");
return ret;
}

cap_info->total_size = cap_hdr->imagesize;
cap_info->total_size = cap_info->header.imagesize;
temp_page = krealloc(cap_info->pages,
pages_needed * sizeof(void *),
GFP_KERNEL | __GFP_ZERO);
if (!temp_page)
return -ENOMEM;

cap_info->pages = temp_page;
cap_info->header_obtained = true;

return 0;
}
Expand All @@ -104,15 +104,8 @@ static int efi_capsule_setup_info(struct capsule_info *cap_info,
static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
{
int ret;
void *cap_hdr_temp;

cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
VM_MAP, PAGE_KERNEL);
if (!cap_hdr_temp)
return -ENOMEM;

ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
vunmap(cap_hdr_temp);
ret = efi_capsule_update(&cap_info->header, cap_info->pages);
if (ret) {
pr_err("capsule update failed\n");
return ret;
Expand Down Expand Up @@ -192,7 +185,7 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
cap_info->page_bytes_remain -= write_byte;

/* Setup capsule binary info structure */
if (!cap_info->header_obtained) {
if (cap_info->header.headersize == 0) {
ret = efi_capsule_setup_info(cap_info, kbuff,
cap_info->count + write_byte);
if (ret)
Expand All @@ -203,7 +196,7 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
kunmap(page);

/* Submit the full binary to efi_capsule_update() API */
if (cap_info->header_obtained &&
if (cap_info->header.headersize > 0 &&
cap_info->count >= cap_info->total_size) {
if (cap_info->count > cap_info->total_size) {
pr_err("capsule upload size exceeded header defined size\n");
Expand Down

0 comments on commit 82c3768

Please sign in to comment.