From 5de0fef0230f3c8d75cff450a71740a7bf2db866 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 2 Feb 2019 10:41:12 +0100 Subject: efi/memattr: Don't bail on zero VA if it equals the region's PA The EFI memory attributes code cross-references the EFI memory map with the more granular EFI memory attributes table to ensure that they are in sync before applying the strict permissions to the regions it describes. Since we always install virtual mappings for the EFI runtime regions to which these strict permissions apply, we currently perform a sanity check on the EFI memory descriptor, and ensure that the EFI_MEMORY_RUNTIME bit is set, and that the virtual address has been assigned. However, in cases where a runtime region exists at physical address 0x0, and the virtual mapping equals the physical mapping, e.g., when running in mixed mode on x86, we encounter a memory descriptor with the runtime attribute and virtual address 0x0, and incorrectly draw the conclusion that a runtime region exists for which no virtual mapping was installed, and give up altogether. The consequence of this is that firmware mappings retain their read-write-execute permissions, making the system more vulnerable to attacks. So let's only bail if the virtual address of 0x0 has been assigned to a physical region that does not reside at address 0x0. Signed-off-by: Ard Biesheuvel Acked-by: Sai Praneeth Prakhya Cc: AKASHI Takahiro Cc: Alexander Graf Cc: Bjorn Andersson Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Jeffrey Hugo Cc: Lee Jones Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 10f0d2f577053 ("efi: Implement generic support for the Memory ...") Link: http://lkml.kernel.org/r/20190202094119.13230-4-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/memattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c index 8986757eafaf..aac972b056d9 100644 --- a/drivers/firmware/efi/memattr.c +++ b/drivers/firmware/efi/memattr.c @@ -94,7 +94,7 @@ static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out) if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; - if (md->virt_addr == 0) { + if (md->virt_addr == 0 && md->phys_addr != 0) { /* no virtual mapping has been installed by the stub */ break; } -- cgit From ac9aff8ef99095b9d46d53d0a779f2bda24ba181 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 2 Feb 2019 10:41:14 +0100 Subject: efi/fdt: Apply more cleanups Apply a number of cleanups: - Introduce fdt_setprop_*var() helper macros to simplify and shorten repetitive sequences - this also makes it less likely that the wrong variable size is passed in. This change makes a lot of the property-setting calls single-line and easier to read. - Harmonize comment style: capitalization, punctuation, whitespaces, etc. - Fix some whitespace noise in the libstub Makefile which I happened to notice. - Use the standard tabular initialization style: - map.map = &runtime_map; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver = &desc_ver; - map.key_ptr = &mmap_key; - map.buff_size = &buff_size; + map.map = &runtime_map; + map.map_size = &map_size; + map.desc_size = &desc_size; + map.desc_ver = &desc_ver; + map.key_ptr = &mmap_key; + map.buff_size = &buff_size; - Use tabular structure definition for better readability. - Make all pr*() lines single-line, even if they marginally exceed 80 cols - this makes them visually less intrusive. - Unbreak line breaks into single lines when the length exceeds 80 cols only marginally, for better readability. - Move assignment closer to the actual usage site. - Plus some other smaller cleanups, spelling fixes, etc. No change in functionality intended. [ ardb: move changes to upstream libfdt into local header. ] Signed-off-by: Ingo Molnar Signed-off-by: Ard Biesheuvel Cc: AKASHI Takahiro Cc: Alexander Graf Cc: Bjorn Andersson Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Jeffrey Hugo Cc: Lee Jones Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190202094119.13230-6-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/Makefile | 4 +- drivers/firmware/efi/libstub/efistub.h | 11 ++++ drivers/firmware/efi/libstub/fdt.c | 107 ++++++++++++++++----------------- 3 files changed, 64 insertions(+), 58 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index d9845099635e..b0103e16fc1b 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -52,7 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o -CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) # # arm64 puts the stub in the kernel proper, which will unnecessarily retain all @@ -89,7 +89,7 @@ quiet_cmd_stubcopy = STUBCPY $@ cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \ then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \ then (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ - rm -f $@; /bin/false); \ + rm -f $@; /bin/false); \ else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi \ else /bin/false; fi diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 32799cf039ef..cefcf6ba3150 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -64,4 +64,15 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg); efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg); +/* Helper macros for the usual case of using simple C variables: */ +#ifndef fdt_setprop_inplace_var +#define fdt_setprop_inplace_var(fdt, node_offset, name, var) \ + fdt_setprop_inplace((fdt), (node_offset), (name), &(var), sizeof(var)) +#endif + +#ifndef fdt_setprop_var +#define fdt_setprop_var(fdt, node_offset, name, var) \ + fdt_setprop((fdt), (node_offset), (name), &(var), sizeof(var)) +#endif + #endif diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 0dc7b4987cc2..d474964b873b 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -26,10 +26,8 @@ static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt) offset = fdt_path_offset(fdt, "/"); /* Set the #address-cells and #size-cells values for an empty tree */ - fdt_setprop_u32(fdt, offset, "#address-cells", - EFI_DT_ADDR_CELLS_DEFAULT); - - fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT); + fdt_setprop_u32(fdt, offset, "#address-cells", EFI_DT_ADDR_CELLS_DEFAULT); + fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT); } static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, @@ -42,7 +40,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, u32 fdt_val32; u64 fdt_val64; - /* Do some checks on provided FDT, if it exists*/ + /* Do some checks on provided FDT, if it exists: */ if (orig_fdt) { if (fdt_check_header(orig_fdt)) { pr_efi_err(sys_table, "Device Tree header not valid!\n"); @@ -50,7 +48,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, } /* * We don't get the size of the FDT if we get if from a - * configuration table. + * configuration table: */ if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { pr_efi_err(sys_table, "Truncated device tree! foo!\n"); @@ -64,8 +62,8 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, status = fdt_create_empty_tree(fdt, new_fdt_size); if (status == 0) { /* - * Any failure from the following function is non - * critical + * Any failure from the following function is + * non-critical: */ fdt_update_cell_size(sys_table, fdt); } @@ -86,12 +84,13 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, if (node < 0) { node = fdt_add_subnode(fdt, 0, "chosen"); if (node < 0) { - status = node; /* node is error code when negative */ + /* 'node' is an error code when negative: */ + status = node; goto fdt_set_fail; } } - if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) { + if (cmdline_ptr != NULL && strlen(cmdline_ptr) > 0) { status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, strlen(cmdline_ptr) + 1); if (status) @@ -103,13 +102,12 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, u64 initrd_image_end; u64 initrd_image_start = cpu_to_fdt64(initrd_addr); - status = fdt_setprop(fdt, node, "linux,initrd-start", - &initrd_image_start, sizeof(u64)); + status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start); if (status) goto fdt_set_fail; + initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); - status = fdt_setprop(fdt, node, "linux,initrd-end", - &initrd_image_end, sizeof(u64)); + status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end); if (status) goto fdt_set_fail; } @@ -117,30 +115,28 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, /* Add FDT entries for EFI runtime services in chosen node. */ node = fdt_subnode_offset(fdt, 0, "chosen"); fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); - status = fdt_setprop(fdt, node, "linux,uefi-system-table", - &fdt_val64, sizeof(fdt_val64)); + + status = fdt_setprop_var(fdt, node, "linux,uefi-system-table", fdt_val64); if (status) goto fdt_set_fail; fdt_val64 = U64_MAX; /* placeholder */ - status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", - &fdt_val64, sizeof(fdt_val64)); + + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64); if (status) goto fdt_set_fail; fdt_val32 = U32_MAX; /* placeholder */ - status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", - &fdt_val32, sizeof(fdt_val32)); + + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32); if (status) goto fdt_set_fail; - status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", - &fdt_val32, sizeof(fdt_val32)); + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32); if (status) goto fdt_set_fail; - status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", - &fdt_val32, sizeof(fdt_val32)); + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32); if (status) goto fdt_set_fail; @@ -150,8 +146,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64), (u8 *)&fdt_val64); if (efi_status == EFI_SUCCESS) { - status = fdt_setprop(fdt, node, "kaslr-seed", - &fdt_val64, sizeof(fdt_val64)); + status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64); if (status) goto fdt_set_fail; } else if (efi_status != EFI_NOT_FOUND) { @@ -159,7 +154,7 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, } } - /* shrink the FDT back to its minimum size */ + /* Shrink the FDT back to its minimum size: */ fdt_pack(fdt); return EFI_SUCCESS; @@ -182,26 +177,26 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map) return EFI_LOAD_ERROR; fdt_val64 = cpu_to_fdt64((unsigned long)*map->map); - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start", - &fdt_val64, sizeof(fdt_val64)); + + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64); if (err) return EFI_LOAD_ERROR; fdt_val32 = cpu_to_fdt32(*map->map_size); - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size", - &fdt_val32, sizeof(fdt_val32)); + + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32); if (err) return EFI_LOAD_ERROR; fdt_val32 = cpu_to_fdt32(*map->desc_size); - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size", - &fdt_val32, sizeof(fdt_val32)); + + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32); if (err) return EFI_LOAD_ERROR; fdt_val32 = cpu_to_fdt32(*map->desc_ver); - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver", - &fdt_val32, sizeof(fdt_val32)); + + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32); if (err) return EFI_LOAD_ERROR; @@ -209,13 +204,13 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map) } #ifndef EFI_FDT_ALIGN -#define EFI_FDT_ALIGN EFI_PAGE_SIZE +# define EFI_FDT_ALIGN EFI_PAGE_SIZE #endif struct exit_boot_struct { - efi_memory_desc_t *runtime_map; - int *runtime_entry_count; - void *new_fdt_addr; + efi_memory_desc_t *runtime_map; + int *runtime_entry_count; + void *new_fdt_addr; }; static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, @@ -235,7 +230,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, } #ifndef MAX_FDT_SIZE -#define MAX_FDT_SIZE SZ_2M +# define MAX_FDT_SIZE SZ_2M #endif /* @@ -266,16 +261,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, unsigned long mmap_key; efi_memory_desc_t *memory_map, *runtime_map; efi_status_t status; - int runtime_entry_count = 0; + int runtime_entry_count; struct efi_boot_memmap map; struct exit_boot_struct priv; - map.map = &runtime_map; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver = &desc_ver; - map.key_ptr = &mmap_key; - map.buff_size = &buff_size; + map.map = &runtime_map; + map.map_size = &map_size; + map.desc_size = &desc_size; + map.desc_ver = &desc_ver; + map.key_ptr = &mmap_key; + map.buff_size = &buff_size; /* * Get a copy of the current memory map that we will use to prepare @@ -289,15 +284,13 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, return status; } - pr_efi(sys_table, - "Exiting boot services and installing virtual address map...\n"); + pr_efi(sys_table, "Exiting boot services and installing virtual address map...\n"); map.map = &memory_map; status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN, new_fdt_addr, max_addr); if (status != EFI_SUCCESS) { - pr_efi_err(sys_table, - "Unable to allocate memory for new device tree.\n"); + pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n"); goto fail; } @@ -318,11 +311,12 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, goto fail_free_new_fdt; } - priv.runtime_map = runtime_map; - priv.runtime_entry_count = &runtime_entry_count; - priv.new_fdt_addr = (void *)*new_fdt_addr; - status = efi_exit_boot_services(sys_table, handle, &map, &priv, - exit_boot_func); + runtime_entry_count = 0; + priv.runtime_map = runtime_map; + priv.runtime_entry_count = &runtime_entry_count; + priv.new_fdt_addr = (void *)*new_fdt_addr; + + status = efi_exit_boot_services(sys_table, handle, &map, &priv, exit_boot_func); if (status == EFI_SUCCESS) { efi_set_virtual_address_map_t *svam; @@ -363,6 +357,7 @@ fail_free_new_fdt: fail: sys_table->boottime->free_pool(runtime_map); + return EFI_LOAD_ERROR; } -- cgit From 4febfb8dd08b6f8bafc19f3f9e382a477425b578 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 2 Feb 2019 10:41:15 +0100 Subject: efi: Replace GPL license boilerplate with SPDX headers Replace all GPL license blurbs with an equivalent SPDX header (most files are GPLv2, some are GPLv2+). While at it, drop some outdated header changelogs as well. Signed-off-by: Ard Biesheuvel Cc: AKASHI Takahiro Cc: Alexander Graf Cc: Bjorn Andersson Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Jeffrey Hugo Cc: Lee Jones Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190202094119.13230-7-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/apple-properties.c | 13 +----- drivers/firmware/efi/arm-init.c | 6 +-- drivers/firmware/efi/arm-runtime.c | 6 +-- drivers/firmware/efi/capsule-loader.c | 4 +- drivers/firmware/efi/capsule.c | 4 +- drivers/firmware/efi/cper-arm.c | 14 +------ drivers/firmware/efi/cper.c | 14 +------ drivers/firmware/efi/dev-path-parser.c | 9 +--- drivers/firmware/efi/efi-bgrt.c | 5 +-- drivers/firmware/efi/efi-pstore.c | 2 + drivers/firmware/efi/efibc.c | 10 +---- drivers/firmware/efi/efivars.c | 58 +------------------------- drivers/firmware/efi/esrt.c | 1 + drivers/firmware/efi/fake_mem.c | 16 +------ drivers/firmware/efi/libstub/arm32-stub.c | 6 +-- drivers/firmware/efi/libstub/arm64-stub.c | 6 +-- drivers/firmware/efi/libstub/efi-stub-helper.c | 5 +-- drivers/firmware/efi/libstub/fdt.c | 5 +-- drivers/firmware/efi/libstub/gop.c | 4 +- drivers/firmware/efi/libstub/random.c | 6 +-- drivers/firmware/efi/libstub/secureboot.c | 4 +- drivers/firmware/efi/libstub/tpm.c | 4 +- drivers/firmware/efi/memattr.c | 5 +-- drivers/firmware/efi/runtime-map.c | 3 +- drivers/firmware/efi/test/efi_test.c | 1 + drivers/firmware/efi/test/efi_test.h | 2 +- drivers/firmware/efi/tpm.c | 5 +-- drivers/firmware/efi/vars.c | 15 +------ 28 files changed, 29 insertions(+), 204 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c index ac1654f74dc7..0e206c9e0d7a 100644 --- a/drivers/firmware/efi/apple-properties.c +++ b/drivers/firmware/efi/apple-properties.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * apple-properties.c - EFI device properties on Macs * Copyright (C) 2016 Lukas Wunner * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * * Note, all properties are considered as u8 arrays. * To get a value of any of them the caller must use device_property_read_u8_array(). */ diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 1a6a77df8a5e..311cd349a862 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Extensible Firmware Interface * * Based on Extensible Firmware Interface Specification version 2.4 * * Copyright (C) 2013 - 2015 Linaro Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #define pr_fmt(fmt) "efi: " fmt diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 352bd2473162..f99995666f86 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Extensible Firmware Interface * * Based on Extensible Firmware Interface Specification version 2.4 * * Copyright (C) 2013, 2014 Linaro Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index 96688986da56..b1395133389e 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c @@ -1,10 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * EFI capsule loader driver. * * Copyright 2015 Intel Corporation - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. */ #define pr_fmt(fmt) "efi: " fmt diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c index 4938c29b7c5d..598b7800d14e 100644 --- a/drivers/firmware/efi/capsule.c +++ b/drivers/firmware/efi/capsule.c @@ -1,10 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * EFI capsule support. * * Copyright 2013 Intel Corporation; author Matt Fleming - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. */ #define pr_fmt(fmt) "efi: " fmt diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c index 502811344e81..36d3b8b9da47 100644 --- a/drivers/firmware/efi/cper-arm.c +++ b/drivers/firmware/efi/cper-arm.c @@ -1,20 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * UEFI Common Platform Error Record (CPER) support * * Copyright (C) 2017, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index a7902fccdcfa..6a966ecdd80a 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * UEFI Common Platform Error Record (CPER) support * @@ -9,19 +10,6 @@ * * For more information about CPER, please refer to Appendix N of UEFI * Specification version 2.4. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/firmware/efi/dev-path-parser.c b/drivers/firmware/efi/dev-path-parser.c index 85d1834ee9b7..85ec99f97841 100644 --- a/drivers/firmware/efi/dev-path-parser.c +++ b/drivers/firmware/efi/dev-path-parser.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dev-path-parser.c - EFI Device Path parser * Copyright (C) 2016 Lukas Wunner @@ -5,14 +6,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2) as * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . */ #include diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c index b22ccfb0c991..a2384184a7de 100644 --- a/drivers/firmware/efi/efi-bgrt.c +++ b/drivers/firmware/efi/efi-bgrt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2012 Intel Corporation * Author: Josh Triplett @@ -5,10 +6,6 @@ * Based on the bgrt driver: * Copyright 2012 Red Hat, Inc * Author: Matthew Garrett - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 0f7d97917197..9ea13e8d12ec 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ + #include #include #include diff --git a/drivers/firmware/efi/efibc.c b/drivers/firmware/efi/efibc.c index 503bbe2a9d49..61e099826cbb 100644 --- a/drivers/firmware/efi/efibc.c +++ b/drivers/firmware/efi/efibc.c @@ -1,15 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * efibc: control EFI bootloaders which obey LoaderEntryOneShot var * Copyright (c) 2013-2016, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #define pr_fmt(fmt) "efibc: " fmt diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 8061667a6765..7576450c8254 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Originally from efivars.c, * @@ -6,63 +7,6 @@ * * This code takes all variables accessible from EFI runtime and * exports them via sysfs - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Changelog: - * - * 17 May 2004 - Matt Domsch - * remove check for efi_enabled in exit - * add MODULE_VERSION - * - * 26 Apr 2004 - Matt Domsch - * minor bug fixes - * - * 21 Apr 2004 - Matt Tolentino - * fix locking per Peter Chubb's findings - * - * 25 Mar 2002 - Matt Domsch - * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_to_str() - * - * 12 Feb 2002 - Matt Domsch - * use list_for_each_safe when deleting vars. - * remove ifdef CONFIG_SMP around include - * v0.04 release to linux-ia64@linuxia64.org - * - * 20 April 2001 - Matt Domsch - * Moved vars from /proc/efi to /proc/efi/vars, and made - * efi.c own the /proc/efi directory. - * v0.03 release to linux-ia64@linuxia64.org - * - * 26 March 2001 - Matt Domsch - * At the request of Stephane, moved ownership of /proc/efi - * to efi.c, and now efivars lives under /proc/efi/vars. - * - * 12 March 2001 - Matt Domsch - * Feedback received from Stephane Eranian incorporated. - * efivar_write() checks copy_from_user() return value. - * efivar_read/write() returns proper errno. - * v0.02 release to linux-ia64@linuxia64.org - * - * 26 February 2001 - Matt Domsch - * v0.01 release to linux-ia64@linuxia64.org */ #include diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 5d06bd247d07..d6dd5f503fa2 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * esrt.c * diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c index 6c7d60c239b5..9501edc0fcfb 100644 --- a/drivers/firmware/efi/fake_mem.c +++ b/drivers/firmware/efi/fake_mem.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * fake_mem.c * @@ -8,21 +9,6 @@ * By specifying this parameter, you can add arbitrary attribute to * specific memory range by updating original (firmware provided) EFI * memmap. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, see . - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". */ #include diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index becbda445913..e8f7aefb6813 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2013 Linaro Ltd; - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include #include diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 1b4d465cc5d9..1550d244e996 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2013, 2014 Linaro Ltd; * * This file implements the EFI boot stub for the arm64 kernel. * Adapted from ARM version by Mark Salter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ /* diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index e94975f4655b..8f2d000bec75 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -1,13 +1,10 @@ +// 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 - * - * This file is part of the Linux kernel, and is made available - * under the terms of the GNU General Public License version 2. - * */ #include diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index d474964b873b..7cfc51935c4b 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * FDT related Helper functions used by the EFI stub on multiple * architectures. This should be #included by the EFI stub * implementation files. * * Copyright 2013 Linaro Limited; author Roy Franz - * - * This file is part of the Linux kernel, and is made available - * under the terms of the GNU General Public License version 2. - * */ #include diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c index 24c461dea7af..0101ca4c13b1 100644 --- a/drivers/firmware/efi/libstub/gop.c +++ b/drivers/firmware/efi/libstub/gop.c @@ -1,10 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* ----------------------------------------------------------------------- * * Copyright 2011 Intel Corporation; author Matt Fleming * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * * ----------------------------------------------------------------------- */ #include diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index e0e603a89aa9..b4b1d1dcb5fd 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2016 Linaro Ltd; - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c index 72d9dfbebf08..edba5e7a3743 100644 --- a/drivers/firmware/efi/libstub/secureboot.c +++ b/drivers/firmware/efi/libstub/secureboot.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Secure boot handling. * @@ -5,9 +6,6 @@ * Roy Franz - * - * This file is part of the Linux kernel, and is made available under the - * terms of the GNU General Public License version 2. */ #include #include diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c index a90b0b8fc69a..5bd04f75d8d6 100644 --- a/drivers/firmware/efi/libstub/tpm.c +++ b/drivers/firmware/efi/libstub/tpm.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * TPM handling. * @@ -5,9 +6,6 @@ * Copyright (C) 2017 Google, Inc. * Matthew Garrett * Thiebaud Weksteen - * - * This file is part of the Linux kernel, and is made available under the - * terms of the GNU General Public License version 2. */ #include #include diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c index aac972b056d9..58452fde92cc 100644 --- a/drivers/firmware/efi/memattr.c +++ b/drivers/firmware/efi/memattr.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2016 Linaro Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #define pr_fmt(fmt) "efi: memattr: " fmt diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c index 84a11d0a8023..ad9ddefc9dcb 100644 --- a/drivers/firmware/efi/runtime-map.c +++ b/drivers/firmware/efi/runtime-map.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * linux/drivers/efi/runtime-map.c * Copyright (C) 2013 Red Hat, Inc., Dave Young - * - * This file is released under the GPLv2. */ #include diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 51ecf7d6da48..877745c3aaf2 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * EFI Test Driver for Runtime Services * diff --git a/drivers/firmware/efi/test/efi_test.h b/drivers/firmware/efi/test/efi_test.h index 5f4818bf112f..f2446aa1c2e3 100644 --- a/drivers/firmware/efi/test/efi_test.h +++ b/drivers/firmware/efi/test/efi_test.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * EFI Test driver Header * diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c index 0cbeb3d46b18..3a689b40ccc0 100644 --- a/drivers/firmware/efi/tpm.c +++ b/drivers/firmware/efi/tpm.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017 Google, Inc. * Thiebaud Weksteen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index fceaafd67ec6..436d1776bc7b 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Originally from efivars.c * * Copyright (C) 2001,2003,2004 Dell * Copyright (C) 2004 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -- cgit From 4e46c2a956215482418d7b315749fb1b6c6bc224 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 2 Feb 2019 10:41:16 +0100 Subject: efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted The UEFI spec revision 2.7 errata A section 8.4 has the following to say about the virtual memory runtime services: "This section contains function definitions for the virtual memory support that may be optionally used by an operating system at runtime. If an operating system chooses to make EFI runtime service calls in a virtual addressing mode instead of the flat physical mode, then the operating system must use the services in this section to switch the EFI runtime services from flat physical addressing to virtual addressing." So it is pretty clear that calling SetVirtualAddressMap() is entirely optional, and so there is no point in doing so unless it achieves anything useful for us. This is not the case for 64-bit ARM. The identity mapping used by the firmware is arbitrarily converted into another permutation of userland addresses (i.e., bits [63:48] cleared), and the runtime code could easily deal with the original layout in exactly the same way as it deals with the converted layout. However, due to constraints related to page size differences if the OS is not running with 4k pages, and related to systems that may expose the individual sections of PE/COFF runtime modules as different memory regions, creating the virtual layout is a bit fiddly, and requires us to sort the memory map and reason about adjacent regions with identical memory types etc etc. So the obvious fix is to stop calling SetVirtualAddressMap() altogether on arm64 systems. However, to avoid surprises, which are notoriously hard to diagnose when it comes to OS<->firmware interactions, let's start by making it an opt-out feature, and implement support for the 'efi=novamap' kernel command line parameter on ARM and arm64 systems. ( Note that 32-bit ARM generally does require SetVirtualAddressMap() to be used, given that the physical memory map and the kernel virtual address map are not guaranteed to be non-overlapping like on arm64. However, having support for efi=novamap,noruntime on 32-bit ARM, combined with the recently proposed support for earlycon=efifb, is likely to be useful to diagnose boot issues on such systems if they have no accessible serial port. ) Tested-by: Jeffrey Hugo Tested-by: Bjorn Andersson Tested-by: Lee Jones Signed-off-by: Ard Biesheuvel Cc: AKASHI Takahiro Cc: Alexander Graf Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190202094119.13230-8-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/arm-stub.c | 5 +++++ drivers/firmware/efi/libstub/efi-stub-helper.c | 10 ++++++++++ drivers/firmware/efi/libstub/efistub.h | 1 + drivers/firmware/efi/libstub/fdt.c | 3 +++ 4 files changed, 19 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index eee42d5e25ee..626ec4b4a664 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -370,6 +370,11 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, paddr = in->phys_addr; size = in->num_pages * EFI_PAGE_SIZE; + if (novamap()) { + in->virt_addr = in->phys_addr; + continue; + } + /* * Make the mapping compatible with 64k pages: this allows * a 4k page size kernel to kexec a 64k page size kernel and diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 8f2d000bec75..e4610e72b78f 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -31,6 +31,7 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; static int __section(.data) __nokaslr; static int __section(.data) __quiet; +static int __section(.data) __novamap; int __pure nokaslr(void) { @@ -40,6 +41,10 @@ int __pure is_quiet(void) { return __quiet; } +int __pure novamap(void) +{ + return __novamap; +} #define EFI_MMAP_NR_SLACK_SLOTS 8 @@ -479,6 +484,11 @@ efi_status_t efi_parse_options(char const *cmdline) __chunk_size = -1UL; } + if (!strncmp(str, "novamap", 7)) { + str += strlen("novamap"); + __novamap = 1; + } + /* Group words together, delimited by "," */ while (*str && *str != ' ' && *str != ',') str++; diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index cefcf6ba3150..1b1dfcaa6fb9 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -27,6 +27,7 @@ extern int __pure nokaslr(void); extern int __pure is_quiet(void); +extern int __pure novamap(void); #define pr_efi(sys_table, msg) do { \ if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \ diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 7cfc51935c4b..5440ba17a1c5 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -318,6 +318,9 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, if (status == EFI_SUCCESS) { efi_set_virtual_address_map_t *svam; + if (novamap()) + return EFI_SUCCESS; + /* Install the new virtual address map */ svam = sys_table->runtime->set_virtual_address_map; status = svam(runtime_entry_count * desc_size, desc_size, -- cgit From 69c1f396f25b805aeff08f06d2e992c315ee5b1e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 2 Feb 2019 10:41:18 +0100 Subject: efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation Move the x86 EFI earlyprintk implementation to a shared location under drivers/firmware and tweak it slightly so we can expose it as an earlycon implementation (which is generic) rather than earlyprintk (which is only implemented for a few architectures) This also involves switching to write-combine mappings by default (which is required on ARM since device mappings lack memory semantics, and so memcpy/memset may not be used on them), and adding support for shared memory framebuffers on cache coherent non-x86 systems (which do not tolerate mismatched attributes). Note that 32-bit ARM does not populate its struct screen_info early enough for earlycon=efifb to work, so it is disabled there. Signed-off-by: Ard Biesheuvel Reviewed-by: Alexander Graf Cc: AKASHI Takahiro Cc: Bjorn Andersson Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Jeffrey Hugo Cc: Lee Jones Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190202094119.13230-10-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/Kconfig | 6 ++ drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/earlycon.c | 206 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 drivers/firmware/efi/earlycon.c (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 89110dfc7127..190be0b1d109 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -198,3 +198,9 @@ config EFI_DEV_PATH_PARSER bool depends on ACPI default n + +config EFI_EARLYCON + def_bool y + depends on SERIAL_EARLYCON && !ARM && !IA64 + select FONT_SUPPORT + select ARCH_USE_MEMREMAP_PROT diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 5f9f5039de50..d2d0d2030620 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -30,5 +30,6 @@ arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o +obj-$(CONFIG_EFI_EARLYCON) += earlycon.o obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o obj-$(CONFIG_UEFI_CPER_X86) += cper-x86.o diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c new file mode 100644 index 000000000000..c9a0efca17b0 --- /dev/null +++ b/drivers/firmware/efi/earlycon.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2013 Intel Corporation; author Matt Fleming + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static const struct font_desc *font; +static u32 efi_x, efi_y; +static u64 fb_base; +static pgprot_t fb_prot; + +static __ref void *efi_earlycon_map(unsigned long start, unsigned long len) +{ + return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot)); +} + +static __ref void efi_earlycon_unmap(void *addr, unsigned long len) +{ + early_memunmap(addr, len); +} + +static void efi_earlycon_clear_scanline(unsigned int y) +{ + unsigned long *dst; + u16 len; + + len = screen_info.lfb_linelength; + dst = efi_earlycon_map(y*len, len); + if (!dst) + return; + + memset(dst, 0, len); + efi_earlycon_unmap(dst, len); +} + +static void efi_earlycon_scroll_up(void) +{ + unsigned long *dst, *src; + u16 len; + u32 i, height; + + len = screen_info.lfb_linelength; + height = screen_info.lfb_height; + + for (i = 0; i < height - font->height; i++) { + dst = efi_earlycon_map(i*len, len); + if (!dst) + return; + + src = efi_earlycon_map((i + font->height) * len, len); + if (!src) { + efi_earlycon_unmap(dst, len); + return; + } + + memmove(dst, src, len); + + efi_earlycon_unmap(src, len); + efi_earlycon_unmap(dst, len); + } +} + +static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h) +{ + const u32 color_black = 0x00000000; + const u32 color_white = 0x00ffffff; + const u8 *src; + u8 s8; + int m; + + src = font->data + c * font->height; + s8 = *(src + h); + + for (m = 0; m < 8; m++) { + if ((s8 >> (7 - m)) & 1) + *dst = color_white; + else + *dst = color_black; + dst++; + } +} + +static void +efi_earlycon_write(struct console *con, const char *str, unsigned int num) +{ + struct screen_info *si; + unsigned int len; + const char *s; + void *dst; + + si = &screen_info; + len = si->lfb_linelength; + + while (num) { + unsigned int linemax; + unsigned int h, count = 0; + + for (s = str; *s && *s != '\n'; s++) { + if (count == num) + break; + count++; + } + + linemax = (si->lfb_width - efi_x) / font->width; + if (count > linemax) + count = linemax; + + for (h = 0; h < font->height; h++) { + unsigned int n, x; + + dst = efi_earlycon_map((efi_y + h) * len, len); + if (!dst) + return; + + s = str; + n = count; + x = efi_x; + + while (n-- > 0) { + efi_earlycon_write_char(dst + x*4, *s, h); + x += font->width; + s++; + } + + efi_earlycon_unmap(dst, len); + } + + num -= count; + efi_x += count * font->width; + str += count; + + if (num > 0 && *s == '\n') { + efi_x = 0; + efi_y += font->height; + str++; + num--; + } + + if (efi_x + font->width > si->lfb_width) { + efi_x = 0; + efi_y += font->height; + } + + if (efi_y + font->height > si->lfb_height) { + u32 i; + + efi_y -= font->height; + efi_earlycon_scroll_up(); + + for (i = 0; i < font->height; i++) + efi_earlycon_clear_scanline(efi_y + i); + } + } +} + +static int __init efi_earlycon_setup(struct earlycon_device *device, + const char *opt) +{ + struct screen_info *si; + u16 xres, yres; + u32 i; + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + return -ENODEV; + + fb_base = screen_info.lfb_base; + if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) + fb_base |= (u64)screen_info.ext_lfb_base << 32; + + if (opt && !strcmp(opt, "ram")) + fb_prot = PAGE_KERNEL; + else + fb_prot = pgprot_writecombine(PAGE_KERNEL); + + si = &screen_info; + xres = si->lfb_width; + yres = si->lfb_height; + + /* + * efi_earlycon_write_char() implicitly assumes a framebuffer with + * 32 bits per pixel. + */ + if (si->lfb_depth != 32) + return -ENODEV; + + font = get_default_font(xres, yres, -1, -1); + if (!font) + return -ENODEV; + + efi_y = rounddown(yres, font->height) - font->height; + for (i = 0; i < (yres - efi_y) / font->height; i++) + efi_earlycon_scroll_up(); + + device->con->write = efi_earlycon_write; + return 0; +} +EARLYCON_DECLARE(efifb, efi_earlycon_setup); -- cgit From 5c418dc789a3898717ebf2caa5716ba91a7150b2 Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Fri, 15 Feb 2019 17:55:51 +0100 Subject: efi: Fix build error due to enum collision between efi.h and ima.h The following commit: a893ea15d764 ("tpm: move tpm_chip definition to include/linux/tpm.h") introduced a build error when both IMA and EFI are enabled: In file included from ../security/integrity/ima/ima_fs.c:30: ../security/integrity/ima/ima.h:176:7: error: redeclaration of enumerator "NONE" What happens is that both headers (ima.h and efi.h) defines the same 'NONE' constant, and it broke when they started getting included from the same file: Rework to prefix the EFI enum with 'EFI_*'. Signed-off-by: Anders Roxell Signed-off-by: Ard Biesheuvel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190215165551.12220-2-ard.biesheuvel@linaro.org [ Cleaned up the changelog a bit. ] Signed-off-by: Ingo Molnar --- drivers/firmware/efi/runtime-wrappers.c | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 8903b9ccfc2b..8bbbbf160d05 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -85,7 +85,7 @@ struct efi_runtime_work efi_rts_work; pr_err("Failed to queue work to efi_rts_wq.\n"); \ \ exit: \ - efi_rts_work.efi_rts_id = NONE; \ + efi_rts_work.efi_rts_id = EFI_NONE; \ efi_rts_work.status; \ }) @@ -168,50 +168,50 @@ static void efi_call_rts(struct work_struct *work) arg5 = efi_rts_work.arg5; switch (efi_rts_work.efi_rts_id) { - case GET_TIME: + case EFI_GET_TIME: status = efi_call_virt(get_time, (efi_time_t *)arg1, (efi_time_cap_t *)arg2); break; - case SET_TIME: + case EFI_SET_TIME: status = efi_call_virt(set_time, (efi_time_t *)arg1); break; - case GET_WAKEUP_TIME: + case EFI_GET_WAKEUP_TIME: status = efi_call_virt(get_wakeup_time, (efi_bool_t *)arg1, (efi_bool_t *)arg2, (efi_time_t *)arg3); break; - case SET_WAKEUP_TIME: + case EFI_SET_WAKEUP_TIME: status = efi_call_virt(set_wakeup_time, *(efi_bool_t *)arg1, (efi_time_t *)arg2); break; - case GET_VARIABLE: + case EFI_GET_VARIABLE: status = efi_call_virt(get_variable, (efi_char16_t *)arg1, (efi_guid_t *)arg2, (u32 *)arg3, (unsigned long *)arg4, (void *)arg5); break; - case GET_NEXT_VARIABLE: + case EFI_GET_NEXT_VARIABLE: status = efi_call_virt(get_next_variable, (unsigned long *)arg1, (efi_char16_t *)arg2, (efi_guid_t *)arg3); break; - case SET_VARIABLE: + case EFI_SET_VARIABLE: status = efi_call_virt(set_variable, (efi_char16_t *)arg1, (efi_guid_t *)arg2, *(u32 *)arg3, *(unsigned long *)arg4, (void *)arg5); break; - case QUERY_VARIABLE_INFO: + case EFI_QUERY_VARIABLE_INFO: status = efi_call_virt(query_variable_info, *(u32 *)arg1, (u64 *)arg2, (u64 *)arg3, (u64 *)arg4); break; - case GET_NEXT_HIGH_MONO_COUNT: + case EFI_GET_NEXT_HIGH_MONO_COUNT: status = efi_call_virt(get_next_high_mono_count, (u32 *)arg1); break; - case UPDATE_CAPSULE: + case EFI_UPDATE_CAPSULE: status = efi_call_virt(update_capsule, (efi_capsule_header_t **)arg1, *(unsigned long *)arg2, *(unsigned long *)arg3); break; - case QUERY_CAPSULE_CAPS: + case EFI_QUERY_CAPSULE_CAPS: status = efi_call_virt(query_capsule_caps, (efi_capsule_header_t **)arg1, *(unsigned long *)arg2, (u64 *)arg3, @@ -235,7 +235,7 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL); + status = efi_queue_work(EFI_GET_TIME, tm, tc, NULL, NULL, NULL); up(&efi_runtime_lock); return status; } @@ -246,7 +246,7 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL); + status = efi_queue_work(EFI_SET_TIME, tm, NULL, NULL, NULL, NULL); up(&efi_runtime_lock); return status; } @@ -259,7 +259,7 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL, + status = efi_queue_work(EFI_GET_WAKEUP_TIME, enabled, pending, tm, NULL, NULL); up(&efi_runtime_lock); return status; @@ -271,7 +271,7 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL, + status = efi_queue_work(EFI_SET_WAKEUP_TIME, &enabled, tm, NULL, NULL, NULL); up(&efi_runtime_lock); return status; @@ -287,7 +287,7 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size, + status = efi_queue_work(EFI_GET_VARIABLE, name, vendor, attr, data_size, data); up(&efi_runtime_lock); return status; @@ -301,7 +301,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor, + status = efi_queue_work(EFI_GET_NEXT_VARIABLE, name_size, name, vendor, NULL, NULL); up(&efi_runtime_lock); return status; @@ -317,7 +317,7 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size, + status = efi_queue_work(EFI_SET_VARIABLE, name, vendor, &attr, &data_size, data); up(&efi_runtime_lock); return status; @@ -352,7 +352,7 @@ static efi_status_t virt_efi_query_variable_info(u32 attr, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space, + status = efi_queue_work(EFI_QUERY_VARIABLE_INFO, &attr, storage_space, remaining_space, max_variable_size, NULL); up(&efi_runtime_lock); return status; @@ -384,7 +384,7 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL, + status = efi_queue_work(EFI_GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL, NULL, NULL); up(&efi_runtime_lock); return status; @@ -400,7 +400,7 @@ static void virt_efi_reset_system(int reset_type, "could not get exclusive access to the firmware\n"); return; } - efi_rts_work.efi_rts_id = RESET_SYSTEM; + efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM; __efi_call_virt(reset_system, reset_type, status, data_size, data); up(&efi_runtime_lock); } @@ -416,7 +416,7 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list, + status = efi_queue_work(EFI_UPDATE_CAPSULE, capsules, &count, &sg_list, NULL, NULL); up(&efi_runtime_lock); return status; @@ -434,7 +434,7 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count, + status = efi_queue_work(EFI_QUERY_CAPSULE_CAPS, capsules, &count, max_size, reset_type, NULL); up(&efi_runtime_lock); return status; -- cgit