287 lines
10 KiB
C
287 lines
10 KiB
C
/*
|
|
* Copyright (c) 2011 - 2022, Intel Corporation.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* This file contains some wrappers around the gnu-efi functions. As
|
|
* we're not going through uefi_call_wrapper() directly, this allows
|
|
* us to get some type-safety for function call arguments and for the
|
|
* compiler to check that the number of function call arguments is
|
|
* correct.
|
|
*
|
|
* It's also a good place to document the EFI interface.
|
|
*/
|
|
|
|
#ifndef __EFILINUX_H__
|
|
#define __EFILINUX_H__
|
|
|
|
#define EFILINUX_VERSION_MAJOR 1
|
|
#define EFILINUX_VERSION_MINOR 0
|
|
|
|
#define MEM_ADDR_1MB (1U << 20U)
|
|
#define MEM_ADDR_4GB (0xFFFFFFFFU)
|
|
|
|
|
|
extern EFI_SYSTEM_TABLE *sys_table;
|
|
extern EFI_BOOT_SERVICES *boot;
|
|
extern EFI_RUNTIME_SERVICES *runtime;
|
|
|
|
extern EFI_STATUS
|
|
emalloc_reserved_aligned(EFI_PHYSICAL_ADDRESS *addr, UINTN size, UINTN align,
|
|
EFI_PHYSICAL_ADDRESS minaddr, EFI_PHYSICAL_ADDRESS maxaddr);
|
|
|
|
/**
|
|
* allocate_pages - Allocate memory pages from the system
|
|
* @atype: type of allocation to perform
|
|
* @mtype: type of memory to allocate
|
|
* @num_pages: number of contiguous 4KB pages to allocate
|
|
* @memory: used to return the address of allocated pages
|
|
*
|
|
* Allocate @num_pages physically contiguous pages from the system
|
|
* memory and return a pointer to the base of the allocation in
|
|
* @memory if the allocation succeeds. On success, the firmware memory
|
|
* map is updated accordingly.
|
|
*
|
|
* If @atype is AllocateAddress then, on input, @memory specifies the
|
|
* address at which to attempt to allocate the memory pages.
|
|
*/
|
|
static inline EFI_STATUS
|
|
allocate_pages(EFI_ALLOCATE_TYPE atype, EFI_MEMORY_TYPE mtype,
|
|
UINTN num_pages, EFI_PHYSICAL_ADDRESS *memory)
|
|
{
|
|
return uefi_call_wrapper(boot->AllocatePages, 4, atype,
|
|
mtype, num_pages, memory);
|
|
}
|
|
|
|
/**
|
|
* free_pages - Return memory allocated by allocate_pages() to the firmware
|
|
* @memory: physical base address of the page range to be freed
|
|
* @num_pages: number of contiguous 4KB pages to free
|
|
*
|
|
* On success, the firmware memory map is updated accordingly.
|
|
*/
|
|
static inline EFI_STATUS
|
|
free_pages(EFI_PHYSICAL_ADDRESS memory, UINTN num_pages)
|
|
{
|
|
return uefi_call_wrapper(boot->FreePages, 2, memory, num_pages);
|
|
}
|
|
|
|
/**
|
|
* allocate_pool - Allocate pool memory
|
|
* @type: the type of pool to allocate
|
|
* @size: number of bytes to allocate from pool of @type
|
|
* @buffer: used to return the address of allocated memory
|
|
*
|
|
* Allocate memory from pool of @type. If the pool needs more memory
|
|
* pages are allocated from EfiConventionalMemory in order to grow the
|
|
* pool.
|
|
*
|
|
* All allocations are eight-byte aligned.
|
|
*/
|
|
static inline EFI_STATUS
|
|
allocate_pool(EFI_MEMORY_TYPE type, UINTN size, void **buffer)
|
|
{
|
|
return uefi_call_wrapper(boot->AllocatePool, 3, type, size, buffer);
|
|
}
|
|
|
|
/**
|
|
* free_pool - Return pool memory to the system
|
|
* @buffer: the buffer to free
|
|
*
|
|
* Return @buffer to the system. The returned memory is marked as
|
|
* EfiConventionalMemory.
|
|
*/
|
|
static inline EFI_STATUS free_pool(void *buffer)
|
|
{
|
|
return uefi_call_wrapper(boot->FreePool, 1, buffer);
|
|
}
|
|
|
|
/**
|
|
* get_memory_map - Return the current memory map
|
|
* @size: the size in bytes of @map
|
|
* @map: buffer to hold the current memory map
|
|
* @key: used to return the key for the current memory map
|
|
* @descr_size: used to return the size in bytes of EFI_MEMORY_DESCRIPTOR
|
|
* @descr_version: used to return the version of EFI_MEMORY_DESCRIPTOR
|
|
*
|
|
* Get a copy of the current memory map. The memory map is an array of
|
|
* EFI_MEMORY_DESCRIPTORs. An EFI_MEMORY_DESCRIPTOR describes a
|
|
* contiguous block of memory.
|
|
*
|
|
* On success, @key is updated to contain an identifer for the current
|
|
* memory map. The firmware's key is changed every time something in
|
|
* the memory map changes. @size is updated to indicate the size of
|
|
* the memory map pointed to by @map.
|
|
*
|
|
* @descr_size and @descr_version are used to ensure backwards
|
|
* compatibility with future changes made to the EFI_MEMORY_DESCRIPTOR
|
|
* structure. @descr_size MUST be used when the size of an
|
|
* EFI_MEMORY_DESCRIPTOR is used in a calculation, e.g when iterating
|
|
* over an array of EFI_MEMORY_DESCRIPTORs.
|
|
*
|
|
* On failure, and if the buffer pointed to by @map is too small to
|
|
* hold the memory map, EFI_BUFFER_TOO_SMALL is returned and @size is
|
|
* updated to reflect the size of a buffer required to hold the memory
|
|
* map.
|
|
*/
|
|
static inline EFI_STATUS
|
|
get_memory_map(UINTN *size, EFI_MEMORY_DESCRIPTOR *map, UINTN *key,
|
|
UINTN *descr_size, UINT32 *descr_version)
|
|
{
|
|
return uefi_call_wrapper(boot->GetMemoryMap, 5, size, map,
|
|
key, descr_size, descr_version);
|
|
}
|
|
|
|
/**
|
|
* exit_boot_serivces - Terminate all boot services
|
|
* @image: firmware-allocated handle that identifies the image
|
|
* @key: key to the latest memory map
|
|
*
|
|
* This function is called when efilinux wants to take complete
|
|
* control of the system. efilinux should not make calls to boot time
|
|
* services after this function is called.
|
|
*/
|
|
static inline EFI_STATUS
|
|
exit_boot_services(EFI_HANDLE image, UINTN key)
|
|
{
|
|
return uefi_call_wrapper(boot->ExitBootServices, 2, image, key);
|
|
}
|
|
|
|
|
|
/**
|
|
* handle_protocol - Query @handle to see if it supports @protocol
|
|
* @handle: the handle being queried
|
|
* @protocol: the GUID of the protocol
|
|
* @interface: used to return the protocol interface
|
|
*
|
|
* Query @handle to see if @protocol is supported. If it is supported,
|
|
* @interface contains the protocol interface.
|
|
*/
|
|
static inline EFI_STATUS
|
|
handle_protocol(EFI_HANDLE handle, EFI_GUID *protocol, void **interface)
|
|
{
|
|
return uefi_call_wrapper(boot->HandleProtocol, 3,
|
|
handle, protocol, interface);
|
|
}
|
|
|
|
|
|
/*
|
|
* emalloc_reserved_mem - it is called to allocate memory hypervisor itself
|
|
* and trampoline code, and mark the allocate memory as EfiReserved memory
|
|
* type so that Service VM won't touch it during boot.
|
|
* @addr: a pointer to the allocated address on success
|
|
* @size: size in bytes of the requested allocation
|
|
* @max_addr: the allocated memory must be no more than this threshold
|
|
*/
|
|
static inline EFI_STATUS emalloc_reserved_mem(EFI_PHYSICAL_ADDRESS *addr,
|
|
UINTN size, EFI_PHYSICAL_ADDRESS max_addr)
|
|
{
|
|
*addr = max_addr;
|
|
return allocate_pages(AllocateMaxAddress, EfiReservedMemoryType,
|
|
EFI_SIZE_TO_PAGES(size), addr);
|
|
}
|
|
|
|
|
|
/*
|
|
* emalloc_fixed_addr - it is called to allocate memory hypervisor itself
|
|
* when CONFIG_RELOC config is NOT enable.And mark the allocated memory as
|
|
* EfiReserved memory type so that Service VM won't touch it during boot.
|
|
* @addr: a pointer to the allocated address on success
|
|
* @size: size in bytes of the requested allocation
|
|
*/
|
|
static inline EFI_STATUS emalloc_fixed_addr(EFI_PHYSICAL_ADDRESS *addr,
|
|
UINTN size, EFI_PHYSICAL_ADDRESS fixed_addr)
|
|
{
|
|
*addr = fixed_addr;
|
|
return allocate_pages(AllocateAddress, EfiReservedMemoryType,
|
|
EFI_SIZE_TO_PAGES(size), addr);
|
|
}
|
|
|
|
static inline EFI_STATUS get_variable(const CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, void *data)
|
|
{
|
|
return uefi_call_wrapper(runtime->GetVariable, 5, name, guid, attrs, size, data);
|
|
}
|
|
|
|
static inline EFI_STATUS set_variable(const CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, void *data)
|
|
{
|
|
return uefi_call_wrapper(runtime->SetVariable, 5, name, guid, attrs, size, data);
|
|
}
|
|
|
|
/**
|
|
* exit - Terminate a loaded EFI image
|
|
* @image: firmware-allocated handle that identifies the image
|
|
* @status: the image's exit code
|
|
* @size: size in bytes of @reason. Ignored if @status is EFI_SUCCESS
|
|
* @reason: a NUL-terminated status string, optionally followed by binary data
|
|
*
|
|
* This function terminates @image and returns control to the boot
|
|
* services. This function MUST NOT be called until all loaded child
|
|
* images have exited. All memory allocated by the image must be freed
|
|
* before calling this function, apart from the buffer @reason, which
|
|
* will be freed by the firmware.
|
|
*/
|
|
static inline EFI_STATUS
|
|
exit(EFI_HANDLE image, EFI_STATUS status, UINTN size, CHAR16 *reason)
|
|
{
|
|
return uefi_call_wrapper(boot->Exit, 4, image, status, size, reason);
|
|
}
|
|
|
|
#define PAGE_SIZE 4096
|
|
|
|
static const CHAR16 *memory_types[] = {
|
|
L"EfiReservedMemoryType",
|
|
L"EfiLoaderCode",
|
|
L"EfiLoaderData",
|
|
L"EfiBootServicesCode",
|
|
L"EfiBootServicesData",
|
|
L"EfiRuntimeServicesCode",
|
|
L"EfiRuntimeServicesData",
|
|
L"EfiConventionalMemory",
|
|
L"EfiUnusableMemory",
|
|
L"EfiACPIReclaimMemory",
|
|
L"EfiACPIMemoryNVS",
|
|
L"EfiMemoryMappedIO",
|
|
L"EfiMemoryMappedIOPortSpace",
|
|
L"EfiPalCode",
|
|
};
|
|
|
|
static inline const CHAR16 *memory_type_to_str(UINT32 type)
|
|
{
|
|
if (type > sizeof(memory_types)/sizeof(CHAR16 *))
|
|
return L"Unknown";
|
|
|
|
return memory_types[type];
|
|
}
|
|
|
|
extern EFI_STATUS memory_map(EFI_MEMORY_DESCRIPTOR **map_buf,
|
|
UINTN *map_size, UINTN *map_key,
|
|
UINTN *desc_size, UINT32 *desc_version);
|
|
|
|
#endif /* __EFILINUX_H__ */
|