mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-22 04:44:46 +00:00
efi_loader: Fix loaded image alignment
We are ignoring the alignment communicated via the PE/COFF header. Starting 5.10 the Linux kernel will loudly complain about it. For more details look at [1] (in linux kernel). So add a function that can allocate aligned EFI memory and use it for our relocated loaded image. [1] c32ac11da3f83 ("efi/libstub: arm64: Double check image alignment at entry") Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Tested-by: Vincent Stehlé <vincent.stehle@arm.com> Acked-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
fa00b6fc3f
commit
ebdea88d57
3 changed files with 60 additions and 6 deletions
|
@ -675,6 +675,8 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid);
|
||||||
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
|
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
|
||||||
/* Generic EFI memory allocator, call this to get memory */
|
/* Generic EFI memory allocator, call this to get memory */
|
||||||
void *efi_alloc(uint64_t len, int memory_type);
|
void *efi_alloc(uint64_t len, int memory_type);
|
||||||
|
/* Allocate pages on the specified alignment */
|
||||||
|
void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align);
|
||||||
/* More specific EFI memory allocator, called by EFI payloads */
|
/* More specific EFI memory allocator, called by EFI payloads */
|
||||||
efi_status_t efi_allocate_pages(enum efi_allocate_type type,
|
efi_status_t efi_allocate_pages(enum efi_allocate_type type,
|
||||||
enum efi_memory_type memory_type,
|
enum efi_memory_type memory_type,
|
||||||
|
|
|
@ -898,9 +898,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
|
||||||
image_base = opt->ImageBase;
|
image_base = opt->ImageBase;
|
||||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||||
handle->image_type = opt->Subsystem;
|
handle->image_type = opt->Subsystem;
|
||||||
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
efi_reloc = efi_alloc_aligned_pages(virt_size,
|
||||||
efi_reloc = efi_alloc(virt_size,
|
loaded_image_info->image_code_type,
|
||||||
loaded_image_info->image_code_type);
|
opt->SectionAlignment);
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
log_err("Out of memory\n");
|
log_err("Out of memory\n");
|
||||||
ret = EFI_OUT_OF_RESOURCES;
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
@ -914,9 +914,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
|
||||||
image_base = opt->ImageBase;
|
image_base = opt->ImageBase;
|
||||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||||
handle->image_type = opt->Subsystem;
|
handle->image_type = opt->Subsystem;
|
||||||
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
efi_reloc = efi_alloc_aligned_pages(virt_size,
|
||||||
efi_reloc = efi_alloc(virt_size,
|
loaded_image_info->image_code_type,
|
||||||
loaded_image_info->image_code_type);
|
opt->SectionAlignment);
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
log_err("Out of memory\n");
|
log_err("Out of memory\n");
|
||||||
ret = EFI_OUT_OF_RESOURCES;
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
|
|
@ -549,6 +549,58 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_alloc_aligned_pages - allocate
|
||||||
|
*
|
||||||
|
* @len: len in bytes
|
||||||
|
* @memory_type: usage type of the allocated memory
|
||||||
|
* @align: alignment in bytes
|
||||||
|
* Return: aligned memory or NULL
|
||||||
|
*/
|
||||||
|
void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align)
|
||||||
|
{
|
||||||
|
u64 req_pages = efi_size_in_pages(len);
|
||||||
|
u64 true_pages = req_pages + efi_size_in_pages(align) - 1;
|
||||||
|
u64 free_pages;
|
||||||
|
u64 aligned_mem;
|
||||||
|
efi_status_t r;
|
||||||
|
u64 mem;
|
||||||
|
|
||||||
|
/* align must be zero or a power of two */
|
||||||
|
if (align & (align - 1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check for overflow */
|
||||||
|
if (true_pages < req_pages)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (align < EFI_PAGE_SIZE) {
|
||||||
|
r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type,
|
||||||
|
req_pages, &mem);
|
||||||
|
return (r == EFI_SUCCESS) ? (void *)(uintptr_t)mem : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type,
|
||||||
|
true_pages, &mem);
|
||||||
|
if (r != EFI_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
aligned_mem = ALIGN(mem, align);
|
||||||
|
/* Free pages before alignment */
|
||||||
|
free_pages = efi_size_in_pages(aligned_mem - mem);
|
||||||
|
if (free_pages)
|
||||||
|
efi_free_pages(mem, free_pages);
|
||||||
|
|
||||||
|
/* Free trailing pages */
|
||||||
|
free_pages = true_pages - (req_pages + free_pages);
|
||||||
|
if (free_pages) {
|
||||||
|
mem = aligned_mem + req_pages * EFI_PAGE_SIZE;
|
||||||
|
efi_free_pages(mem, free_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)(uintptr_t)aligned_mem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_allocate_pool - allocate memory from pool
|
* efi_allocate_pool - allocate memory from pool
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue