Path: blob/master/drivers/firmware/efi/libstub/efi-stub-helper.c
26483 views
// SPDX-License-Identifier: GPL-2.01/*2* Helper functions used by the EFI stub on multiple3* architectures. This should be #included by the EFI stub4* implementation files.5*6* Copyright 2011 Intel Corporation; author Matt Fleming7*/89#include <linux/stdarg.h>1011#include <linux/efi.h>12#include <linux/kernel.h>13#include <linux/overflow.h>14#include <asm/efi.h>15#include <asm/setup.h>1617#include "efistub.h"1819bool efi_nochunk;20bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);21bool efi_novamap;2223static bool efi_noinitrd;24static bool efi_nosoftreserve;25static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);2627int efi_mem_encrypt;2829bool __pure __efi_soft_reserve_enabled(void)30{31return !efi_nosoftreserve;32}3334/**35* efi_parse_options() - Parse EFI command line options36* @cmdline: kernel command line37*38* Parse the ASCII string @cmdline for EFI options, denoted by the efi=39* option, e.g. efi=nochunk.40*41* It should be noted that efi= is parsed in two very different42* environments, first in the early boot environment of the EFI boot43* stub, and subsequently during the kernel boot.44*45* Return: status code46*/47efi_status_t efi_parse_options(char const *cmdline)48{49char *buf __free(efi_pool) = NULL;50efi_status_t status;51size_t len;52char *str;5354if (!cmdline)55return EFI_SUCCESS;5657len = strnlen(cmdline, COMMAND_LINE_SIZE - 1) + 1;58status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);59if (status != EFI_SUCCESS)60return status;6162memcpy(buf, cmdline, len - 1);63buf[len - 1] = '\0';64str = skip_spaces(buf);6566while (*str) {67char *param, *val;6869str = next_arg(str, ¶m, &val);70if (!val && !strcmp(param, "--"))71break;7273if (!strcmp(param, "nokaslr")) {74efi_nokaslr = true;75} else if (!strcmp(param, "quiet")) {76efi_loglevel = CONSOLE_LOGLEVEL_QUIET;77} else if (!strcmp(param, "noinitrd")) {78efi_noinitrd = true;79} else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {80efi_no5lvl = true;81} else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&82!strcmp(param, "mem_encrypt") && val) {83if (parse_option_str(val, "on"))84efi_mem_encrypt = 1;85else if (parse_option_str(val, "off"))86efi_mem_encrypt = -1;87} else if (!strcmp(param, "efi") && val) {88efi_nochunk = parse_option_str(val, "nochunk");89efi_novamap |= parse_option_str(val, "novamap");9091efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&92parse_option_str(val, "nosoftreserve");9394if (parse_option_str(val, "disable_early_pci_dma"))95efi_disable_pci_dma = true;96if (parse_option_str(val, "no_disable_early_pci_dma"))97efi_disable_pci_dma = false;98if (parse_option_str(val, "debug"))99efi_loglevel = CONSOLE_LOGLEVEL_DEBUG;100} else if (!strcmp(param, "video") &&101val && strstarts(val, "efifb:")) {102efi_parse_option_graphics(val + strlen("efifb:"));103}104}105return EFI_SUCCESS;106}107108/*109* The EFI_LOAD_OPTION descriptor has the following layout:110* u32 Attributes;111* u16 FilePathListLength;112* u16 Description[];113* efi_device_path_protocol_t FilePathList[];114* u8 OptionalData[];115*116* This function validates and unpacks the variable-size data fields.117*/118static119bool efi_load_option_unpack(efi_load_option_unpacked_t *dest,120const efi_load_option_t *src, size_t size)121{122const void *pos;123u16 c;124efi_device_path_protocol_t header;125const efi_char16_t *description;126const efi_device_path_protocol_t *file_path_list;127128if (size < offsetof(efi_load_option_t, variable_data))129return false;130pos = src->variable_data;131size -= offsetof(efi_load_option_t, variable_data);132133if ((src->attributes & ~EFI_LOAD_OPTION_MASK) != 0)134return false;135136/* Scan description. */137description = pos;138do {139if (size < sizeof(c))140return false;141c = *(const u16 *)pos;142pos += sizeof(c);143size -= sizeof(c);144} while (c != L'\0');145146/* Scan file_path_list. */147file_path_list = pos;148do {149if (size < sizeof(header))150return false;151header = *(const efi_device_path_protocol_t *)pos;152if (header.length < sizeof(header))153return false;154if (size < header.length)155return false;156pos += header.length;157size -= header.length;158} while ((header.type != EFI_DEV_END_PATH && header.type != EFI_DEV_END_PATH2) ||159(header.sub_type != EFI_DEV_END_ENTIRE));160if (pos != (const void *)file_path_list + src->file_path_list_length)161return false;162163dest->attributes = src->attributes;164dest->file_path_list_length = src->file_path_list_length;165dest->description = description;166dest->file_path_list = file_path_list;167dest->optional_data_size = size;168dest->optional_data = size ? pos : NULL;169170return true;171}172173/*174* At least some versions of Dell firmware pass the entire contents of the175* Boot#### variable, i.e. the EFI_LOAD_OPTION descriptor, rather than just the176* OptionalData field.177*178* Detect this case and extract OptionalData.179*/180void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size)181{182const efi_load_option_t *load_option = *load_options;183efi_load_option_unpacked_t load_option_unpacked;184185if (!IS_ENABLED(CONFIG_X86))186return;187if (!load_option)188return;189if (*load_options_size < sizeof(*load_option))190return;191if ((load_option->attributes & ~EFI_LOAD_OPTION_BOOT_MASK) != 0)192return;193194if (!efi_load_option_unpack(&load_option_unpacked, load_option, *load_options_size))195return;196197efi_warn_once(FW_BUG "LoadOptions is an EFI_LOAD_OPTION descriptor\n");198efi_warn_once(FW_BUG "Using OptionalData as a workaround\n");199200*load_options = load_option_unpacked.optional_data;201*load_options_size = load_option_unpacked.optional_data_size;202}203204enum efistub_event_type {205EFISTUB_EVT_INITRD,206EFISTUB_EVT_LOAD_OPTIONS,207EFISTUB_EVT_COUNT,208};209210#define STR_WITH_SIZE(s) sizeof(s), s211212static const struct {213u32 pcr_index;214u32 event_id;215u32 event_data_len;216u8 event_data[52];217} events[] = {218[EFISTUB_EVT_INITRD] = {2199,220INITRD_EVENT_TAG_ID,221STR_WITH_SIZE("Linux initrd")222},223[EFISTUB_EVT_LOAD_OPTIONS] = {2249,225LOAD_OPTIONS_EVENT_TAG_ID,226STR_WITH_SIZE("LOADED_IMAGE::LoadOptions")227},228};229230static_assert(sizeof(efi_tcg2_event_t) == sizeof(efi_cc_event_t));231232union efistub_event {233efi_tcg2_event_t tcg2_data;234efi_cc_event_t cc_data;235};236237struct efistub_measured_event {238union efistub_event event_data;239TCG_PCClientTaggedEvent tagged_event __packed;240};241242static efi_status_t efi_measure_tagged_event(unsigned long load_addr,243unsigned long load_size,244enum efistub_event_type event)245{246union {247efi_status_t248(__efiapi *hash_log_extend_event)(void *, u64, efi_physical_addr_t,249u64, const union efistub_event *);250struct { u32 hash_log_extend_event; } mixed_mode;251} method;252struct efistub_measured_event *evt __free(efi_pool) = NULL;253int size = struct_size(evt, tagged_event.tagged_event_data,254events[event].event_data_len);255efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;256efi_tcg2_protocol_t *tcg2 = NULL;257union efistub_event ev;258efi_status_t status;259void *protocol;260261efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);262if (tcg2) {263ev.tcg2_data = (struct efi_tcg2_event){264.event_size = size,265.event_header.header_size = sizeof(ev.tcg2_data.event_header),266.event_header.header_version = EFI_TCG2_EVENT_HEADER_VERSION,267.event_header.pcr_index = events[event].pcr_index,268.event_header.event_type = EV_EVENT_TAG,269};270protocol = tcg2;271method.hash_log_extend_event =272(void *)efi_table_attr(tcg2, hash_log_extend_event);273} else {274efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;275efi_cc_protocol_t *cc = NULL;276277efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);278if (!cc)279return EFI_UNSUPPORTED;280281ev.cc_data = (struct efi_cc_event){282.event_size = size,283.event_header.header_size = sizeof(ev.cc_data.event_header),284.event_header.header_version = EFI_CC_EVENT_HEADER_VERSION,285.event_header.event_type = EV_EVENT_TAG,286};287288status = efi_call_proto(cc, map_pcr_to_mr_index,289events[event].pcr_index,290&ev.cc_data.event_header.mr_index);291if (status != EFI_SUCCESS)292goto fail;293294protocol = cc;295method.hash_log_extend_event =296(void *)efi_table_attr(cc, hash_log_extend_event);297}298299status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, (void **)&evt);300if (status != EFI_SUCCESS)301goto fail;302303*evt = (struct efistub_measured_event) {304.event_data = ev,305.tagged_event.tagged_event_id = events[event].event_id,306.tagged_event.tagged_event_data_size = events[event].event_data_len,307};308309memcpy(evt->tagged_event.tagged_event_data, events[event].event_data,310events[event].event_data_len);311312status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,313load_addr, load_size, &evt->event_data);314315if (status == EFI_SUCCESS)316return EFI_SUCCESS;317318fail:319efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);320return status;321}322323/*324* Convert the unicode UEFI command line to ASCII to pass to kernel.325* Size of memory allocated return in *cmd_line_len.326* Returns NULL on error.327*/328char *efi_convert_cmdline(efi_loaded_image_t *image)329{330const efi_char16_t *options = efi_table_attr(image, load_options);331u32 options_size = efi_table_attr(image, load_options_size);332int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */333unsigned long cmdline_addr = 0;334const efi_char16_t *s2;335bool in_quote = false;336efi_status_t status;337u32 options_chars;338339if (options_size > 0)340efi_measure_tagged_event((unsigned long)options, options_size,341EFISTUB_EVT_LOAD_OPTIONS);342343efi_apply_loadoptions_quirk((const void **)&options, &options_size);344options_chars = options_size / sizeof(efi_char16_t);345346if (options) {347s2 = options;348while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {349efi_char16_t c = *s2++;350351if (c < 0x80) {352if (c == L'\0' || c == L'\n')353break;354if (c == L'"')355in_quote = !in_quote;356else if (!in_quote && isspace((char)c))357safe_options_bytes = options_bytes;358359options_bytes++;360continue;361}362363/*364* Get the number of UTF-8 bytes corresponding to a365* UTF-16 character.366* The first part handles everything in the BMP.367*/368options_bytes += 2 + (c >= 0x800);369/*370* Add one more byte for valid surrogate pairs. Invalid371* surrogates will be replaced with 0xfffd and take up372* only 3 bytes.373*/374if ((c & 0xfc00) == 0xd800) {375/*376* If the very last word is a high surrogate,377* we must ignore it since we can't access the378* low surrogate.379*/380if (!options_chars) {381options_bytes -= 3;382} else if ((*s2 & 0xfc00) == 0xdc00) {383options_bytes++;384options_chars--;385s2++;386}387}388}389if (options_bytes >= COMMAND_LINE_SIZE) {390options_bytes = safe_options_bytes;391efi_err("Command line is too long: truncated to %d bytes\n",392options_bytes);393}394}395396options_bytes++; /* NUL termination */397398status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, options_bytes,399(void **)&cmdline_addr);400if (status != EFI_SUCCESS)401return NULL;402403snprintf((char *)cmdline_addr, options_bytes, "%.*ls",404options_bytes - 1, options);405406return (char *)cmdline_addr;407}408409/**410* efi_exit_boot_services() - Exit boot services411* @handle: handle of the exiting image412* @priv: argument to be passed to @priv_func413* @priv_func: function to process the memory map before exiting boot services414*415* Handle calling ExitBootServices according to the requirements set out by the416* spec. Obtains the current memory map, and returns that info after calling417* ExitBootServices. The client must specify a function to perform any418* processing of the memory map data prior to ExitBootServices. A client419* specific structure may be passed to the function via priv. The client420* function may be called multiple times.421*422* Return: status code423*/424efi_status_t efi_exit_boot_services(void *handle, void *priv,425efi_exit_boot_map_processing priv_func)426{427struct efi_boot_memmap *map;428efi_status_t status;429430if (efi_disable_pci_dma)431efi_pci_disable_bridge_busmaster();432433status = efi_get_memory_map(&map, true);434if (status != EFI_SUCCESS)435return status;436437status = priv_func(map, priv);438if (status != EFI_SUCCESS) {439efi_bs_call(free_pool, map);440return status;441}442443status = efi_bs_call(exit_boot_services, handle, map->map_key);444445if (status == EFI_INVALID_PARAMETER) {446/*447* The memory map changed between efi_get_memory_map() and448* exit_boot_services(). Per the UEFI Spec v2.6, Section 6.4:449* EFI_BOOT_SERVICES.ExitBootServices we need to get the450* updated map, and try again. The spec implies one retry451* should be sufficent, which is confirmed against the EDK2452* implementation. Per the spec, we can only invoke453* get_memory_map() and exit_boot_services() - we cannot alloc454* so efi_get_memory_map() cannot be used, and we must reuse455* the buffer. For all practical purposes, the headroom in the456* buffer should account for any changes in the map so the call457* to get_memory_map() is expected to succeed here.458*/459map->map_size = map->buff_size;460status = efi_bs_call(get_memory_map,461&map->map_size,462&map->map,463&map->map_key,464&map->desc_size,465&map->desc_ver);466467/* exit_boot_services() was called, thus cannot free */468if (status != EFI_SUCCESS)469return status;470471status = priv_func(map, priv);472/* exit_boot_services() was called, thus cannot free */473if (status != EFI_SUCCESS)474return status;475476status = efi_bs_call(exit_boot_services, handle, map->map_key);477}478479return status;480}481482/**483* get_efi_config_table() - retrieve UEFI configuration table484* @guid: GUID of the configuration table to be retrieved485* Return: pointer to the configuration table or NULL486*/487void *get_efi_config_table(efi_guid_t guid)488{489unsigned long tables = efi_table_attr(efi_system_table, tables);490int nr_tables = efi_table_attr(efi_system_table, nr_tables);491int i;492493for (i = 0; i < nr_tables; i++) {494efi_config_table_t *t = (void *)tables;495496if (efi_guidcmp(t->guid, guid) == 0)497return efi_table_attr(t, table);498499tables += efi_is_native() ? sizeof(efi_config_table_t)500: sizeof(efi_config_table_32_t);501}502return NULL;503}504505/*506* The LINUX_EFI_INITRD_MEDIA_GUID vendor media device path below provides a way507* for the firmware or bootloader to expose the initrd data directly to the stub508* via the trivial LoadFile2 protocol, which is defined in the UEFI spec, and is509* very easy to implement. It is a simple Linux initrd specific conduit between510* kernel and firmware, allowing us to put the EFI stub (being part of the511* kernel) in charge of where and when to load the initrd, while leaving it up512* to the firmware to decide whether it needs to expose its filesystem hierarchy513* via EFI protocols.514*/515static const struct {516struct efi_vendor_dev_path vendor;517struct efi_generic_dev_path end;518} __packed initrd_dev_path = {519{520{521EFI_DEV_MEDIA,522EFI_DEV_MEDIA_VENDOR,523sizeof(struct efi_vendor_dev_path),524},525LINUX_EFI_INITRD_MEDIA_GUID526}, {527EFI_DEV_END_PATH,528EFI_DEV_END_ENTIRE,529sizeof(struct efi_generic_dev_path)530}531};532533/**534* efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path535* @initrd: pointer of struct to store the address where the initrd was loaded536* and the size of the loaded initrd537* @max: upper limit for the initrd memory allocation538*539* Return:540* * %EFI_SUCCESS if the initrd was loaded successfully, in which541* case @load_addr and @load_size are assigned accordingly542* * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path543* * %EFI_OUT_OF_RESOURCES if memory allocation failed544* * %EFI_LOAD_ERROR in all other cases545*/546static547efi_status_t efi_load_initrd_dev_path(struct linux_efi_initrd *initrd,548unsigned long max)549{550efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;551efi_device_path_protocol_t *dp;552efi_load_file2_protocol_t *lf2;553efi_handle_t handle;554efi_status_t status;555556dp = (efi_device_path_protocol_t *)&initrd_dev_path;557status = efi_bs_call(locate_device_path, &lf2_proto_guid, &dp, &handle);558if (status != EFI_SUCCESS)559return status;560561status = efi_bs_call(handle_protocol, handle, &lf2_proto_guid,562(void **)&lf2);563if (status != EFI_SUCCESS)564return status;565566initrd->size = 0;567status = efi_call_proto(lf2, load_file, dp, false, &initrd->size, NULL);568if (status != EFI_BUFFER_TOO_SMALL)569return EFI_LOAD_ERROR;570571status = efi_allocate_pages(initrd->size, &initrd->base, max);572if (status != EFI_SUCCESS)573return status;574575status = efi_call_proto(lf2, load_file, dp, false, &initrd->size,576(void *)initrd->base);577if (status != EFI_SUCCESS) {578efi_free(initrd->size, initrd->base);579return EFI_LOAD_ERROR;580}581return EFI_SUCCESS;582}583584static585efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,586struct linux_efi_initrd *initrd,587unsigned long soft_limit,588unsigned long hard_limit)589{590if (image == NULL)591return EFI_UNSUPPORTED;592593return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,594soft_limit, hard_limit,595&initrd->base, &initrd->size);596}597598/**599* efi_load_initrd() - Load initial RAM disk600* @image: EFI loaded image protocol601* @soft_limit: preferred address for loading the initrd602* @hard_limit: upper limit address for loading the initrd603* @out: pointer to store the address of the initrd table604*605* Return: status code606*/607efi_status_t efi_load_initrd(efi_loaded_image_t *image,608unsigned long soft_limit,609unsigned long hard_limit,610const struct linux_efi_initrd **out)611{612efi_guid_t tbl_guid = LINUX_EFI_INITRD_MEDIA_GUID;613efi_status_t status = EFI_SUCCESS;614struct linux_efi_initrd initrd, *tbl;615616if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD) || efi_noinitrd)617return EFI_SUCCESS;618619status = efi_load_initrd_dev_path(&initrd, hard_limit);620if (status == EFI_SUCCESS) {621efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");622} else if (status == EFI_NOT_FOUND) {623status = efi_load_initrd_cmdline(image, &initrd, soft_limit,624hard_limit);625/* command line loader disabled or no initrd= passed? */626if (status == EFI_UNSUPPORTED || status == EFI_NOT_READY)627return EFI_SUCCESS;628if (status == EFI_SUCCESS)629efi_info("Loaded initrd from command line option\n");630}631if (status != EFI_SUCCESS)632goto failed;633634if (initrd.size > 0 &&635efi_measure_tagged_event(initrd.base, initrd.size,636EFISTUB_EVT_INITRD) == EFI_SUCCESS)637efi_info("Measured initrd data into PCR 9\n");638639status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),640(void **)&tbl);641if (status != EFI_SUCCESS)642goto free_initrd;643644*tbl = initrd;645status = efi_bs_call(install_configuration_table, &tbl_guid, tbl);646if (status != EFI_SUCCESS)647goto free_tbl;648649if (out)650*out = tbl;651return EFI_SUCCESS;652653free_tbl:654efi_bs_call(free_pool, tbl);655free_initrd:656efi_free(initrd.size, initrd.base);657failed:658efi_err("Failed to load initrd: 0x%lx\n", status);659return status;660}661662/**663* efi_wait_for_key() - Wait for key stroke664* @usec: number of microseconds to wait for key stroke665* @key: key entered666*667* Wait for up to @usec microseconds for a key stroke.668*669* Return: status code, EFI_SUCCESS if key received670*/671efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)672{673efi_event_t events[2], timer;674unsigned long index;675efi_simple_text_input_protocol_t *con_in;676efi_status_t status;677678con_in = efi_table_attr(efi_system_table, con_in);679if (!con_in)680return EFI_UNSUPPORTED;681efi_set_event_at(events, 0, efi_table_attr(con_in, wait_for_key));682683status = efi_bs_call(create_event, EFI_EVT_TIMER, 0, NULL, NULL, &timer);684if (status != EFI_SUCCESS)685return status;686687status = efi_bs_call(set_timer, timer, EfiTimerRelative,688EFI_100NSEC_PER_USEC * usec);689if (status != EFI_SUCCESS)690return status;691efi_set_event_at(events, 1, timer);692693status = efi_bs_call(wait_for_event, 2, events, &index);694if (status == EFI_SUCCESS) {695if (index == 0)696status = efi_call_proto(con_in, read_keystroke, key);697else698status = EFI_TIMEOUT;699}700701efi_bs_call(close_event, timer);702703return status;704}705706/**707* efi_remap_image - Remap a loaded image with the appropriate permissions708* for code and data709*710* @image_base: the base of the image in memory711* @alloc_size: the size of the area in memory occupied by the image712* @code_size: the size of the leading part of the image containing code713* and read-only data714*715* efi_remap_image() uses the EFI memory attribute protocol to remap the code716* region of the loaded image read-only/executable, and the remainder717* read-write/non-executable. The code region is assumed to start at the base718* of the image, and will therefore cover the PE/COFF header as well.719*/720void efi_remap_image(unsigned long image_base, unsigned alloc_size,721unsigned long code_size)722{723efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;724efi_memory_attribute_protocol_t *memattr;725efi_status_t status;726u64 attr;727728/*729* If the firmware implements the EFI_MEMORY_ATTRIBUTE_PROTOCOL, let's730* invoke it to remap the text/rodata region of the decompressed image731* as read-only and the data/bss region as non-executable.732*/733status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&memattr);734if (status != EFI_SUCCESS)735return;736737// Get the current attributes for the entire region738status = memattr->get_memory_attributes(memattr, image_base,739alloc_size, &attr);740if (status != EFI_SUCCESS) {741efi_warn("Failed to retrieve memory attributes for image region: 0x%lx\n",742status);743return;744}745746// Mark the code region as read-only747status = memattr->set_memory_attributes(memattr, image_base, code_size,748EFI_MEMORY_RO);749if (status != EFI_SUCCESS) {750efi_warn("Failed to remap code region read-only\n");751return;752}753754// If the entire region was already mapped as non-exec, clear the755// attribute from the code region. Otherwise, set it on the data756// region.757if (attr & EFI_MEMORY_XP) {758status = memattr->clear_memory_attributes(memattr, image_base,759code_size,760EFI_MEMORY_XP);761if (status != EFI_SUCCESS)762efi_warn("Failed to remap code region executable\n");763} else {764status = memattr->set_memory_attributes(memattr,765image_base + code_size,766alloc_size - code_size,767EFI_MEMORY_XP);768if (status != EFI_SUCCESS)769efi_warn("Failed to remap data region non-executable\n");770}771}772773774