Path: blob/master/drivers/firmware/efi/libstub/alignedmem.c
26483 views
// SPDX-License-Identifier: GPL-2.012#include <linux/efi.h>3#include <asm/efi.h>45#include "efistub.h"67/**8* efi_allocate_pages_aligned() - Allocate memory pages9* @size: minimum number of bytes to allocate10* @addr: On return the address of the first allocated page. The first11* allocated page has alignment EFI_ALLOC_ALIGN which is an12* architecture dependent multiple of the page size.13* @max: the address that the last allocated memory page shall not14* exceed15* @align: minimum alignment of the base of the allocation16* @memory_type: the type of memory to allocate17*18* Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according19* to @align, which should be >= EFI_ALLOC_ALIGN. The last allocated page will20* not exceed the address given by @max.21*22* Return: status code23*/24efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,25unsigned long max, unsigned long align,26int memory_type)27{28efi_physical_addr_t alloc_addr;29efi_status_t status;30int slack;3132max = min(max, EFI_ALLOC_LIMIT);3334if (align < EFI_ALLOC_ALIGN)35align = EFI_ALLOC_ALIGN;3637alloc_addr = ALIGN_DOWN(max + 1, align) - 1;38size = round_up(size, EFI_ALLOC_ALIGN);39slack = align / EFI_PAGE_SIZE - 1;4041status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,42memory_type, size / EFI_PAGE_SIZE + slack,43&alloc_addr);44if (status != EFI_SUCCESS)45return status;4647*addr = ALIGN((unsigned long)alloc_addr, align);4849if (slack > 0) {50int l = (alloc_addr & (align - 1)) / EFI_PAGE_SIZE;5152if (l) {53efi_bs_call(free_pages, alloc_addr, slack - l + 1);54slack = l - 1;55}56if (slack)57efi_bs_call(free_pages, *addr + size, slack);58}59return EFI_SUCCESS;60}616263