143b1df0eSArd Biesheuvel // SPDX-License-Identifier: GPL-2.0 243b1df0eSArd Biesheuvel 343b1df0eSArd Biesheuvel #include <linux/efi.h> 443b1df0eSArd Biesheuvel #include <asm/efi.h> 543b1df0eSArd Biesheuvel 643b1df0eSArd Biesheuvel #include "efistub.h" 743b1df0eSArd Biesheuvel 843b1df0eSArd Biesheuvel /** 943b1df0eSArd Biesheuvel * efi_allocate_pages_aligned() - Allocate memory pages 1043b1df0eSArd Biesheuvel * @size: minimum number of bytes to allocate 1143b1df0eSArd Biesheuvel * @addr: On return the address of the first allocated page. The first 1243b1df0eSArd Biesheuvel * allocated page has alignment EFI_ALLOC_ALIGN which is an 1343b1df0eSArd Biesheuvel * architecture dependent multiple of the page size. 1443b1df0eSArd Biesheuvel * @max: the address that the last allocated memory page shall not 1543b1df0eSArd Biesheuvel * exceed 1643b1df0eSArd Biesheuvel * @align: minimum alignment of the base of the allocation 1743b1df0eSArd Biesheuvel * 1843b1df0eSArd Biesheuvel * Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according 1943b1df0eSArd Biesheuvel * to @align, which should be >= EFI_ALLOC_ALIGN. The last allocated page will 2043b1df0eSArd Biesheuvel * not exceed the address given by @max. 2143b1df0eSArd Biesheuvel * 2243b1df0eSArd Biesheuvel * Return: status code 2343b1df0eSArd Biesheuvel */ 2443b1df0eSArd Biesheuvel efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, 25*9cf42bcaSArd Biesheuvel unsigned long max, unsigned long align, 26*9cf42bcaSArd Biesheuvel int memory_type) 2743b1df0eSArd Biesheuvel { 2843b1df0eSArd Biesheuvel efi_physical_addr_t alloc_addr; 2943b1df0eSArd Biesheuvel efi_status_t status; 3043b1df0eSArd Biesheuvel int slack; 3143b1df0eSArd Biesheuvel 3243b1df0eSArd Biesheuvel if (align < EFI_ALLOC_ALIGN) 3343b1df0eSArd Biesheuvel align = EFI_ALLOC_ALIGN; 3443b1df0eSArd Biesheuvel 3543b1df0eSArd Biesheuvel alloc_addr = ALIGN_DOWN(max + 1, align) - 1; 3643b1df0eSArd Biesheuvel size = round_up(size, EFI_ALLOC_ALIGN); 3743b1df0eSArd Biesheuvel slack = align / EFI_PAGE_SIZE - 1; 3843b1df0eSArd Biesheuvel 3943b1df0eSArd Biesheuvel status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, 40*9cf42bcaSArd Biesheuvel memory_type, size / EFI_PAGE_SIZE + slack, 4143b1df0eSArd Biesheuvel &alloc_addr); 4243b1df0eSArd Biesheuvel if (status != EFI_SUCCESS) 4343b1df0eSArd Biesheuvel return status; 4443b1df0eSArd Biesheuvel 4543b1df0eSArd Biesheuvel *addr = ALIGN((unsigned long)alloc_addr, align); 4643b1df0eSArd Biesheuvel 4743b1df0eSArd Biesheuvel if (slack > 0) { 48950accbaSAtish Patra int l = (alloc_addr & (align - 1)) / EFI_PAGE_SIZE; 4943b1df0eSArd Biesheuvel 5043b1df0eSArd Biesheuvel if (l) { 5143b1df0eSArd Biesheuvel efi_bs_call(free_pages, alloc_addr, slack - l + 1); 5243b1df0eSArd Biesheuvel slack = l - 1; 5343b1df0eSArd Biesheuvel } 5443b1df0eSArd Biesheuvel if (slack) 5543b1df0eSArd Biesheuvel efi_bs_call(free_pages, *addr + size, slack); 5643b1df0eSArd Biesheuvel } 5743b1df0eSArd Biesheuvel return EFI_SUCCESS; 5843b1df0eSArd Biesheuvel } 59