History

Merge tag 'efi-next' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi into efi/core

More EFI updates for v5.7 - Incorporate a stable branch with the EFI pieces of Hans's work on loading device firmware from EFI boot service memory regions

Ingo Molnar committed 6 years ago

Commit 3be5f0d2 parents c98a76e f0df68d8 files · +264 −0Browse files

Unified · Split

8 files
  1. arch/x86/platform/efi/efi.c +2 −0
  2. arch/x86/platform/efi/quirks.c +4 −0
  3. drivers/firmware/efi/Kconfig +5 −0
  4. drivers/firmware/efi/Makefile +1 −0
  5. drivers/firmware/efi/efi.c +57 −0
  6. drivers/firmware/efi/embedded-firmware.c +147 −0
  7. include/linux/efi.h +7 −0
  8. include/linux/efi_embedded_fw.h +41 −0
arch/x86/platform/efi/efi.c+2−0
@@ -246,6 +246,7 @@ int __init efi_memblock_x86_reserve_range(void) · 245 unmodified lines
246246 efi.memmap.desc_version);
247247
248248 memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
249+ set_bit(EFI_PRESERVE_BS_REGIONS, &efi.flags);
249250
250251 return 0;
251252 }
@@ -901,6 +902,7 @@ static void __init __efi_enter_virtual_mode(void) · 649 unmodified lines
901902 goto err;
902903 }
903904
905+ efi_check_for_embedded_firmwares();
904906 efi_free_boot_services();
905907
906908 if (!efi_is_mixed())
arch/x86/platform/efi/quirks.c+4−0
@@ -410,6 +410,10 @@ void __init efi_free_boot_services(void) · 409 unmodified lines
410410 int num_entries = 0;
411411 void *new, *new_md;
412412
413+ /* Keep all regions for /sys/kernel/debug/efi */
414+ if (efi_enabled(EFI_DBG))
415+ return;
416+
413417 for_each_efi_memory_desc(md) {
414418 unsigned long long start = md->phys_addr;
415419 unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
drivers/firmware/efi/Kconfig+5−0
@@ -239,6 +239,11 @@ config EFI_DISABLE_PCI_DMA · 238 unmodified lines
239239
240240 endmenu
241241
242+config EFI_EMBEDDED_FIRMWARE
243+ bool
244+ depends on EFI
245+ select CRYPTO_LIB_SHA256
246+
242247 config UEFI_CPER
243248 bool
244249
drivers/firmware/efi/Makefile+1−0
@@ -27,6 +27,7 @@ obj-$(CONFIG_EFI_TEST) += test/ · 26 unmodified lines
2727 obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
2828 obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
2929 obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
30+obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
3031
3132 fake_map-y += fake_mem.o
3233 fake_map-$(CONFIG_X86) += x86_fake_mem.o
drivers/firmware/efi/efi.c+57−0
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include <linux/kobject.h>
1818 #include <linux/module.h>
1919 #include <linux/init.h>
20+#include <linux/debugfs.h>
2021 #include <linux/device.h>
2122 #include <linux/efi.h>
2223 #include <linux/of.h>
@@ -291,6 +292,59 @@ free_entry: · 268 unmodified lines
291292 static inline int efivar_ssdt_load(void) { return 0; }
292293 #endif
293294
295+#ifdef CONFIG_DEBUG_FS
296+
297+#define EFI_DEBUGFS_MAX_BLOBS 32
298+
299+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
300+
301+static void __init efi_debugfs_init(void)
302+{
303+ struct dentry *efi_debugfs;
304+ efi_memory_desc_t *md;
305+ char name[32];
306+ int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
307+ int i = 0;
308+
309+ efi_debugfs = debugfs_create_dir("efi", NULL);
310+ if (IS_ERR_OR_NULL(efi_debugfs))
311+ return;
312+
313+ for_each_efi_memory_desc(md) {
314+ switch (md->type) {
315+ case EFI_BOOT_SERVICES_CODE:
316+ snprintf(name, sizeof(name), "boot_services_code%d",
317+ type_count[md->type]++);
318+ break;
319+ case EFI_BOOT_SERVICES_DATA:
320+ snprintf(name, sizeof(name), "boot_services_data%d",
321+ type_count[md->type]++);
322+ break;
323+ default:
324+ continue;
325+ }
326+
327+ if (i >= EFI_DEBUGFS_MAX_BLOBS) {
328+ pr_warn("More then %d EFI boot service segments, only showing first %d in debugfs\n",
329+ EFI_DEBUGFS_MAX_BLOBS, EFI_DEBUGFS_MAX_BLOBS);
330+ break;
331+ }
332+
333+ debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
334+ debugfs_blob[i].data = memremap(md->phys_addr,
335+ debugfs_blob[i].size,
336+ MEMREMAP_WB);
337+ if (!debugfs_blob[i].data)
338+ continue;
339+
340+ debugfs_create_blob(name, 0400, efi_debugfs, &debugfs_blob[i]);
341+ i++;
342+ }
343+}
344+#else
345+static inline void efi_debugfs_init(void) {}
346+#endif
347+
294348 /*
295349 * We register the efi subsystem with the firmware subsystem and the
296350 * efivars subsystem with the efi subsystem, if the system was booted with
@@ -357,6 +411,9 @@ static int __init efisubsys_init(void) · 60 unmodified lines
357411 goto err_remove_group;
358412 }
359413
414+ if (efi_enabled(EFI_DBG) && efi_enabled(EFI_PRESERVE_BS_REGIONS))
415+ efi_debugfs_init();
416+
360417 return 0;
361418
362419 err_remove_group:
drivers/firmware/efi/embedded-firmware.c+147−0
@@ -0,0 +1,147 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Support for extracting embedded firmware for peripherals from EFI code,
4+ *
5+ * Copyright (c) 2018 Hans de Goede <hdegoede@redhat.com>
6+ */
7+
8+#include <linux/dmi.h>
9+#include <linux/efi.h>
10+#include <linux/efi_embedded_fw.h>
11+#include <linux/io.h>
12+#include <linux/slab.h>
13+#include <linux/types.h>
14+#include <linux/vmalloc.h>
15+#include <crypto/sha.h>
16+
17+/* Exported for use by lib/test_firmware.c only */
18+LIST_HEAD(efi_embedded_fw_list);
19+EXPORT_SYMBOL_GPL(efi_embedded_fw_list);
20+
21+static bool checked_for_fw;
22+
23+static const struct dmi_system_id * const embedded_fw_table[] = {
24+ NULL
25+};
26+
27+/*
28+ * Note the efi_check_for_embedded_firmwares() code currently makes the
29+ * following 2 assumptions. This may needs to be revisited if embedded firmware
30+ * is found where this is not true:
31+ * 1) The firmware is only found in EFI_BOOT_SERVICES_CODE memory segments
32+ * 2) The firmware always starts at an offset which is a multiple of 8 bytes
33+ */
34+static int __init efi_check_md_for_embedded_firmware(
35+ efi_memory_desc_t *md, const struct efi_embedded_fw_desc *desc)
36+{
37+ struct sha256_state sctx;
38+ struct efi_embedded_fw *fw;
39+ u8 sha256[32];
40+ u64 i, size;
41+ u8 *map;
42+
43+ size = md->num_pages << EFI_PAGE_SHIFT;
44+ map = memremap(md->phys_addr, size, MEMREMAP_WB);
45+ if (!map) {
46+ pr_err("Error mapping EFI mem at %#llx\n", md->phys_addr);
47+ return -ENOMEM;
48+ }
49+
50+ for (i = 0; (i + desc->length) <= size; i += 8) {
51+ if (memcmp(map + i, desc->prefix, EFI_EMBEDDED_FW_PREFIX_LEN))
52+ continue;
53+
54+ sha256_init(&sctx);
55+ sha256_update(&sctx, map + i, desc->length);
56+ sha256_final(&sctx, sha256);
57+ if (memcmp(sha256, desc->sha256, 32) == 0)
58+ break;
59+ }
60+ if ((i + desc->length) > size) {
61+ memunmap(map);
62+ return -ENOENT;
63+ }
64+
65+ pr_info("Found EFI embedded fw '%s'\n", desc->name);
66+
67+ fw = kmalloc(sizeof(*fw), GFP_KERNEL);
68+ if (!fw) {
69+ memunmap(map);
70+ return -ENOMEM;
71+ }
72+
73+ fw->data = kmemdup(map + i, desc->length, GFP_KERNEL);
74+ memunmap(map);
75+ if (!fw->data) {
76+ kfree(fw);
77+ return -ENOMEM;
78+ }
79+
80+ fw->name = desc->name;
81+ fw->length = desc->length;
82+ list_add(&fw->list, &efi_embedded_fw_list);
83+
84+ return 0;
85+}
86+
87+void __init efi_check_for_embedded_firmwares(void)
88+{
89+ const struct efi_embedded_fw_desc *fw_desc;
90+ const struct dmi_system_id *dmi_id;
91+ efi_memory_desc_t *md;
92+ int i, r;
93+
94+ for (i = 0; embedded_fw_table[i]; i++) {
95+ dmi_id = dmi_first_match(embedded_fw_table[i]);
96+ if (!dmi_id)
97+ continue;
98+
99+ fw_desc = dmi_id->driver_data;
100+
101+ /*
102+ * In some drivers the struct driver_data contains may contain
103+ * other driver specific data after the fw_desc struct; and
104+ * the fw_desc struct itself may be empty, skip these.
105+ */
106+ if (!fw_desc->name)
107+ continue;
108+
109+ for_each_efi_memory_desc(md) {
110+ if (md->type != EFI_BOOT_SERVICES_CODE)
111+ continue;
112+
113+ r = efi_check_md_for_embedded_firmware(md, fw_desc);
114+ if (r == 0)
115+ break;
116+ }
117+ }
118+
119+ checked_for_fw = true;
120+}
121+
122+int efi_get_embedded_fw(const char *name, const u8 **data, size_t *size)
123+{
124+ struct efi_embedded_fw *iter, *fw = NULL;
125+
126+ if (!checked_for_fw) {
127+ pr_warn("Warning %s called while we did not check for embedded fw\n",
128+ __func__);
129+ return -ENOENT;
130+ }
131+
132+ list_for_each_entry(iter, &efi_embedded_fw_list, list) {
133+ if (strcmp(name, iter->name) == 0) {
134+ fw = iter;
135+ break;
136+ }
137+ }
138+
139+ if (!fw)
140+ return -ENOENT;
141+
142+ *data = fw->data;
143+ *size = fw->length;
144+
145+ return 0;
146+}
147+EXPORT_SYMBOL_GPL(efi_get_embedded_fw);
include/linux/efi.h+7−0
@@ -775,6 +775,7 @@ extern int __init efi_setup_pcdp_console(char *); · 774 unmodified lines
775775 #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */
776776 #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
777777 #define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */
778+#define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */
778779
779780 #ifdef CONFIG_EFI
780781 /*
@@ -1097,6 +1098,12 @@ static inline void · 316 unmodified lines
10971098 efi_enable_reset_attack_mitigation(void) { }
10981099 #endif
10991100
1101+#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
1102+void efi_check_for_embedded_firmwares(void);
1103+#else
1104+static inline void efi_check_for_embedded_firmwares(void) { }
1105+#endif
1106+
11001107 efi_status_t efi_random_get_seed(void);
11011108
11021109 void efi_retrieve_tpm2_eventlog(void);
include/linux/efi_embedded_fw.h+41−0
@@ -0,0 +1,41 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+#ifndef _LINUX_EFI_EMBEDDED_FW_H
3+#define _LINUX_EFI_EMBEDDED_FW_H
4+
5+#include <linux/list.h>
6+#include <linux/mod_devicetable.h>
7+
8+#define EFI_EMBEDDED_FW_PREFIX_LEN 8
9+
10+/*
11+ * This struct and efi_embedded_fw_list are private to the efi-embedded fw
12+ * implementation they are in this header for use by lib/test_firmware.c only!
13+ */
14+struct efi_embedded_fw {
15+ struct list_head list;
16+ const char *name;
17+ const u8 *data;
18+ size_t length;
19+};
20+
21+extern struct list_head efi_embedded_fw_list;
22+
23+/**
24+ * struct efi_embedded_fw_desc - This struct is used by the EFI embedded-fw
25+ * code to search for embedded firmwares.
26+ *
27+ * @name: Name to register the firmware with if found
28+ * @prefix: First 8 bytes of the firmware
29+ * @length: Length of the firmware in bytes including prefix
30+ * @sha256: SHA256 of the firmware
31+ */
32+struct efi_embedded_fw_desc {
33+ const char *name;
34+ u8 prefix[EFI_EMBEDDED_FW_PREFIX_LEN];
35+ u32 length;
36+ u8 sha256[32];
37+};
38+
39+int efi_get_embedded_fw(const char *name, const u8 **dat, size_t *sz);
40+
41+#endif