Skip to content

Commit

Permalink
efi/libstub: Fix allocation size calculations
Browse files Browse the repository at this point in the history
Adjust the size used in calculations to match the actual size of allocation
that will be performed based on EFI size/alignment constraints.
efi_high_alloc() and efi_low_alloc() use the passed size in bytes directly
to find space in the memory map for the allocation, rather than the actual
allocation size that has been adjusted for size and alignment constraints.
This results in failed allocations and retries in efi_high_alloc().  The
same error is present in efi_low_alloc(), although failure will only happen
if the lowest memory block is small.
Also use EFI_PAGE_SIZE consistently and remove use of EFI_PAGE_SHIFT to
calculate page size.

Signed-off-by: Roy Franz <roy.franz@hpe.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-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/20161112213237.8804-2-matt@codeblueprint.co.uk
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Roy Franz authored and Ingo Molnar committed Nov 13, 2016
1 parent 74239ac commit 5b88a31
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions drivers/firmware/efi/libstub/efi-stub-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,16 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
goto fail;

/*
* Enforce minimum alignment that EFI requires when requesting
* a specific address. We are doing page-based allocations,
* so we must be aligned to a page.
* Enforce minimum alignment that EFI or Linux requires when
* requesting a specific address. We are doing page-based (or
* larger) allocations, and both the address and size must meet
* alignment constraints.
*/
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;

nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
size = round_up(size, EFI_ALLOC_ALIGN);
nr_pages = size / EFI_PAGE_SIZE;
again:
for (i = 0; i < map_size / desc_size; i++) {
efi_memory_desc_t *desc;
Expand All @@ -208,7 +210,7 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
continue;

start = desc->phys_addr;
end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
end = start + desc->num_pages * EFI_PAGE_SIZE;

if (end > max)
end = max;
Expand Down Expand Up @@ -278,14 +280,16 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
goto fail;

/*
* Enforce minimum alignment that EFI requires when requesting
* a specific address. We are doing page-based allocations,
* so we must be aligned to a page.
* Enforce minimum alignment that EFI or Linux requires when
* requesting a specific address. We are doing page-based (or
* larger) allocations, and both the address and size must meet
* alignment constraints.
*/
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;

nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
size = round_up(size, EFI_ALLOC_ALIGN);
nr_pages = size / EFI_PAGE_SIZE;
for (i = 0; i < map_size / desc_size; i++) {
efi_memory_desc_t *desc;
unsigned long m = (unsigned long)map;
Expand All @@ -300,7 +304,7 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
continue;

start = desc->phys_addr;
end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
end = start + desc->num_pages * EFI_PAGE_SIZE;

/*
* Don't allocate at 0x0. It will confuse code that
Expand Down

0 comments on commit 5b88a31

Please sign in to comment.