Received: by 10.192.165.148 with SMTP id m20csp2597313imm; Sun, 29 Apr 2018 02:38:48 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqm8UOEPZ3Y6b/haj2P4+6++Ft1ERmxhvPjsX2pf4O/hy2rLj1VIueAdeChcRtchZrXDvba X-Received: by 2002:a17:902:407:: with SMTP id 7-v6mr8650205ple.47.1524994728430; Sun, 29 Apr 2018 02:38:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524994728; cv=none; d=google.com; s=arc-20160816; b=MigCMkG1lG/nCwiKEfC6kHs1Ceavx+UtS4Q9TkX3FYC+cDPogNArAIKopZDmB42WxB yH0dIFp/K86iBUN61I3h5sUX+FScpFRHIeN3w/uDvwCZxZKFYB+hLlpHvA3oZcVMug7T p5ktZ/kkPB9aAbfxiZBVYoTH4NTbKa6ln9lLHcEZjIxRL1c+NZ/m/FtDCWi2Vh6mhTCD GrBBVLi7LUYWqaKQ6yql7S5kT1P1yu81kAnNwiLAd8/Udog1PgeMyAVo4KRGYZWtZ75L cqYc0GcyVkM/AQYq9k+WiVlY/8oGGPyD+ASrm3cJc6JPNq8nfpHYhjf4CvOwI3ubBzuh 09Rg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=w/KcCpey6K2VwE8pCMUVVi6vOzABF8Tutxt7JAS/AWw=; b=mNRYxAD0YKno0VxrixHh5xZWnhCCLFw6uz+Wgipw6q61d4kMEqhFCQ26cK7tkbEKSd Tz97cbAzEQgnifmp6uq7diRftO6BhExUTjlryWOk0SVZJ90t44T6phFjzcvr0ClyWV/z ZHudau2kq4wN2BCArELrzyP9oNhWJEL7bb79RLteZfM8Do7r+UKgvZYnMDlL2qcevEPW vIyB16zgboYF4OvA6Y3FSZPVpPqQskrB8ZthOqilMiKOhYNQ4pDWtfs/IsBFJFLz14RO qcf+A8cWELJXjrJ3ZrGtJYvNNKGUNqwL9vSMCt1Hi+eQjAOkzS/EpVmPIOPdMzc11gnq +uIw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h27-v6si386731pgn.147.2018.04.29.02.38.34; Sun, 29 Apr 2018 02:38:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753405AbeD2JhM (ORCPT + 99 others); Sun, 29 Apr 2018 05:37:12 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:46488 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753024AbeD2JgM (ORCPT ); Sun, 29 Apr 2018 05:36:12 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EE055814F0A8; Sun, 29 Apr 2018 09:36:10 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-27.ams2.redhat.com [10.36.116.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 997882166BAD; Sun, 29 Apr 2018 09:36:07 +0000 (UTC) From: Hans de Goede To: Ard Biesheuvel , "Luis R . Rodriguez" , Greg Kroah-Hartman , Thomas Gleixner , Ingo Molnar , "H . Peter Anvin" Cc: Hans de Goede , Peter Jones , Dave Olsthoorn , Will Deacon , Andy Lutomirski , Matt Fleming , David Howells , Mimi Zohar , Josh Triplett , dmitry.torokhov@gmail.com, mfuzzey@parkeon.com, Kalle Valo , Arend Van Spriel , Linus Torvalds , nbroeking@me.com, bjorn.andersson@linaro.org, Torsten Duwe , Kees Cook , x86@kernel.org, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 2/5] efi: Add embedded peripheral firmware support Date: Sun, 29 Apr 2018 11:35:55 +0200 Message-Id: <20180429093558.5411-3-hdegoede@redhat.com> In-Reply-To: <20180429093558.5411-1-hdegoede@redhat.com> References: <20180429093558.5411-1-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sun, 29 Apr 2018 09:36:12 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sun, 29 Apr 2018 09:36:12 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'hdegoede@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Just like with PCI options ROMs, which we save in the setup_efi_pci* functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself sometimes may contain data which is useful/necessary for peripheral drivers to have access to. Specifically the EFI code may contain an embedded copy of firmware which needs to be (re)loaded into the peripheral. Normally such firmware would be part of linux-firmware, but in some cases this is not feasible, for 2 reasons: 1) The firmware is customized for a specific use-case of the chipset / use with a specific hardware model, so we cannot have a single firmware file for the chipset. E.g. touchscreen controller firmwares are compiled specifically for the hardware model they are used with, as they are calibrated for a specific model digitizer. 2) Despite repeated attempts we have failed to get permission to redistribute the firmware. This is especially a problem with customized firmwares, these get created by the chip vendor for a specific ODM and the copyright may partially belong with the ODM, so the chip vendor cannot give a blanket permission to distribute these. This commit adds support for finding peripheral firmware embedded in the EFI code and making this available to peripheral drivers through the standard firmware loading mechanism. Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end of start_kernel(), just before calling rest_init(), this is on purpose because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for early_memremap(), so the check must be done after mm_init(). This relies on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services() is called, which means that this will only work on x86 for now. Reported-by: Dave Olsthoorn Suggested-by: Peter Jones Acked-by: Ard Biesheuvel Signed-off-by: Hans de Goede --- Changes in v5: -Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS Changes in v4: -Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of UEFI proper, so the EFI maintainers don't want us referring people to it -Use new EFI_BOOT_SERVICES flag -Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c file which only gets built when EFI_EMBEDDED_FIRMWARE is selected -Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs in firmware_loader/main.c -Properly call security_kernel_post_read_file() on the firmware returned by efi_get_embedded_fw() to make sure that we are allowed to use it Changes in v3: -Fix the docs using "efi-embedded-fw" as property name instead of "efi-embedded-firmware" Changes in v2: -Rebased on driver-core/driver-core-next -Add documentation describing the EFI embedded firmware mechanism to: Documentation/driver-api/firmware/request_firmware.rst -Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded fw support if this is set. This is an invisible option which should be selected by drivers which need this -Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices from the efi-embedded-fw code, instead drivers using this are expected to export a dmi_system_id array, with each entries' driver_data pointing to a efi_embedded_fw_desc struct and register this with the efi-embedded-fw code -Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware, this avoids us messing with the EFI memmap and avoids the need to make changes to efi_mem_desc_lookup() -Make the firmware-loader code only fallback to efi_get_embedded_fw() if the passed in device has the "efi-embedded-firmware" device-property bool set -Skip usermodehelper fallback when "efi-embedded-firmware" device-property is set --- .../driver-api/firmware/request_firmware.rst | 66 ++++++++ drivers/base/firmware_loader/Makefile | 1 + drivers/base/firmware_loader/fallback.h | 12 ++ drivers/base/firmware_loader/fallback_efi.c | 51 ++++++ drivers/base/firmware_loader/main.c | 2 + drivers/firmware/efi/Kconfig | 3 + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/embedded-firmware.c | 149 ++++++++++++++++++ include/linux/efi.h | 6 + include/linux/efi_embedded_fw.h | 25 +++ init/main.c | 3 + 11 files changed, 319 insertions(+) create mode 100644 drivers/base/firmware_loader/fallback_efi.c create mode 100644 drivers/firmware/efi/embedded-firmware.c create mode 100644 include/linux/efi_embedded_fw.h diff --git a/Documentation/driver-api/firmware/request_firmware.rst b/Documentation/driver-api/firmware/request_firmware.rst index c8bddbdcfd10..560dfed76e38 100644 --- a/Documentation/driver-api/firmware/request_firmware.rst +++ b/Documentation/driver-api/firmware/request_firmware.rst @@ -73,3 +73,69 @@ If something went wrong firmware_request() returns non-zero and fw_entry is set to NULL. Once your driver is done with processing the firmware it can call call firmware_release(fw_entry) to release the firmware image and any related resource. + +EFI embedded firmware support +============================= + +On some devices the system's EFI code / ROM may contain an embedded copy +of firmware for some of the system's integrated peripheral devices and +the peripheral's Linux device-driver needs to access this firmware. + +A device driver which needs this can describe the firmware it needs +using an efi_embedded_fw_desc struct: + +.. kernel-doc:: include/linux/efi_embedded_fw.h + :functions: efi_embedded_fw_desc + +The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory +segments for an eight byte sequence matching prefix, if the prefix is found it +then does a crc32 over length bytes and if that matches makes a copy of length +bytes and adds that to its list with found firmwares. + +To avoid doing this somewhat expensive scan on all systems, dmi matching is +used. Drivers are expected to export a dmi_system_id array, with each entries' +driver_data pointing to an efi_embedded_fw_desc. + +To register this array with the efi-embedded-fw code, a driver needs to: + +1. Always be builtin to the kernel or store the dmi_system_id array in a + separate object file which always gets builtin. + +2. Add an extern declaration for the dmi_system_id array to + include/linux/efi_embedded_fw.h. + +3. Add the dmi_system_id array to the embedded_fw_table in + drivers/firmware/efi/embedded-firmware.c wrapped in a #ifdef testing that + the driver is being builtin. + +4. Add "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry. + +The request_firmware() function will always first try to load firmware with +the specified name directly from the disk, so the EFI embedded-fw can always +be overridden by placing a file under /lib/firmare. + +To make request_firmware() fallback to trying EFI embedded firmwares after this, +the driver must set a boolean "efi-embedded-firmware" device-property on the +device before passing it to request_firmware(). Note that this disables the +usual usermodehelper fallback, so you may want to only set this on systems +which match your dmi_system_id array. + +Once the device-property is set, the driver can use the regular +request_firmware() function to get the firmware, using the name filled in +in the efi_embedded_fw_desc. + +Note that: + +1. The code scanning for EFI embbedded-firmware runs near the end + of start_kernel(), just before calling rest_init(). For normal drivers and + subsystems using subsys_initcall() to register themselves this does not + matter. This means that code running earlier cannot use EFI + embbedded-firmware. + +2. ATM the EFI embedded-fw code assumes that firmwares always start at an offset + which is a multiple of 8 bytes, if this is not true for your case send in + a patch to fix this. + +3. ATM the EFI embedded-fw code only works on x86 because other archs free + EFI_BOOT_SERVICES_CODE before the EFI embedded-fw code gets a chance to + scan it. diff --git a/drivers/base/firmware_loader/Makefile b/drivers/base/firmware_loader/Makefile index a97eeb0be1d8..365a040995d3 100644 --- a/drivers/base/firmware_loader/Makefile +++ b/drivers/base/firmware_loader/Makefile @@ -5,3 +5,4 @@ obj-y := fallback_table.o obj-$(CONFIG_FW_LOADER) += firmware_class.o firmware_class-objs := main.o firmware_class-$(CONFIG_FW_LOADER_USER_HELPER) += fallback.o +firmware_class-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += fallback_efi.o diff --git a/drivers/base/firmware_loader/fallback.h b/drivers/base/firmware_loader/fallback.h index 8cfaa3299bb7..92f462415d25 100644 --- a/drivers/base/firmware_loader/fallback.h +++ b/drivers/base/firmware_loader/fallback.h @@ -66,4 +66,16 @@ static inline void unregister_sysfs_loader(void) } #endif /* CONFIG_FW_LOADER_USER_HELPER */ +#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE +int fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, + enum fw_opt *opt_flags, int ret); +#else +static inline int fw_get_efi_embedded_fw(struct device *dev, + struct fw_priv *fw_priv, + enum fw_opt *opt_flags, int ret) +{ + return ret; +} +#endif /* CONFIG_EFI_EMBEDDED_FIRMWARE */ + #endif /* __FIRMWARE_FALLBACK_H */ diff --git a/drivers/base/firmware_loader/fallback_efi.c b/drivers/base/firmware_loader/fallback_efi.c new file mode 100644 index 000000000000..82ba82f48a79 --- /dev/null +++ b/drivers/base/firmware_loader/fallback_efi.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#include "fallback.h" +#include "firmware.h" + +int fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, + enum fw_opt *opt_flags, int ret) +{ + enum kernel_read_file_id id = READING_FIRMWARE; + size_t size, max = INT_MAX; + int rc; + + if (!dev) + return ret; + + if (!device_property_read_bool(dev, "efi-embedded-firmware")) + return ret; + + *opt_flags |= FW_OPT_NO_WARN | FW_OPT_NOCACHE | FW_OPT_NOFALLBACK; + + /* Already populated data member means we're loading into a buffer */ + if (fw_priv->data) { + id = READING_FIRMWARE_PREALLOC_BUFFER; + max = fw_priv->allocated_size; + } + + rc = efi_get_embedded_fw(fw_priv->fw_name, &fw_priv->data, &size, max); + if (rc) { + dev_warn(dev, "Firmware %s not in EFI\n", fw_priv->fw_name); + return ret; + } + + rc = security_kernel_post_read_file(NULL, fw_priv->data, size, id); + if (rc) { + if (id != READING_FIRMWARE_PREALLOC_BUFFER) { + vfree(fw_priv->data); + fw_priv->data = NULL; + } + return rc; + } + + dev_dbg(dev, "using efi-embedded fw %s\n", fw_priv->fw_name); + fw_priv->size = size; + fw_state_done(fw_priv); + return 0; +} diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index f009566acd35..23c5392eb59e 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -576,6 +576,8 @@ _firmware_request(const struct firmware **firmware_p, const char *name, goto out; ret = fw_get_filesystem_firmware(device, fw->priv); + if (ret) + ret = fw_get_efi_embedded_fw(device, fw->priv, &opt_flags, ret); if (ret) { if (!(opt_flags & FW_OPT_NO_WARN)) dev_warn(device, diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 3098410abad8..faefeff7fb34 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -164,6 +164,9 @@ config RESET_ATTACK_MITIGATION have been evicted, since otherwise it will trigger even on clean reboots. +config EFI_EMBEDDED_FIRMWARE + bool + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index cb805374f4bc..dde12cea8aac 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o obj-$(CONFIG_EFI_TEST) += test/ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o +obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) diff --git a/drivers/firmware/efi/embedded-firmware.c b/drivers/firmware/efi/embedded-firmware.c new file mode 100644 index 000000000000..22a0f598b53d --- /dev/null +++ b/drivers/firmware/efi/embedded-firmware.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for extracting embedded firmware for peripherals from EFI code, + * + * Copyright (c) 2018 Hans de Goede + */ + +#include +#include +#include +#include +#include +#include +#include + +struct embedded_fw { + struct list_head list; + const char *name; + void *data; + size_t length; +}; + +static LIST_HEAD(found_fw_list); + +static const struct dmi_system_id * const embedded_fw_table[] = { + NULL +}; + +/* + * Note the efi_check_for_embedded_firmwares() code currently makes the + * following 2 assumptions. This may needs to be revisited if embedded firmware + * is found where this is not true: + * 1) The firmware is only found in EFI_BOOT_SERVICES_CODE memory segments + * 2) The firmware always starts at an offset which is a multiple of 8 bytes + */ +static int __init efi_check_md_for_embedded_firmware( + efi_memory_desc_t *md, const struct efi_embedded_fw_desc *desc) +{ + struct embedded_fw *fw; + u64 i, size; + u32 crc; + u8 *mem; + + size = md->num_pages << EFI_PAGE_SHIFT; + mem = memremap(md->phys_addr, size, MEMREMAP_WB); + if (!mem) { + pr_err("Error mapping EFI mem at %#llx\n", md->phys_addr); + return -ENOMEM; + } + + size -= desc->length; + for (i = 0; i < size; i += 8) { + if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix)) + continue; + + /* Seed with ~0, invert to match crc32 userspace utility */ + crc = ~crc32(~0, mem + i, desc->length); + if (crc == desc->crc) + break; + } + + memunmap(mem); + + if (i >= size) + return -ENOENT; + + pr_info("Found EFI embedded fw '%s' crc %08x\n", desc->name, desc->crc); + + fw = kmalloc(sizeof(*fw), GFP_KERNEL); + if (!fw) + return -ENOMEM; + + mem = memremap(md->phys_addr + i, desc->length, MEMREMAP_WB); + if (!mem) { + pr_err("Error mapping embedded firmware\n"); + goto error_free_fw; + } + fw->data = kmemdup(mem, desc->length, GFP_KERNEL); + memunmap(mem); + if (!fw->data) + goto error_free_fw; + + fw->name = desc->name; + fw->length = desc->length; + list_add(&fw->list, &found_fw_list); + + return 0; + +error_free_fw: + kfree(fw); + return -ENOMEM; +} + +void __init efi_check_for_embedded_firmwares(void) +{ + const struct efi_embedded_fw_desc *fw_desc; + const struct dmi_system_id *dmi_id; + efi_memory_desc_t *md; + int i, r; + + for (i = 0; embedded_fw_table[i]; i++) { + dmi_id = dmi_first_match(embedded_fw_table[i]); + if (!dmi_id) + continue; + + fw_desc = dmi_id->driver_data; + for_each_efi_memory_desc(md) { + if (md->type != EFI_BOOT_SERVICES_CODE) + continue; + + r = efi_check_md_for_embedded_firmware(md, fw_desc); + if (r == 0) + break; + } + } +} + +int efi_get_embedded_fw(const char *name, void **data, size_t *size, + size_t msize) +{ + struct embedded_fw *iter, *fw = NULL; + void *buf = *data; + + list_for_each_entry(iter, &found_fw_list, list) { + if (strcmp(name, iter->name) == 0) { + fw = iter; + break; + } + } + + if (!fw) + return -ENOENT; + + if (msize && msize < fw->length) + return -EFBIG; + + if (!buf) { + buf = vmalloc(fw->length); + if (!buf) + return -ENOMEM; + } + + memcpy(buf, fw->data, fw->length); + *size = fw->length; + *data = buf; + + return 0; +} +EXPORT_SYMBOL_GPL(efi_get_embedded_fw); diff --git a/include/linux/efi.h b/include/linux/efi.h index 791088360c1e..23e8a9c26ce2 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1575,6 +1575,12 @@ static inline void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { } #endif +#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE +void efi_check_for_embedded_firmwares(void); +#else +static inline void efi_check_for_embedded_firmwares(void) { } +#endif + void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table); /* diff --git a/include/linux/efi_embedded_fw.h b/include/linux/efi_embedded_fw.h new file mode 100644 index 000000000000..0f7d4df3f57a --- /dev/null +++ b/include/linux/efi_embedded_fw.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_EFI_EMBEDDED_FW_H +#define _LINUX_EFI_EMBEDDED_FW_H + +#include + +/** + * struct efi_embedded_fw_desc - This struct is used by the EFI embedded-fw + * code to search for embedded firmwares. + * + * @name: Name to register the firmware with if found + * @prefix: First 8 bytes of the firmware + * @length: Length of the firmware in bytes including prefix + * @crc: Inverted little endian Ethernet style CRC32, with 0xffffffff seed + */ +struct efi_embedded_fw_desc { + const char *name; + u8 prefix[8]; + u32 length; + u32 crc; +}; + +int efi_get_embedded_fw(const char *name, void **dat, size_t *sz, size_t msize); + +#endif diff --git a/init/main.c b/init/main.c index b795aa341a3a..ab29775b35db 100644 --- a/init/main.c +++ b/init/main.c @@ -729,6 +729,9 @@ asmlinkage __visible void __init start_kernel(void) arch_post_acpi_subsys_init(); sfi_init_late(); + if (efi_enabled(EFI_PRESERVE_BS_REGIONS)) + efi_check_for_embedded_firmwares(); + if (efi_enabled(EFI_RUNTIME_SERVICES)) { efi_free_boot_services(); } -- 2.17.0