// SPDX-License-Identifier: GPL-2.012#include <linux/efi.h>3#include <asm/efi.h>45#include "efistub.h"67/**8* efi_get_memory_map() - get memory map9* @map: pointer to memory map pointer to which to assign the10* newly allocated memory map11* @install_cfg_tbl: whether or not to install the boot memory map as a12* configuration table13*14* Retrieve the UEFI memory map. The allocated memory leaves room for15* up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries.16*17* Return: status code18*/19efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,20bool install_cfg_tbl)21{22struct efi_boot_memmap tmp, *m __free(efi_pool) = NULL;23int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY24: EFI_LOADER_DATA;25efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;26efi_status_t status;27unsigned long size;2829tmp.map_size = 0;30status = efi_bs_call(get_memory_map, &tmp.map_size, NULL, &tmp.map_key,31&tmp.desc_size, &tmp.desc_ver);32if (status != EFI_BUFFER_TOO_SMALL)33return EFI_LOAD_ERROR;3435size = tmp.map_size + tmp.desc_size * EFI_MMAP_NR_SLACK_SLOTS;36status = efi_bs_call(allocate_pool, memtype, sizeof(*m) + size,37(void **)&m);38if (status != EFI_SUCCESS)39return status;4041if (install_cfg_tbl) {42/*43* Installing a configuration table might allocate memory, and44* this may modify the memory map. This means we should install45* the configuration table first, and re-install or delete it46* as needed.47*/48status = efi_bs_call(install_configuration_table, &tbl_guid, m);49if (status != EFI_SUCCESS)50return status;51}5253m->buff_size = m->map_size = size;54status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key,55&m->desc_size, &m->desc_ver);56if (status != EFI_SUCCESS) {57if (install_cfg_tbl)58efi_bs_call(install_configuration_table, &tbl_guid, NULL);59return status;60}6162*map = no_free_ptr(m);63return EFI_SUCCESS;64}6566/**67* efi_allocate_pages() - Allocate memory pages68* @size: minimum number of bytes to allocate69* @addr: On return the address of the first allocated page. The first70* allocated page has alignment EFI_ALLOC_ALIGN which is an71* architecture dependent multiple of the page size.72* @max: the address that the last allocated memory page shall not73* exceed74*75* Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according76* to EFI_ALLOC_ALIGN. The last allocated page will not exceed the address77* given by @max.78*79* Return: status code80*/81efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,82unsigned long max)83{84efi_physical_addr_t alloc_addr;85efi_status_t status;8687max = min(max, EFI_ALLOC_LIMIT);8889if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)90return efi_allocate_pages_aligned(size, addr, max,91EFI_ALLOC_ALIGN,92EFI_LOADER_DATA);9394alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;95status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,96EFI_LOADER_DATA, DIV_ROUND_UP(size, EFI_PAGE_SIZE),97&alloc_addr);98if (status != EFI_SUCCESS)99return status;100101*addr = alloc_addr;102return EFI_SUCCESS;103}104105/**106* efi_free() - free memory pages107* @size: size of the memory area to free in bytes108* @addr: start of the memory area to free (must be EFI_PAGE_SIZE109* aligned)110*111* @size is rounded up to a multiple of EFI_ALLOC_ALIGN which is an112* architecture specific multiple of EFI_PAGE_SIZE. So this function should113* only be used to return pages allocated with efi_allocate_pages() or114* efi_low_alloc_above().115*/116void efi_free(unsigned long size, unsigned long addr)117{118unsigned long nr_pages;119120if (!size)121return;122123nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;124efi_bs_call(free_pages, addr, nr_pages);125}126127128