// SPDX-License-Identifier: GPL-2.0 /* * Helper functions used by the EFI stub on multiple * architectures. This should be #included by the EFI stub * implementation files. * * Copyright 2011 Intel Corporation; author Matt Fleming */ #include <linux/stdarg.h> #include <linux/efi.h> #include <linux/kernel.h> #include <linux/overflow.h> #include <asm/efi.h> #include <asm/setup.h> #include "efistub.h" bool efi_nochunk; bool efi_nokaslr = !IS_ENABLED(…); bool efi_novamap; static bool efi_noinitrd; static bool efi_nosoftreserve; static bool efi_disable_pci_dma = … IS_ENABLED(…); int efi_mem_encrypt; bool __pure __efi_soft_reserve_enabled(void) { … } /** * efi_parse_options() - Parse EFI command line options * @cmdline: kernel command line * * Parse the ASCII string @cmdline for EFI options, denoted by the efi= * option, e.g. efi=nochunk. * * It should be noted that efi= is parsed in two very different * environments, first in the early boot environment of the EFI boot * stub, and subsequently during the kernel boot. * * Return: status code */ efi_status_t efi_parse_options(char const *cmdline) { … } /* * The EFI_LOAD_OPTION descriptor has the following layout: * u32 Attributes; * u16 FilePathListLength; * u16 Description[]; * efi_device_path_protocol_t FilePathList[]; * u8 OptionalData[]; * * This function validates and unpacks the variable-size data fields. */ static bool efi_load_option_unpack(efi_load_option_unpacked_t *dest, const efi_load_option_t *src, size_t size) { … } /* * At least some versions of Dell firmware pass the entire contents of the * Boot#### variable, i.e. the EFI_LOAD_OPTION descriptor, rather than just the * OptionalData field. * * Detect this case and extract OptionalData. */ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size) { … } enum efistub_event_type { … }; #define STR_WITH_SIZE(s) … static const struct { … } events[] = …; static_assert(…); efistub_event; struct efistub_measured_event { … }; static efi_status_t efi_measure_tagged_event(unsigned long load_addr, unsigned long load_size, enum efistub_event_type event) { … } /* * Convert the unicode UEFI command line to ASCII to pass to kernel. * Size of memory allocated return in *cmd_line_len. * Returns NULL on error. */ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len) { … } /** * efi_exit_boot_services() - Exit boot services * @handle: handle of the exiting image * @priv: argument to be passed to @priv_func * @priv_func: function to process the memory map before exiting boot services * * Handle calling ExitBootServices according to the requirements set out by the * spec. Obtains the current memory map, and returns that info after calling * ExitBootServices. The client must specify a function to perform any * processing of the memory map data prior to ExitBootServices. A client * specific structure may be passed to the function via priv. The client * function may be called multiple times. * * Return: status code */ efi_status_t efi_exit_boot_services(void *handle, void *priv, efi_exit_boot_map_processing priv_func) { … } /** * get_efi_config_table() - retrieve UEFI configuration table * @guid: GUID of the configuration table to be retrieved * Return: pointer to the configuration table or NULL */ void *get_efi_config_table(efi_guid_t guid) { … } /* * The LINUX_EFI_INITRD_MEDIA_GUID vendor media device path below provides a way * for the firmware or bootloader to expose the initrd data directly to the stub * via the trivial LoadFile2 protocol, which is defined in the UEFI spec, and is * very easy to implement. It is a simple Linux initrd specific conduit between * kernel and firmware, allowing us to put the EFI stub (being part of the * kernel) in charge of where and when to load the initrd, while leaving it up * to the firmware to decide whether it needs to expose its filesystem hierarchy * via EFI protocols. */ static const struct { … } __packed initrd_dev_path = …; /** * efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path * @initrd: pointer of struct to store the address where the initrd was loaded * and the size of the loaded initrd * @max: upper limit for the initrd memory allocation * * Return: * * %EFI_SUCCESS if the initrd was loaded successfully, in which * case @load_addr and @load_size are assigned accordingly * * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path * * %EFI_OUT_OF_RESOURCES if memory allocation failed * * %EFI_LOAD_ERROR in all other cases */ static efi_status_t efi_load_initrd_dev_path(struct linux_efi_initrd *initrd, unsigned long max) { … } static efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, struct linux_efi_initrd *initrd, unsigned long soft_limit, unsigned long hard_limit) { … } /** * efi_load_initrd() - Load initial RAM disk * @image: EFI loaded image protocol * @soft_limit: preferred address for loading the initrd * @hard_limit: upper limit address for loading the initrd * * Return: status code */ efi_status_t efi_load_initrd(efi_loaded_image_t *image, unsigned long soft_limit, unsigned long hard_limit, const struct linux_efi_initrd **out) { … } /** * efi_wait_for_key() - Wait for key stroke * @usec: number of microseconds to wait for key stroke * @key: key entered * * Wait for up to @usec microseconds for a key stroke. * * Return: status code, EFI_SUCCESS if key received */ efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key) { … } /** * efi_remap_image - Remap a loaded image with the appropriate permissions * for code and data * * @image_base: the base of the image in memory * @alloc_size: the size of the area in memory occupied by the image * @code_size: the size of the leading part of the image containing code * and read-only data * * efi_remap_image() uses the EFI memory attribute protocol to remap the code * region of the loaded image read-only/executable, and the remainder * read-write/non-executable. The code region is assumed to start at the base * of the image, and will therefore cover the PE/COFF header as well. */ void efi_remap_image(unsigned long image_base, unsigned alloc_size, unsigned long code_size) { … }