Re: [PATCH] efi: use 32-bit alignment for efi_guid_t
On Tue, Jan 08, 2019 at 04:28:29PM +0100, Ard Biesheuvel wrote: > The UEFI spec and EDK2 reference implementation both define EFI_GUID as > struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment > is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM), > this means that firmware services invoked by the kernel may assume that > efi_guid_t* arguments are 32-bit aligned, and use memory accessors that > do not tolerate misalignment. So let's set the minimum alignment to 32 bits. > > Note that the UEFI spec as well as some comments in the EDK2 code base > suggest that EFI_GUID should be 64-bit aligned, but this appears to be > a mistake, given that no code seems to exist that actually enforces that > or relies on it. Whereas code does exist that relies on it being 32-bit aligned... > Reported-by: Heinrich Schuchardt , > Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm > --- > include/linux/efi.h | 15 ++- > 1 file changed, 14 insertions(+), 1 deletion(-) > > diff --git a/include/linux/efi.h b/include/linux/efi.h > index 45ff763fba76..be08518c2553 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -48,7 +48,20 @@ typedef u16 efi_char16_t; /* UNICODE character */ > typedef u64 efi_physical_addr_t; > typedef void *efi_handle_t; > > -typedef guid_t efi_guid_t; > +/* > + * The UEFI spec and EDK2 reference implementation both define EFI_GUID as > + * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment > + * is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit > ARM), > + * this means that firmware services invoked by the kernel may assume that > + * efi_guid_t* arguments are 32-bit aligned, and use memory accessors that > + * do not tolerate misalignment. So let's set the minimum alignment to 32 > bits. > + * > + * Note that the UEFI spec as well as some comments in the EDK2 code base > + * suggest that EFI_GUID should be 64-bit aligned, but this appears to be > + * a mistake, given that no code seems to exist that actually enforces that > + * or relies on it. > + */ > +typedef guid_t efi_guid_t __aligned(__alignof__(u32)); > > #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ > GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) > -- > 2.20.1 >
Re: [PATCH v2 2/2] drivers: firmware: efi: install new fdt in configuration table
On Tue, Dec 11, 2018 at 12:55:39PM +, Pankaj Bansal wrote: > I am not able to understand the reservation about this patch. The reservation is that from an outside perspective, this patch set gives the impression that somewhere deep down the line, a fundamental misunderstanding exists. This impression may be completely incorrect, but from the information presented here, we cannot understand what problem is being solved by this set. This is why we keep coming with endless follow-up questions. > At least in earlier version, the apprehension was that if dtb > supplied by kernel (using command line parameters) > Is supplied to firmware, it may break firmware, as firmware might > not understand the bindings in it. Then I am afraid there has been some miscommunication. I have re-read the thread on the original patch set, and my interpretation on the feedback is completely different. It is referring to creating multiple layers of stability requirements between kernel and firmware when dealing with command-line loaded device trees. The firmware could _never_ be a consumer of a device tree loaded by the kernel stub. Best Regards, Leif
Re: [PATCH] efi_stub: update documentation on dtb= parameter
On Wed, Sep 05, 2018 at 08:07:50PM +0100, Grant Likely wrote: > The dtb= parameter is no longer the primary mechanism for providing a > devicetree to the kernel. Now either firmware or the boot selector (ex. > Grub) should provide the devicetree and dtb= should only be used for > debug or when using firmware that doesn't understand DT. > Update the EFI stub documentation to reflect the current usage. > > Signed-off-by: Grant Likely > Cc: Ard Biesheuvel > Cc: Jonathan Corbet Acked-by: Leif Lindholm > --- > Documentation/efi-stub.txt | 17 ++--- > 1 file changed, 14 insertions(+), 3 deletions(-) > > diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt > index 41df801f9a50..833edb0d0bc4 100644 > --- a/Documentation/efi-stub.txt > +++ b/Documentation/efi-stub.txt > @@ -83,7 +83,18 @@ is passed to bzImage.efi. > The "dtb=" option > - > > -For the ARM and arm64 architectures, we also need to be able to provide a > -device tree to the kernel. This is done with the "dtb=" command line option, > -and is processed in the same manner as the "initrd=" option that is > +For the ARM and arm64 architectures, a device tree must be provided to > +the kernel. Normally firmware shall supply the device tree via the > +EFI CONFIGURATION TABLE. However, the "dtb=" command line option can > +be used to override the firmware supplied device tree, or to supply > +one when firmware is unable to. > + > +Please note: Firmware adds runtime configuration information to the > +device tree before booting the kernel. If dtb= is used to override > +the device tree, then any runtime data provided by firmware will be > +lost. The dtb= option should only be used either as a debug tool, or > +as a last resort when a device tree is not provided in the EFI > +CONFIGURATION TABLE. > + > +"dtb=" is processed in the same manner as the "initrd=" option that is > described above. > -- > 2.11.0 > > IMPORTANT NOTICE: The contents of this email and any attachments are > confidential and may also be privileged. If you are not the intended > recipient, please notify the sender immediately and do not disclose the > contents to any other person, use it for any purpose, or store or copy the > information in any medium. Thank you.
Re: [PATCH] efi/libstub/arm: add opt-in Kconfig option for the DTB loader
On Mon, Jun 25, 2018 at 08:34:05AM +0200, Ard Biesheuvel wrote: > There are various ways a platform can provide a device tree binary > to the kernel, with different levels of sophistication: > - ideally, the UEFI firmware, which is tightly coupled with the > platform, provides a device tree image directly as a UEFI > configuration table, and typically permits the contents to be > manipulated either via menu options or via UEFI environment > variables that specify a replacement image, > - GRUB for ARM has a 'devicetree' directive which allows a device > tree image to be loaded from any location accessible to GRUB, and > supersede the one provided by the firmware, Just for comment - this too is considered an anomaly and will eventually be phased out. (Some part of the functionality may be retained in the form of overlay management.) > - the EFI stub implements a dtb= command line option that allows a > device tree image to be loaded from a file residing in the same > file system as the one the kernel image was loaded from. > > The dtb= command line option was never intended to be more than a > development feature, to allow the other options to be implemented > in parallel. So let's make it an opt-in feature that is disabled > by default, but can be re-enabled at will. > > Note that we already disable the dtb= command line option when we > detect that we are running with UEFI Secure Boot enabled. > > Signed-off-by: Ard Biesheuvel Acked-by: Leif Lindholm > --- > drivers/firmware/efi/Kconfig| 12 > drivers/firmware/efi/libstub/arm-stub.c | 7 --- > 2 files changed, 16 insertions(+), 3 deletions(-) > > diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig > index 781a4a337557..fc1cb2961d5b 100644 > --- a/drivers/firmware/efi/Kconfig > +++ b/drivers/firmware/efi/Kconfig > @@ -87,6 +87,18 @@ config EFI_RUNTIME_WRAPPERS > config EFI_ARMSTUB > bool > > +config EFI_ARMSTUB_DTB_LOADER > + bool "Enable the DTB loader" > + depends on EFI_ARMSTUB > + help > + Select this config option to add support for the dtb= command > + line parameter, allowing a device tree blob to be loaded into > + memory from the EFI System Partition by the stub. > + > + The device tree is typically provided by the platform or by > + the bootloader, and so this option is mostly for development > + purposes only. > + > config EFI_BOOTLOADER_CONTROL > tristate "EFI Bootloader Control" > depends on EFI_VARS > diff --git a/drivers/firmware/efi/libstub/arm-stub.c > b/drivers/firmware/efi/libstub/arm-stub.c > index 01a9d78ee415..c98b1856fc3d 100644 > --- a/drivers/firmware/efi/libstub/arm-stub.c > +++ b/drivers/firmware/efi/libstub/arm-stub.c > @@ -202,9 +202,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t > *sys_table, >* 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure >* boot is enabled if we can't determine its state. >*/ > - if (secure_boot != efi_secureboot_mode_disabled && > - strstr(cmdline_ptr, "dtb=")) { > - pr_efi(sys_table, "Ignoring DTB from command line.\n"); > + if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) || > + secure_boot != efi_secureboot_mode_disabled) { > + if (strstr(cmdline_ptr, "dtb=")) > + pr_efi(sys_table, "Ignoring DTB from command line.\n"); > } else { > status = handle_cmdline_files(sys_table, image, cmdline_ptr, > "dtb=", > -- > 2.11.0 > -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] drivers: firmware: efi: install new fdt in configuration table
On Wed, Apr 25, 2018 at 11:04:13AM +0100, Grant Likely wrote: > On 25/04/2018 07:49, Udit Kumar wrote: > > > 2) Kernel provides/overrides DTB > > > The kernel always has the option of loading it's own DTB, either because > > > firmware doesn't provide one, or it needs a newer DTB. This is similar > > > to CONFIG_ACPI_CUSTOM_DSDT in ACPI land. However, if the kernel is > > > overriding the DTB, then firmware has no part of it, and it should not > > > be allowed to modify the DTB at ExitBootServices() time. > > > > For our platforms at least, this will not work unless firmware is doing > > modifications. I think this I likely true for Ard as well. > > Firmware has a logic to modify default DTB for available devices, reading > > board configuration > > programming required muxes, based upon this removing/adding devices > > into DTB. > > IMO, this will not be an optimal way to use untouched DTB provided by > > kernel. > > Right, which is part of the reason for insisting on the firmare being > responsible. If the kernel or Grub overrides the DTB, then it is an explicit > *rejection* of anything firmware provides; presumable because something is > broken and it has to be worked around. So, the functionality in GRUB to replace a firmware-provided devicetree needs to go. And dtb= loading should ideally be made dependent on some sort of DEBUG config option. Suppliers that consider the DTB a feature of the kernel image need to go back to appending it to the kernel image. And if overriding the firmware-provided system configuration is necessary for booting at all, a trivial portable UEFI application can be written to do that. The thing I would like to add that is not just repeating myself is just pointing out that "firmware" is not just EDK2/U-Boot. It is entirely feasible that either of those inherit an already modified DTB from an earlier firmware stage. (I.e., let's make sure we don't just kick the GRUB problem one step up the stack.) / Leif -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] efi: arm: stop printing addresses of virtual mappings
On Fri, Jan 19, 2018 at 12:26:19PM +, Ard Biesheuvel wrote: > With the recent %p -> %px changes, we now get something like this in > the kernel boot log on ARM/arm64 EFI systems: > > Remapping and enabling EFI services. >EFI remap 0x0087fb83 => (ptrval) >EFI remap 0x0087fbdb => (ptrval) >EFI remap 0x0087fffc => (ptrval) > > The physical addresses of the UEFI runtime regions will also be > printed when booting with the efi=debug command line option, and the > virtual addresses can be inspected via /sys/kernel/debug/efi_page_tables > (if enabled). So let's just remove the lines above. As long as the efi=debug functionality is kept, I have no issue with this. Acked-by: Leif Lindholm <leif.lindh...@linaro.org> > Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org> > --- > drivers/firmware/efi/arm-runtime.c | 5 + > 1 file changed, 1 insertion(+), 4 deletions(-) > > diff --git a/drivers/firmware/efi/arm-runtime.c > b/drivers/firmware/efi/arm-runtime.c > index 1cc41c3d6315..5d4c8b661548 100644 > --- a/drivers/firmware/efi/arm-runtime.c > +++ b/drivers/firmware/efi/arm-runtime.c > @@ -80,10 +80,7 @@ static bool __init efi_virtmap_init(void) > return false; > > ret = efi_create_mapping(_mm, md); > - if (!ret) { > - pr_info(" EFI remap %pa => %p\n", > - , (void *)(unsigned long)md->virt_addr); > - } else { > + if (ret) { > pr_warn(" EFI remap %pa: failed to create mapping > (%d)\n", > , ret); > return false; > -- > 2.11.0 > -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] efi/arm32-stub: allow boottime allocations in the vmlinux region
sys_table_arg, > +"reserve_kernel_base(): Unable to retrieve memory > map.\n"); > + return status; > + } > + > + for (l = 0; l < map_size; l += desc_size) { > + efi_memory_desc_t *desc; > + u64 start, end; > + > + desc = (void *)memory_map + l; > + start = desc->phys_addr; > + end = start + desc->num_pages * EFI_PAGE_SIZE; > + > + /* does this entry cover the region? */ Nitpick: the logic tests the opposite of what the comment describes. /* Skip if entry does not intersect with region */ ? Anyway, that's minor. Reviewed-by: Leif Lindholm <leif.lindh...@linaro.org> > + if (start >= dram_base + MAX_UNCOMP_KERNEL_SIZE || > + end <= dram_base) > + continue; > + > + /* ignore types that are released to the OS anyway */ > + switch (desc->type) { > + case EFI_BOOT_SERVICES_CODE: > + case EFI_BOOT_SERVICES_DATA: > + /* these are safe -- ignore */ > + continue; > + > + case EFI_CONVENTIONAL_MEMORY: > + /* > + * Reserve the intersection between this entry and the > + * region. > + */ > + start = max(start, (u64)dram_base); > + end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE); > + > + status = efi_call_early(allocate_pages, > + EFI_ALLOCATE_ADDRESS, > + EFI_LOADER_DATA, > + (end - start) / EFI_PAGE_SIZE, > + ); > + if (status != EFI_SUCCESS) { > + pr_efi_err(sys_table_arg, > + "reserve_kernel_base(): alloc > failed.\n"); > + goto out; > + } > + break; > + > + case EFI_LOADER_CODE: > + case EFI_LOADER_DATA: > + /* > + * These regions may be released and reallocated for > + * another purpose (including EFI_RUNTIME_SERVICE_DATA) > + * at any time during the execution of the OS loader, > + * so we cannot consider them as safe. > + */ > + default: > + /* > + * Treat any other allocation in the region as unsafe */ > + status = EFI_OUT_OF_RESOURCES; > + goto out; > + } > + } > + > + status = EFI_SUCCESS; > +out: > + efi_call_early(free_pool, memory_map); > + return status; > +} > + > efi_status_t handle_kernel_image(efi_system_table_t *sys_table, >unsigned long *image_addr, >unsigned long *image_size, > @@ -71,10 +186,7 @@ efi_status_t handle_kernel_image(efi_system_table_t > *sys_table, >unsigned long dram_base, >efi_loaded_image_t *image) > { > - unsigned long nr_pages; > efi_status_t status; > - /* Use alloc_addr to tranlsate between types */ > - efi_physical_addr_t alloc_addr; > > /* >* Verify that the DRAM base address is compatible with the ARM > @@ -85,27 +197,12 @@ efi_status_t handle_kernel_image(efi_system_table_t > *sys_table, >*/ > dram_base = round_up(dram_base, SZ_128M); > > - /* > - * Reserve memory for the uncompressed kernel image. This is > - * all that prevents any future allocations from conflicting > - * with the kernel. Since we can't tell from the compressed > - * image how much DRAM the kernel actually uses (due to BSS > - * size uncertainty) we allocate the maximum possible size. > - * Do this very early, as prints can cause memory allocations > - * that may conflict with this. > - */ > - alloc_addr = dram_base; > - *reserve_size = MAX_UNCOMP_KERNEL_SIZE; > - nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; > - status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, > - EFI_LOADER_DATA, > - nr_pages, _addr); > + status = reserve_kernel_base(sys_table, dram_base, reserve_addr, > + reserve_size); > if (status != EFI_SUCCESS) { > - *reserve_size = 0; > pr_efi_err(sys_table, "Unable to allocate memory for > uncompressed kernel.\n"); > return status; > } > - *reserve_addr = alloc_addr; > > /* >* Relocate the zImage, so that it appears in the lowest 128 MB > -- > 2.7.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] efi/libstub/fdt: Standardize the names of EFI stub parameters
On Thu, Sep 10, 2015 at 02:52:25PM +0100, Stefano Stabellini wrote: > > > In any case this should be separate from the shim ABI discussion. > > > > I disagree; I think this is very much relevant to the ABI discussion. > > That's not to say that I insist on a particular approach, but I think > > that they need to be considered together. > > Let's suppose Xen didn't expose any RuntimeServices at all, would that > make it easier to discuss about the EFI stub parameters? Possibly :) > In the grant > scheme of things, they are not that important, as Ian wrote what is > important is how to pass the RSDP. So, we have discussed in the past having the ability to get at configuration tables when UEFI is not available. Say, for example, that we wanted SMBIOS support on a platform with U-Boot firmware. Since all that is needed then is a UEFI System Table with a pointer to a configuration table array, this should be fairly straightforward to implement statically. The other parameters would not be necessary. It would however require minor changes to the arm64 kernel UEFI support. / Leif -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] x86, efi, kasan: #undef memset/memcpy/memmove per arch.
On Fri, Aug 28, 2015 at 08:27:45AM +0200, Ingo Molnar wrote: * Andrey Ryabinin ryabinin@gmail.com wrote: In not-instrumented code KASAN replaces instrumented memset/memcpy/memmove with not-instrumented analogues __memset/__memcpy/__memove. However, on x86 EFI stub is not linked with kernel. s/with the kernel It uses not-instrumented mem*() functions from arch/x86/boot/compressed/string.c So we don't replace them with __mem*() variants in EFI stub. In ARM64 EFI stub is linked with the kernel, so we should s/In ARM64 EFI stub/On ARM64 the EFI stub/. replace mem*() functions with __mem*(), because EFI stub s/the EFI stub runs before KASAN setup early shadow. s/before KASAN sets up the early shadow ? So let's move these #undef mem* into arch's asm/efi.h which is s/lets No, that one is actually correct. Abbreviation of let us. also included by EFI stub. s/by the EFI stub Signed-off-by: Andrey Ryabinin ryabinin@gmail.com --- arch/x86/include/asm/efi.h | 8 drivers/firmware/efi/libstub/efistub.h | 4 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 155162e..d821ce2 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -25,6 +25,14 @@ #define EFI32_LOADER_SIGNATURE EL32 #define EFI64_LOADER_SIGNATURE EL64 +/* + * Use memcpy/memset from arch/x86/boot/compressed/string.c + * for EFI stub. + */ +#undef memcpy +#undef memset +#undef memmove This comment should also mention why it's done, not what is done. Also: s/for EFI stub/for the EFI stub Thanks, Ingo -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] arm64: use core efi=debug instead of uefi_debug command line parameter
On Wed, Aug 26, 2015 at 06:24:55PM +0100, Matt Fleming wrote: On Wed, 26 Aug, at 02:24:57PM, Leif Lindholm wrote: Now that we have an efi=debug command line option in the core code, use this instead of the arm64-specific uefi_debug option. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- Documentation/arm/uefi.txt | 2 -- arch/arm64/kernel/efi.c| 19 +-- 2 files changed, 5 insertions(+), 16 deletions(-) Are there no concerns with backwards-compatibility here? I expected this patch to internally convert uefi_debug to efi=debug if old boot loaders, kernel config, etc specify it. Is that something that can be safely ignored? Since it is purely a debug feature, I opted to just drop it. I don't have strong feelings, and it could certainly be kept as an arm64-only alias (but setting the EFI_DBG flag) if others disagree. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 1/5] arm64: clone early_init_dt_add_memory_arch() to override default
On Wed, Aug 26, 2015 at 10:06:27AM +0200, Ard Biesheuvel wrote: Override the __weak early_init_dt_add_memory_arch() with our own version. We need this in a subsequent patch to make the handling of the memory nodes conditional on whether we are booting via UEFI or not. Worth clarifying that this is a direct copy? (Our own version can be read as there being modifications here.) Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/mm/init.c | 41 1 file changed, 41 insertions(+) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index f5c0680d17d9..ab25fde7397c 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -374,3 +374,44 @@ static int __init keepinitrd_setup(char *__unused) __setup(keepinitrd, keepinitrd_setup); #endif + +void __init early_init_dt_add_memory_arch(u64 base, u64 size) +{ + const u64 phys_offset = __pa(PAGE_OFFSET); + + if (!PAGE_ALIGNED(base)) { + if (size PAGE_SIZE - (base ~PAGE_MASK)) { + pr_warn(Ignoring memory block 0x%llx - 0x%llx\n, + base, base + size); + return; + } + size -= PAGE_SIZE - (base ~PAGE_MASK); + base = PAGE_ALIGN(base); + } + size = PAGE_MASK; + + if (base MAX_MEMBLOCK_ADDR) { + pr_warning(Ignoring memory block 0x%llx - 0x%llx\n, + base, base + size); + return; + } + + if (base + size - 1 MAX_MEMBLOCK_ADDR) { + pr_warning(Ignoring memory range 0x%llx - 0x%llx\n, + ((u64)MAX_MEMBLOCK_ADDR) + 1, base + size); + size = MAX_MEMBLOCK_ADDR - base + 1; + } + + if (base + size phys_offset) { + pr_warning(Ignoring memory block 0x%llx - 0x%llx\n, +base, base + size); + return; + } + if (base phys_offset) { + pr_warning(Ignoring memory range 0x%llx - 0x%llx\n, +base, phys_offset); + size -= phys_offset - base; + base = phys_offset; + } + memblock_add(base, size); +} -- 1.9.1 Would it be too crazy to do this via an added call to a weak memblock_use_dt() function in the original instead, to avoid duplicating this entire function? We need the functionality for 4/5 (nice cleanup) and 5/5 (bugfix), so happy with whatever works. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/5] efi: move FDT handling to separate object file
On Wed, Aug 26, 2015 at 10:06:28AM +0200, Ard Biesheuvel wrote: The EFI specific FDT handling is compiled conditionally, and is logically independent of the rest of efi.o. So move it to a separate file before making changes to it in subsequent patches. Acked-by: Matt Fleming matt.flem...@intel.com Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efi-fdt.c | 93 drivers/firmware/efi/efi.c | 86 -- 3 files changed, 94 insertions(+), 86 deletions(-) Acked-by: Leif Lindholm leif.lindh...@linaro.org diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 6fd3da938717..d9140208fc1c 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP)+= runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_STUB) += libstub/ +obj-$(CONFIG_EFI_PARAMS_FROM_FDT)+= efi-fdt.o diff --git a/drivers/firmware/efi/efi-fdt.c b/drivers/firmware/efi/efi-fdt.c new file mode 100644 index ..f0e7ef2ae0e9 --- /dev/null +++ b/drivers/firmware/efi/efi-fdt.c @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#include linux/init.h +#include linux/efi.h +#include linux/of.h +#include linux/of_fdt.h + +#define UEFI_PARAM(name, prop, field) \ + { \ + { name }, \ + { prop }, \ + offsetof(struct efi_fdt_params, field),\ + FIELD_SIZEOF(struct efi_fdt_params, field) \ + } + +static __initdata struct { + const char name[32]; + const char propname[32]; + int offset; + int size; +} dt_params[] = { + UEFI_PARAM(System Table, linux,uefi-system-table, system_table), + UEFI_PARAM(MemMap Address, linux,uefi-mmap-start, mmap), + UEFI_PARAM(MemMap Size, linux,uefi-mmap-size, mmap_size), + UEFI_PARAM(MemMap Desc. Size, linux,uefi-mmap-desc-size, desc_size), + UEFI_PARAM(MemMap Desc. Version, linux,uefi-mmap-desc-ver, desc_ver) +}; + +struct param_info { + int verbose; + int found; + void *params; +}; + +static int __init fdt_find_uefi_params(unsigned long node, const char *uname, +int depth, void *data) +{ + struct param_info *info = data; + const void *prop; + void *dest; + u64 val; + int i, len; + + if (depth != 1 || strcmp(uname, chosen) != 0) + return 0; + + for (i = 0; i ARRAY_SIZE(dt_params); i++) { + prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); + if (!prop) + return 0; + dest = info-params + dt_params[i].offset; + info-found++; + + val = of_read_number(prop, len / sizeof(u32)); + + if (dt_params[i].size == sizeof(u32)) + *(u32 *)dest = val; + else + *(u64 *)dest = val; + + if (info-verbose) + pr_info( %s: 0x%0*llx\n, dt_params[i].name, + dt_params[i].size * 2, val); + } + return 1; +} + +int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) +{ + struct param_info info; + int ret; + + pr_info(Getting EFI parameters from FDT:\n); + + info.verbose = verbose; + info.found = 0; + info.params = params; + + ret = of_scan_flat_dt(fdt_find_uefi_params, info); + if (!info.found) + pr_info(UEFI not found.\n); + else if (!ret) + pr_err(Can't find '%s' in device tree!\n, +dt_params[info.found].name); + + return ret; +} diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 9fa8084a7c8d..f975a1a45b80 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -20,8 +20,6 @@ #include linux/init.h #include linux/device.h #include linux/efi.h -#include linux/of.h -#include linux/of_fdt.h #include linux/io.h #include linux/platform_device.h @@ -460,90 +458,6 @@ static int __init efi_load_efivars(void) device_initcall(efi_load_efivars); #endif -#ifdef CONFIG_EFI_PARAMS_FROM_FDT - -#define UEFI_PARAM(name, prop, field) \ - { \ - { name }, \ - { prop
[PATCH 0/3] unify efi debug output across architectures
efi didn't use to have much in the way of kernel command line options, until some point last year. Then once the efi= option was added, it has been expanded on. x86 had an efi=debug option added, but that would be a useful thing across all efi architectures. arm64 efi support (predating efi=debug) came with its own 'uefi_debug' option, and passed along a special verbosity flag when calling into some not-strictly-arch-specific functions in core efi code. So: - Move efi=debug into core code, to be usable by all architectures - Change arm64 efi code to use 'efi=debug' instead of 'uefi_debug' - Rework arm64 interface to core code to drop special verbosity flag Leif Lindholm (3): efi/x86: move efi=debug option parsing to core arm64: use core efi=debug instead of uefi_debug command line parameter efi/arm64: clean up efi_get_fdt_params() interface Documentation/arm/uefi.txt | 2 -- arch/arm64/kernel/efi.c | 19 +-- arch/x86/platform/efi/efi.c | 2 -- drivers/firmware/efi/efi.c | 9 + include/linux/efi.h | 2 +- 5 files changed, 11 insertions(+), 23 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] efi/arm64: clean up efi_get_fdt_params() interface
As we now have a common debug infrastructure between core and arm64 efi, drop the bit of the interface passing verbose output flags around. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/kernel/efi.c| 2 +- drivers/firmware/efi/efi.c | 6 ++ include/linux/efi.h| 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 612ad5e..ab5eeb6 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -201,7 +201,7 @@ void __init efi_init(void) struct efi_fdt_params params; /* Grab UEFI information placed in FDT by stub */ - if (!efi_get_fdt_params(params, efi_enabled(EFI_DBG))) + if (!efi_get_fdt_params(params)) return; efi_system_table = params.system_table; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 78de0bd..aca6aaf 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -492,7 +492,6 @@ static __initdata struct { }; struct param_info { - int verbose; int found; void *params; }; @@ -523,21 +522,20 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, else *(u64 *)dest = val; - if (info-verbose) + if (efi_enabled(EFI_DBG)) pr_info( %s: 0x%0*llx\n, dt_params[i].name, dt_params[i].size * 2, val); } return 1; } -int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) +int __init efi_get_fdt_params(struct efi_fdt_params *params) { struct param_info info; int ret; pr_info(Getting EFI parameters from FDT:\n); - info.verbose = verbose; info.found = 0; info.params = params; diff --git a/include/linux/efi.h b/include/linux/efi.h index 85ef051..b1a5b74 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -901,7 +901,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); extern void efi_get_time(struct timespec *now); extern void efi_reserve_boot_services(void); -extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); +extern int efi_get_fdt_params(struct efi_fdt_params *params); extern struct efi_memory_map memmap; extern struct kobject *efi_kobj; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] arm64: use core efi=debug instead of uefi_debug command line parameter
Now that we have an efi=debug command line option in the core code, use this instead of the arm64-specific uefi_debug option. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- Documentation/arm/uefi.txt | 2 -- arch/arm64/kernel/efi.c| 19 +-- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt index d60030a..7b3fdfe 100644 --- a/Documentation/arm/uefi.txt +++ b/Documentation/arm/uefi.txt @@ -60,5 +60,3 @@ linux,uefi-mmap-desc-ver | 32-bit | Version of the mmap descriptor format. linux,uefi-stub-kern-ver | string | Copy of linux_banner from build. - -For verbose debug messages, specify 'uefi_debug' on the kernel command line. diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index e8ca6ea..612ad5e 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -51,15 +51,6 @@ static struct mm_struct efi_mm = { INIT_MM_CONTEXT(efi_mm) }; -static int uefi_debug __initdata; -static int __init uefi_debug_setup(char *str) -{ - uefi_debug = 1; - - return 0; -} -early_param(uefi_debug, uefi_debug_setup); - static int __init is_normal_ram(efi_memory_desc_t *md) { if (md-attribute EFI_MEMORY_WB) @@ -171,14 +162,14 @@ static __init void reserve_regions(void) efi_memory_desc_t *md; u64 paddr, npages, size; - if (uefi_debug) + if (efi_enabled(EFI_DBG)) pr_info(Processing EFI memory map:\n); for_each_efi_memory_desc(memmap, md) { paddr = md-phys_addr; npages = md-num_pages; - if (uefi_debug) { + if (efi_enabled(EFI_DBG)) { char buf[64]; pr_info( 0x%012llx-0x%012llx %s, @@ -194,11 +185,11 @@ static __init void reserve_regions(void) if (is_reserve_region(md)) { memblock_reserve(paddr, size); - if (uefi_debug) + if (efi_enabled(EFI_DBG)) pr_cont(*); } - if (uefi_debug) + if (efi_enabled(EFI_DBG)) pr_cont(\n); } @@ -210,7 +201,7 @@ void __init efi_init(void) struct efi_fdt_params params; /* Grab UEFI information placed in FDT by stub */ - if (!efi_get_fdt_params(params, uefi_debug)) + if (!efi_get_fdt_params(params, efi_enabled(EFI_DBG))) return; efi_system_table = params.system_table; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] efi/x86: move efi=debug option parsing to core
fed6cefe3b6e (x86/efi: Add a debug option to the efi= cmdline) adds the DBG flag, but does so for x86 only. Move this early param parsing to core code. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 2 -- drivers/firmware/efi/efi.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index e4308fe..9757b79 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -979,8 +979,6 @@ static int __init arch_parse_efi_cmdline(char *str) if (parse_option_str(str, old_map)) set_bit(EFI_OLD_MEMMAP, efi.flags); - if (parse_option_str(str, debug)) - set_bit(EFI_DBG, efi.flags); return 0; } diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index d6144e3..78de0bd 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -63,6 +63,9 @@ static int __init parse_efi_cmdline(char *str) return -EINVAL; } + if (parse_option_str(str, debug)) + set_bit(EFI_DBG, efi.flags); + if (parse_option_str(str, noruntime)) disable_runtime = true; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 3/5] arm64/efi: move EFI init before early FDT processing
On Wed, Aug 26, 2015 at 10:06:29AM +0200, Ard Biesheuvel wrote: The early FDT processing is responsible for enumerating the DT memory nodes and installing them as memblocks. This should only be done if we are not booting via EFI, but at this point, we don't know yet if that is the case or not. So move the EFI init to before the early FDT processing. This involves making some changes to the way EFI discovers the locations of the EFI system table and the memory map, since those values are retrieved from the FDT as well. Instead the of_scan infrastructure, it now uses libfdt directly to access the /chosen node. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/include/asm/efi.h | 4 +- arch/arm64/kernel/efi.c| 14 ++-- arch/arm64/kernel/setup.c | 4 +- drivers/firmware/efi/efi-fdt.c | 74 include/linux/efi.h| 3 +- 5 files changed, 40 insertions(+), 59 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index ef572206f1c3..635101f36720 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -5,9 +5,9 @@ #include asm/neon.h #ifdef CONFIG_EFI -extern void efi_init(void); +extern void efi_init_fdt(void *fdt); #else -#define efi_init() +#define efi_init_fdt(x) #endif #define efi_call_virt(f, ...) \ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 9d4aa18f2a82..0e3dbe2cb752 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -51,14 +51,7 @@ static struct mm_struct efi_mm = { INIT_MM_CONTEXT(efi_mm) }; -static int uefi_debug __initdata; -static int __init uefi_debug_setup(char *str) -{ - uefi_debug = 1; - - return 0; -} -early_param(uefi_debug, uefi_debug_setup); +static bool uefi_debug __initdata; So, this obviously clashes with the patches I sent out recently, but then they were triggered by the awkwardness of the interface passing the verbosity flag around... static int __init is_normal_ram(efi_memory_desc_t *md) { @@ -205,14 +198,15 @@ static __init void reserve_regions(void) set_bit(EFI_MEMMAP, efi.flags); } -void __init efi_init(void) +void __init efi_init_fdt(void *fdt) (Nitpick: efi_init_fdt here, efi_virtmap_init below - naming consistency) { struct efi_fdt_params params; /* Grab UEFI information placed in FDT by stub */ - if (!efi_get_fdt_params(params, uefi_debug)) + if (!efi_get_fdt_params(fdt, params)) return; + uefi_debug = params.verbose; efi_system_table = params.system_table; Here is where it gets problematic. Because this is now called before parse_early_params(), we lose the ability to do debug output. Now, the details in the DT parsing is maybe not that critical, but what follow is: memblock_reserve(params.mmap PAGE_MASK, ... and we _really_ need to be able to dump the memory regions, with attributes, for debugging purposes. diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index fddae2c15ad2..8fdde97c975c 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -298,6 +298,9 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) { void *dt_virt = fixmap_remap_fdt(dt_phys); + if (dt_virt) + efi_init_fdt(dt_virt); + if (!dt_virt || !early_init_dt_scan(dt_virt)) { pr_crit(\n Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n @@ -366,7 +369,6 @@ void __init setup_arch(char **cmdline_p) */ local_async_enable(); - efi_init(); So can we just keep this call and terminate efi_init_fdt before memblock_reserve? arm64_memblock_init(); /* Parse the ACPI tables for possible boot-time configuration */ diff --git a/drivers/firmware/efi/efi-fdt.c b/drivers/firmware/efi/efi-fdt.c index f0e7ef2ae0e9..2e0e1a5a3fbb 100644 --- a/drivers/firmware/efi/efi-fdt.c +++ b/drivers/firmware/efi/efi-fdt.c @@ -8,8 +8,7 @@ #include linux/init.h #include linux/efi.h -#include linux/of.h -#include linux/of_fdt.h +#include linux/libfdt.h #define UEFI_PARAM(name, prop, field) \ { \ @@ -32,62 +31,47 @@ static __initdata struct { UEFI_PARAM(MemMap Desc. Version, linux,uefi-mmap-desc-ver, desc_ver) }; -struct param_info { - int verbose; - int found; - void *params; -}; - -static int __init fdt_find_uefi_params(unsigned long node, const char *uname, -int depth, void *data) +bool __init efi_get_fdt_params(void *fdt, struct efi_fdt_params *params) { - struct param_info *info = data; const void *prop; - void *dest; - u64 val; - int i, len; + int node,
Re: [PATCH v2 4/5] arm64/efi: ignore DT memory nodes instead of removing them
On Wed, Aug 26, 2015 at 10:06:30AM +0200, Ard Biesheuvel wrote: There are two problems with the UEFI stub DT memory node removal routine: - it deletes nodes as it traverses the tree, which happens to work but is not supported, as deletion invalidates the node iterator; - deleting memory nodes entirely may discard annotations in the form of additional properties on the nodes. Now that the UEFI initialization has moved to an earlier stage, we can actually just ignore any memblocks that are installed after we have processed the UEFI memory map. This way, it is no longer necessary to remove the nodes, so we can remove that logic from the stub as well. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/mm/init.c | 10 drivers/firmware/efi/libstub/fdt.c | 24 +--- 2 files changed, 11 insertions(+), 23 deletions(-) Nice cleanup. Acked-by: Leif Lindholm leif.lindh...@linaro.org diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index ab25fde7397c..ecbc051bc66b 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -379,6 +379,16 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) { const u64 phys_offset = __pa(PAGE_OFFSET); + /* + * This callback will be invoked both when booting via UEFI and when + * booting via DT only. In the former case, we need to ignore memory + * nodes in the DT since UEFI is authoritative when it comes to the + * memory map. So ignore any invocations of this callback after + * EFI_MEMMAP has been set. + */ + if (efi_enabled(EFI_MEMMAP)) + return; + if (!PAGE_ALIGNED(base)) { if (size PAGE_SIZE - (base ~PAGE_MASK)) { pr_warn(Ignoring memory block 0x%llx - 0x%llx\n, diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index ef5d764e2a27..343e7992bd8f 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -24,7 +24,7 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, unsigned long map_size, unsigned long desc_size, u32 desc_ver) { - int node, prev, num_rsv; + int node, num_rsv; int status; u32 fdt_val32; u64 fdt_val64; @@ -54,28 +54,6 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, goto fdt_set_fail; /* - * Delete any memory nodes present. We must delete nodes which - * early_init_dt_scan_memory may try to use. - */ - prev = 0; - for (;;) { - const char *type; - int len; - - node = fdt_next_node(fdt, prev, NULL); - if (node 0) - break; - - type = fdt_getprop(fdt, node, device_type, len); - if (type strncmp(type, memory, len) == 0) { - fdt_del_node(fdt, node); - continue; - } - - prev = node; - } - - /* * Delete all memory reserve map entries. When booting via UEFI, * kernel will use the UEFI memory map to find reserved regions. */ -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Linaro-uefi] [PATCH] firmware: efi: remove unneeded guid unparse
On Tue, Jan 20, 2015 at 04:20:10PM +, Ard Biesheuvel wrote: On 20 January 2015 at 16:12, Ivan Khoronzhuk ivan.khoronz...@linaro.org wrote: There is no reason to translate guid number to string here. So remove it in order to not do unneeded work. Signed-off-by: Ivan Khoronzhuk ivan.khoronz...@linaro.org --- drivers/firmware/efi/efi.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 9035c1b..f6be017 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -272,15 +272,10 @@ static __init int match_config_table(efi_guid_t *guid, unsigned long table, efi_config_table_type_t *table_types) { - u8 str[EFI_VARIABLE_GUID_LEN + 1]; int i; if (table_types) { - efi_guid_unparse(guid, str); - for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { - efi_guid_unparse(table_types[i].guid, str); - if (!efi_guidcmp(*guid, table_types[i].guid)) { *(table_types[i].ptr) = table; pr_cont( %s=0x%lx , Doh! Left the unparses in after I removed the debug printouts :| Thanks for spotting. Acked-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] efi: don't look for chosen@0 node on DT platforms
Due to some scary special case handling noticed in drivers/of, various bits of the ARM* EFI support patches did duplicate looking for @0 variants of various nodes. Unless on an ancient PPC system, these are not in fact required. Most instances have become refactored out along the way, this removes the last one. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 9035c1b..9fd923a 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -403,8 +403,7 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, u64 val; int i, len; - if (depth != 1 || - (strcmp(uname, chosen) != 0 strcmp(uname, chosen@0) != 0)) + if (depth != 1 || strcmp(uname, chosen) != 0) return 0; for (i = 0; i ARRAY_SIZE(dt_params); i++) { -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 0/8] arm64: stable UEFI virtual mappings for kexec
For the series: Tested-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
new_fdt_size; efi_status_t status; + int runtime_entry_count = 0; + + /* + * Get a copy of the current memory map that we will use to prepare + * the input for SetVirtualAddressMap(). We don't have to worry about + * subsequent allocations adding entries, since they could not affect + * the number of EFI_MEMORY_RUNTIME regions. + */ + status = efi_get_memory_map(sys_table, runtime_map, map_size, + desc_size, desc_ver, mmap_key); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, Unable to retrieve UEFI memory map.\n); + return status; + } + + pr_efi(sys_table, +Exiting boot services and installing virtual address map...\n); /* * Estimate size of new FDT, and allocate memory for it. We @@ -248,12 +267,48 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, } } + /* + * Update the memory map with virtual addresses. The function will also + * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME + * entries so that we can pass it straight into SetVirtualAddressMap() + */ + efi_get_virtmap(memory_map, map_size, desc_size, runtime_map, + runtime_entry_count); + /* Now we are ready to exit_boot_services.*/ status = sys_table-boottime-exit_boot_services(handle, mmap_key); + if (status == EFI_SUCCESS) { + efi_set_virtual_address_map_t *svam; - if (status == EFI_SUCCESS) - return status; + /* Install the new virtual address map */ + svam = sys_table-runtime-set_virtual_address_map; + status = svam(runtime_entry_count * desc_size, desc_size, + desc_ver, runtime_map); + + /* + * We are beyond the point of no return here, so if the call to + * SetVirtualAddressMap() failed, we need to signal that to the + * incoming kernel but proceed normally otherwise. + */ + if (status != EFI_SUCCESS) { + int l; + + /* + * Set the virtual address field of all + * EFI_MEMORY_RUNTIME entries to 0. This will signal + * the incoming kernel that no virtual translation has + * been installed. + */ + for (l = 0; l map_size; l += desc_size) { + efi_memory_desc_t *p = (void *)memory_map + l; + + if (p-attribute EFI_MEMORY_RUNTIME) + p-virt_addr = 0; + } + } + return EFI_SUCCESS; + } pr_efi_err(sys_table, Exit boot services failed.\n); @@ -264,6 +319,7 @@ fail_free_new_fdt: efi_free(sys_table, new_fdt_size, *new_fdt_addr); fail: + sys_table-boottime-free_pool(runtime_map); return EFI_LOAD_ERROR; } -- 1.8.3.2 Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
On Mon, Dec 22, 2014 at 10:59:02AM +, Ard Biesheuvel wrote: In order to support kexec, the kernel needs to be able to deal with the state of the UEFI firmware after SetVirtualAddressMap() has been called. To avoid having separate code paths for non-kexec and kexec, let's move the call to SetVirtualAddressMap() to the stub: this will guarantee us that it will only be called once (since the stub is not executed during kexec), and ensures that the UEFI state is identical between kexec and normal boot. This implies that the layout of the virtual mapping needs to be created by the stub as well. All regions are rounded up to a naturally aligned multiple of 64 KB (for compatibility with 64k pages kernels) and recorded in the UEFI memory map. The kernel proper reads those values and installs the mappings in a dedicated set of page tables that are swapped in during UEFI Runtime Services calls. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/include/asm/efi.h | 20 +++- arch/arm64/kernel/efi.c| 223 - arch/arm64/kernel/setup.c | 1 + drivers/firmware/efi/libstub/fdt.c | 137 ++- 4 files changed, 270 insertions(+), 111 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 71291253114f..6cc668a378c5 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -7,28 +7,36 @@ #ifdef CONFIG_EFI extern void efi_init(void); extern void efi_idmap_init(void); +extern void efi_virtmap_init(void); #else #define efi_init() #define efi_idmap_init() +#define efi_virtmap_init #endif #define efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab-runtime-f; \ + efi_##f##_t *__f; \ efi_status_t __s; \ \ - kernel_neon_begin();\ + kernel_neon_begin();/* disables preemption */ \ Nitpick: adding comment to otherwise untouched source line. + efi_virtmap_load(); \ + __f = efi.systab-runtime-f; \ __s = __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ kernel_neon_end(); \ __s;\ }) #define __efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab-runtime-f; \ + efi_##f##_t *__f; \ \ - kernel_neon_begin();\ + kernel_neon_begin();/* disables preemption */ \ Same nitpick. + efi_virtmap_load(); \ + __f = efi.systab-runtime-f; \ __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ kernel_neon_end(); \ }) @@ -45,5 +53,9 @@ extern void efi_idmap_init(void); #define efi_call_early(f, ...) sys_table_arg-boottime-f(__VA_ARGS__) #define EFI_ALLOC_ALIGN SZ_64K +#define EFI_VIRTMAP EFI_ARCH_1 + +void efi_virtmap_load(void); +void efi_virtmap_unload(void); #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 6fac253bc783..2ebe67ffb629 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,25 +11,30 @@ * */ +#include linux/atomic.h #include linux/dmi.h #include linux/efi.h #include linux/export.h #include linux/memblock.h +#include linux/mm_types.h #include linux/bootmem.h #include linux/of.h #include linux/of_fdt.h +#include linux/rbtree.h +#include linux/rwsem.h #include linux/sched.h #include linux/slab.h +#include linux/spinlock.h #include asm/cacheflush.h #include asm/efi.h #include asm/tlbflush.h #include asm/mmu_context.h +#include asm/mmu.h +#include asm/pgtable.h struct efi_memory_map memmap; -static efi_runtime_services_t *runtime; - static u64 efi_system_table; static int uefi_debug __initdata; @@ -69,9 +74,33 @@ static void __init efi_setup_idmap(void) } } +/* + * Translate a EFI virtual
Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
On Wed, Jan 07, 2015 at 12:30:27PM +, Ard Biesheuvel wrote: + kernel_neon_begin();/* disables preemption */ \ Same nitpick. Is there anything wrong with that? I said nitpick. My (very minor) objection is that a (very reasonable) comment is added to existing functionality by a patch that adds new functionality. It makes the git blame/praise output less clear. Would you prefer the comment to be on a separate line? I would _prefer_ the comments to be a separate patch. But again, a nitpick. Well, adding the comment is relevant to this patch, as we need to disable preemption now before switching to the new address space. In fact, it might be better even to drop the comment, and add an explicit (if redundant) preempt_disable/preempt_enable pair. That would be more clear, yes. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
On Wed, Jan 07, 2015 at 12:16:02PM +, Ard Biesheuvel wrote: diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 71291253114f..6cc668a378c5 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -7,28 +7,36 @@ #ifdef CONFIG_EFI extern void efi_init(void); extern void efi_idmap_init(void); +extern void efi_virtmap_init(void); #else #define efi_init() #define efi_idmap_init() +#define efi_virtmap_init #endif #define efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab-runtime-f; \ + efi_##f##_t *__f; \ efi_status_t __s; \ \ - kernel_neon_begin();\ + kernel_neon_begin();/* disables preemption */ \ Nitpick: adding comment to otherwise untouched source line. + efi_virtmap_load(); \ + __f = efi.systab-runtime-f; \ __s = __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ kernel_neon_end(); \ __s;\ }) #define __efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab-runtime-f; \ + efi_##f##_t *__f; \ \ - kernel_neon_begin();\ + kernel_neon_begin();/* disables preemption */ \ Same nitpick. Is there anything wrong with that? I said nitpick. My (very minor) objection is that a (very reasonable) comment is added to existing functionality by a patch that adds new functionality. It makes the git blame/praise output less clear. Would you prefer the comment to be on a separate line? I would _prefer_ the comments to be a separate patch. But again, a nitpick. diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index b80991166754..d8390f507da0 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -402,6 +402,7 @@ void __init setup_arch(char **cmdline_p) request_standard_resources(); efi_idmap_init(); + efi_virtmap_init(); Could these two be merged together into one function? Say efi_memmap_init()? Well, I decided to do it like this because efi_idmap_init() gets removed in its entirety (including this invocation) in a subsequent patch. Ah yeah. I knew that yesterday. Ignore me. More coffee. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] arm64: don't make early_*map() calls post paging_init()
On Tue, Jan 06, 2015 at 09:38:24AM +, Ard Biesheuvel wrote: diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 6fac253..790adb5 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -393,6 +385,8 @@ static int __init arm64_enter_virtual_mode(void) mapsize); memmap.map_end = memmap.map + mapsize; + efi_setup_idmap(); + I think this is incorrect: we may call early_alloc() here which is only allowed before paging_init() Hmm... Technically, the existing code is already breaking this restriction then - but my patch moved that _way_ later in the boot process (early initcall instead of setup_arch()). I'll resend with an alternative solution that leaves the efi_setup_idmap() ordering vs paging init() in its current state. Since efi_setup_idmap() goes away with your stable UEFI virtual mappings for kexec series, I don't want to make changes here and for potential backports too invasive. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] arm64: don't make early_*map() calls post paging_init()
arm64 early_ioremap/iounmap/memremap/memunmap are not supported beyond the call to paging_init(), but arm64_enter_virtual_mode() (an early initcall) makes one call to unmap the UEFI memory map. Rearrange the code to unmap this region before paging_init(), and then pull back the remapping of the EFI memory map to the second part of UEFI initialisation - efi_idmap_init() - renaming that function as efi_memmap_init(), which better describes what it now does. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Fixes: f84d02755f5a (arm64: add EFI runtime services) --- arch/arm64/include/asm/efi.h | 4 ++-- arch/arm64/kernel/efi.c | 27 ++- arch/arm64/kernel/setup.c| 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a34fd3b..92f4d44 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -6,10 +6,10 @@ #ifdef CONFIG_EFI extern void efi_init(void); -extern void efi_idmap_init(void); +extern void efi_memmap_init(void); #else #define efi_init() -#define efi_idmap_init() +#define efi_memmap_init() #endif #define efi_call_virt(f, ...) \ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 6fac253..e311066 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -313,17 +313,26 @@ void __init efi_init(void) memmap.desc_size = params.desc_size; memmap.desc_version = params.desc_ver; - if (uefi_init() 0) - return; + if (uefi_init() = 0) + reserve_regions(); - reserve_regions(); + early_memunmap(memmap.map, params.mmap_size); } -void __init efi_idmap_init(void) +void __init efi_memmap_init(void) { + u64 mapsize; + if (!efi_enabled(EFI_BOOT)) return; + /* replace early memmap mapping with permanent mapping */ + mapsize = memmap.map_end - memmap.map; + memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, + mapsize); + memmap.map_end = memmap.map + mapsize; + efi.memmap = memmap; + /* boot time idmap_pg_dir is incomplete, so fill in missing parts */ efi_setup_idmap(); } @@ -379,23 +388,15 @@ static int __init arm64_enter_virtual_mode(void) return -1; } - mapsize = memmap.map_end - memmap.map; - early_memunmap(memmap.map, mapsize); - if (efi_runtime_disabled()) { pr_info(EFI runtime services will be disabled.\n); return -1; } pr_info(Remapping and enabling EFI services.\n); - /* replace early memmap mapping with permanent mapping */ - memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, - mapsize); - memmap.map_end = memmap.map + mapsize; - - efi.memmap = memmap; /* Map the runtime regions */ + mapsize = memmap.map_end - memmap.map; virtmap = kmalloc(mapsize, GFP_KERNEL); if (!virtmap) { pr_err(Failed to allocate EFI virtual memmap\n); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index b809911..ebf7820 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -401,7 +401,7 @@ void __init setup_arch(char **cmdline_p) paging_init(); request_standard_resources(); - efi_idmap_init(); + efi_memmap_init(); unflatten_device_tree(); -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] arm64: call early_ioremap_reset() in paging_init()
arm64 does not support early_memremap/memunmap/ioremap/iounmap after paging_init() has been called. The core early_*remap code handles this via the after_paging_init variable, which is set by a call to early_ioremap_reset(). However, arm64 currently does not call early_ioremap_reset(), which has made it possible to poke around in the fixmap region after kmap is enabled. Add the required call. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Fixes: bf4b558eba92 (arm64: add early_ioremap support) Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/mm/mmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 6032f3e..506544f 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -348,6 +348,7 @@ void __init paging_init(void) { void *zero_page; + early_ioremap_reset(); map_mem(); /* -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] arm64: don't call early_*map() post paging_init()
This (tiny) series resolves a fairly serious problem with early_ioremap/iounmap/memremap/memunmap on arm64. These functions cannot safely be called after paging_init(), but the sanity check was not triggering. As a result, a fixmap entry was incorrectly cleared during early_initcalls on arm64 UEFI systems. 1/2 reworks the arm64 UEFI support code to not attempt these calls and 2/2 enables the sanity check Changes since v1: - Rebased to v3.19-rc3 - Added 'Fixes:' tags - Reworked 1/2 to restore call to efi_setup_idmap() to the original location in the boot process. Leif Lindholm (2): arm64: don't make early_*map() calls post paging_init() arm64: call early_ioremap_reset() in paging_init() arch/arm64/include/asm/efi.h | 4 ++-- arch/arm64/kernel/efi.c | 27 ++- arch/arm64/kernel/setup.c| 2 +- arch/arm64/mm/mmu.c | 1 + 4 files changed, 18 insertions(+), 16 deletions(-) -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/2] arm64: don't call early_*map() post paging_init()
On Tue, Jan 06, 2015 at 02:04:50PM +, Ard Biesheuvel wrote: Changes since v1: - Rebased to v3.19-rc3 - Added 'Fixes:' tags - Reworked 1/2 to restore call to efi_setup_idmap() to the original location in the boot process. Looks reasonable to me; do they need a CC stable, Yes, but with a note that both patches should be taken and the order is retained, or we break bisect. Where would one add such a note? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 5/8] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB
On Mon, Dec 22, 2014 at 10:59:01AM +, Ard Biesheuvel wrote: Set EFI_ALLOC_ALIGN to 64 KB so that all allocations done by the stub are naturally compatible with a 64 KB granule kernel. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/include/asm/efi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a34fd3b12e2b..71291253114f 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -44,4 +44,6 @@ extern void efi_idmap_init(void); #define efi_call_early(f, ...) sys_table_arg-boottime-f(__VA_ARGS__) +#define EFI_ALLOC_ALIGN SZ_64K + #endif /* _ASM_EFI_H */ -- 1.8.3.2 Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
On Mon, Jan 05, 2015 at 04:54:02PM +, Matt Fleming wrote: +static efi_status_t get_memory_map(efi_system_table_t *sys_table_arg, + efi_memory_desc_t **map, + unsigned long *map_size, + unsigned long *desc_size, + u32 *desc_ver, unsigned long *key_ptr) +{ + efi_status_t status; + + /* +* Call get_memory_map() with 0 size to retrieve the size of the +* required allocation. +*/ + *map_size = 0; + status = efi_call_early(get_memory_map, map_size, NULL, + key_ptr, desc_size, desc_ver); + if (status != EFI_BUFFER_TOO_SMALL) + return EFI_LOAD_ERROR; + + /* +* Add an additional efi_memory_desc_t to map_size because we're doing +* an allocation which may be in a new descriptor region. Then double it +* to give us some scratch space to prepare the input virtmap to give +* to SetVirtualAddressMap(). Note that this is EFI_LOADER_DATA memory, +* and the kernel memblock_reserve()'s only the size of the actual +* memory map, so the scratch space is freed again automatically. +*/ + *map_size += *desc_size; + status = efi_call_early(allocate_pool, EFI_LOADER_DATA, + *map_size * 2, (void **)map); + if (status != EFI_SUCCESS) + return status; + + status = efi_call_early(get_memory_map, map_size, *map, + key_ptr, desc_size, desc_ver); + if (status != EFI_SUCCESS) + efi_call_early(free_pool, *map); + return status; +} We've now got two (slightly different) versions of this function. Is there any way we could make do with just one? I think all we really need above what efi_get_memory_map() provides is the scratch space. Would we care about temporarily wasting a little bit of EFI_LOADER_DATA on all platforms, or could we just swap the function body in efi-stub-helper.c for Ard's version above? (I would guess memory maps with = 32 entries are uncommon anyway, so the existing version would already make the bootservice call twice.) +/* + * This is the base address at which to start allocating virtual memory ranges + * for UEFI Runtime Services. This is a userland range so that we can use any + * allocation we choose, and eliminate the risk of a conflict after kexec. + */ +#define EFI_RT_VIRTUAL_BASE0x4000 + +static void update_memory_map(efi_memory_desc_t *memory_map, + unsigned long map_size, unsigned long desc_size, + int *count) +{ + u64 efi_virt_base = EFI_RT_VIRTUAL_BASE; + efi_memory_desc_t *out = (void *)memory_map + map_size; + int l; + + for (l = 0; l map_size; l += desc_size) { + efi_memory_desc_t *in = (void *)memory_map + l; + u64 paddr, size; + + if (!(in-attribute EFI_MEMORY_RUNTIME)) + continue; + + /* +* Make the mapping compatible with 64k pages: this allows +* a 4k page size kernel to kexec a 64k page size kernel and +* vice versa. +*/ + paddr = round_down(in-phys_addr, SZ_64K); + size = round_up(in-num_pages * EFI_PAGE_SIZE + + in-phys_addr - paddr, SZ_64K); + + /* +* Avoid wasting memory on PTEs by choosing a virtual base that +* is compatible with section mappings if this region has the +* appropriate size and physical alignment. (Sections are 2 MB +* on 4k granule kernels) +*/ + if (IS_ALIGNED(in-phys_addr, SZ_2M) size = SZ_2M) + efi_virt_base = round_up(efi_virt_base, SZ_2M); + + in-virt_addr = efi_virt_base + in-phys_addr - paddr; + efi_virt_base += size; + + memcpy(out, in, desc_size); + out = (void *)out + desc_size; + ++*count; + } +} + fdt.c is starting to become a dumping ground for arm*-specific stuff :-( Mmm, not optimal. That said, the only arm*-specific things about this particular function are the page sizes. Should this move to efi-stub-helper.c with EFI_RT_VIRTUAL_BASE moved to arch/x/include/asm/efi.h and joined by EFI_RT_VIRTUAL_BASE_ALIGN and EFI_RT_VIRTUAL_REGION_ALIGN? Is there no general solution for sharing code between arm and aarch64 in the kernel so we don't have to stick things like this in drivers/firmware/efi/? Not currently. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 7/8] arm64/efi: remove free_boot_services() and friends
; - if (free_start = free_end) - free_start = 0; - } - } - if (free_start) - total_freed += free_region(free_start, free_end); - - if (total_freed) - pr_info(Freed 0x%llx bytes of EFI boot services memory, - total_freed); -} - void __init efi_init(void) { struct efi_fdt_params params; @@ -396,8 +277,6 @@ static int __init arm64_enter_virtual_mode(void) } set_bit(EFI_SYSTEM_TABLES, efi.flags); - free_boot_services(); - if (!efi_enabled(EFI_VIRTMAP)) { pr_err(No UEFI virtual mapping was installed -- runtime services will not be available\n); return -1; -- 1.8.3.2 Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
On Mon, Jan 05, 2015 at 04:20:16PM +, Mark Rutland wrote: Hi Ard, I have a few (minor) comments below. On Mon, Dec 22, 2014 at 10:59:02AM +, Ard Biesheuvel wrote: In order to support kexec, the kernel needs to be able to deal with the state of the UEFI firmware after SetVirtualAddressMap() has been called. To avoid having separate code paths for non-kexec and kexec, let's move the call to SetVirtualAddressMap() to the stub: this will guarantee us that it will only be called once (since the stub is not executed during kexec), and ensures that the UEFI state is identical between kexec and normal boot. This implies that the layout of the virtual mapping needs to be created by the stub as well. All regions are rounded up to a naturally aligned multiple of 64 KB (for compatibility with 64k pages kernels) and recorded in the UEFI memory map. The kernel proper reads those values and installs the mappings in a dedicated set of page tables that are swapped in during UEFI Runtime Services calls. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/include/asm/efi.h | 20 +++- arch/arm64/kernel/efi.c| 223 - arch/arm64/kernel/setup.c | 1 + drivers/firmware/efi/libstub/fdt.c | 137 ++- 4 files changed, 270 insertions(+), 111 deletions(-) [...] +static void efi_set_pgd(struct mm_struct *mm) +{ + cpu_switch_mm(mm-pgd, mm); + flush_tlb_all(); + if (icache_is_aivivt()) + __flush_icache_all(); +} Do we have any idea how often we call runtime services? Very rarely. I assume not all that often (read the RTC at boot, set/get variables). And in future possibly: - adding capsules - getwakeuptime/setwakeuptime - saving time to RTC on shutdown - reboot All of which are uid0-invoked manual operations. The only exception I can think of is if we're using the efivarfs backend for pstore. If we're nuking the TLBs and I-cache a lot we'll probably need to reserve an asid for the EFI virtmap. @@ -248,12 +337,52 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, } } + /* +* Update the memory map with virtual addresses. The function will also +* populate the spare second half of the memory_map allocation with +* copies of just the EFI_MEMORY_RUNTIME entries so that we can pass it +* straight into SetVirtualAddressMap() +*/ + update_memory_map(memory_map, map_size, desc_size, + runtime_entry_count); + + pr_efi(sys_table, + Exiting boot services and installing virtual address map...\n); I believe that the memory map is allowed to change as a result of this call, so I think this needs to be moved before update_memory_map. You are absolutely correct - but update_memory_map() only modifies the copy of the memory map. The message needs to move all the way to before the calll to get_memory_map(), and for practical reasons perhaps before the while(1) loop. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] arm64: call early_ioremap_reset() in paging_init()
arm64 does not support early_memremap/memunmap/ioremap/iounmap after paging_init() has been called. The core early_*remap code handles this via the after_paging_init variable, which is set by a call to early_ioremap_reset(). However, arm64 currently does not call early_ioremap_reset(), which has made it possible to poke around in the fixmap region after kmap is enabled. Add the required call. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/mm/mmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 6032f3e..506544f 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -348,6 +348,7 @@ void __init paging_init(void) { void *zero_page; + early_ioremap_reset(); map_mem(); /* -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] arm64: don't make early_*map() calls post paging_init()
arm64 early_ioremap/iounmap/memremap/memunmap are not supported beyond the call to paging_init(), but arm64_enter_virtual_mode() (an early initcall) makes one call to unmap the UEFI memory map. Rearrange the code to unmap this region before paging_init(). Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/kernel/efi.c | 12 +++- arch/arm64/kernel/setup.c | 2 -- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 6fac253..790adb5 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -317,15 +317,8 @@ void __init efi_init(void) return; reserve_regions(); -} - -void __init efi_idmap_init(void) -{ - if (!efi_enabled(EFI_BOOT)) - return; - /* boot time idmap_pg_dir is incomplete, so fill in missing parts */ - efi_setup_idmap(); + early_memunmap(memmap.map, params.mmap_size); } static int __init remap_region(efi_memory_desc_t *md, void **new) @@ -380,7 +373,6 @@ static int __init arm64_enter_virtual_mode(void) } mapsize = memmap.map_end - memmap.map; - early_memunmap(memmap.map, mapsize); if (efi_runtime_disabled()) { pr_info(EFI runtime services will be disabled.\n); @@ -393,6 +385,8 @@ static int __init arm64_enter_virtual_mode(void) mapsize); memmap.map_end = memmap.map + mapsize; + efi_setup_idmap(); + efi.memmap = memmap; /* Map the runtime regions */ diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index b809911..c7eb3c5 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -401,8 +401,6 @@ void __init setup_arch(char **cmdline_p) paging_init(); request_standard_resources(); - efi_idmap_init(); - unflatten_device_tree(); psci_init(); -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] arm64: don't call early_*map() post paging_init()
This (tiny) series resolves a fairly serious problem with early_ioremap/iounmap/memremap/memunmap on arm64. These functions cannot safely be called after paging_init(), but the sanity check was not triggering. As a result, a fixmap entry was incorrectly cleared during early_initcalls on arm64 UEFI systems. 1/2 reworks the arm64 UEFI support code to not attempt these calls and 2/2 enables the sanity check Leif Lindholm (2): arm64: don't make early_*map() calls post paging_init() arm64: call early_ioremap_reset() in paging_init() arch/arm64/kernel/efi.c | 12 +++- arch/arm64/kernel/setup.c | 2 -- arch/arm64/mm/mmu.c | 1 + 3 files changed, 4 insertions(+), 11 deletions(-) -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC] fs: make efivarfs a pseudo filesystem, built by default with EFI
efivars is currently enabled under MISC_FILESYSTEMS, which is decribed as such as filesystems that came from other operating systems. In reality, it is a pseudo filesystem, providing access to the kernel UEFI variable interface. Since this is the preferred interface for accessing UEFI variables, over the legacy efivars interface, also build it by default as a module if CONFIG_EFI. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- fs/Kconfig | 2 +- fs/efivarfs/Kconfig | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/Kconfig b/fs/Kconfig index 664991a..a6bb530 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -165,6 +165,7 @@ config HUGETLB_PAGE def_bool HUGETLBFS source fs/configfs/Kconfig +source fs/efivarfs/Kconfig endmenu @@ -209,7 +210,6 @@ source fs/sysv/Kconfig source fs/ufs/Kconfig source fs/exofs/Kconfig source fs/f2fs/Kconfig -source fs/efivarfs/Kconfig endif # MISC_FILESYSTEMS diff --git a/fs/efivarfs/Kconfig b/fs/efivarfs/Kconfig index 367bbb1..c2499ef 100644 --- a/fs/efivarfs/Kconfig +++ b/fs/efivarfs/Kconfig @@ -1,6 +1,7 @@ config EFIVAR_FS tristate EFI Variable filesystem depends on EFI + default m help efivarfs is a replacement filesystem for the old EFI variable support via sysfs, as it doesn't suffer from the -- 2.1.3 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 09/10] arm64: dmi: set DMI string as dump stack arch description
On Tue, Oct 28, 2014 at 05:18:42PM +0100, Ard Biesheuvel wrote: This sets the DMI string, containing system type, serial number, firmware version etc. as dump stack arch description, so that oopses and other kernel stack dumps automatically have this information included, if available. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- arch/arm64/kernel/efi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 9ae5e7918b8f..6fac253bc783 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -479,6 +479,8 @@ static int __init arm64_dmi_init(void) * itself, depends on dmi_scan_machine() having been called already. */ dmi_scan_machine(); + if (dmi_available) + dmi_set_dump_stack_arch_desc(); return 0; } core_initcall(arm64_dmi_init); -- 1.8.3.2 Tested-by/Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] dmi: add support for SMBIOS 3.0 64-bit entry point
On Wed, Oct 29, 2014 at 04:11:25PM +0100, Ard Biesheuvel wrote: The DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point, which enables support for SMBIOS structure tables residing at a physical offset over 4 GB. This is especially important for upcoming arm64 platforms whose system RAM resides entirely above the 4 GB boundary. For the UEFI case, this code attempts to detect the new SMBIOS 3.0 header magic at the offset passed in the SMBIOS3_TABLE_GUID UEFI configuration table. If this configuration table is not provided, or if we fail to parse the header, we fall back to using the legacy SMBIOS_TABLE_GUID configuration table. This is in line with the spec, that allows both configuration tables to be provided, but mandates that they must point to the same structure table, unless the version pointed to by the 64-bit entry point is a superset of the 32-bit one. For the non-UEFI case, the detection logic is modified to look for the SMBIOS 3.0 header magic before it looks for the legacy header magic. Note that this patch is based on version 3.0.0d [draft] of the specification, which is expected not to deviate from the final version in ways that would affect the correctness of this implementation. Tested-by: Suravee Suthikulpanit suravee.suthikulpa...@amd.com Acked-by: Leif Lindholm leif.lindh...@linaro.org Also, for SMBIOS 2 on X64 Ovmf and FVP Base AEMv8-A (with UEFI), Tested-by: Leif Lindholm leif.lindh...@linaro.org Cc: Andrew Morton a...@linux-foundation.org Cc: Tony Luck tony.l...@intel.com Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- v2: since dmi_base is now a phys_addr_t, prevent surprises caused by GCC's type promotion rules by replacing the open coded shifts/ORs with get_unaligned_leXX() --- drivers/firmware/dmi_scan.c | 79 + 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 17afc51f3054..f617badc2698 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num, const struct dmi_header *dm = (const struct dmi_header *)data; /* + * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0] + */ + if (dm-type == 127) + break; + + /* * We want to know the total length (formatted area and * strings) before decoding to make sure we won't run off the * table in dmi_decode or dmi_string @@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } } -static u32 dmi_base; +static phys_addr_t dmi_base; static u16 dmi_len; static u16 dmi_num; @@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf) if (memcmp(buf, _SM_, 4) == 0 buf[5] 32 dmi_checksum(buf, buf[5])) { - smbios_ver = (buf[6] 8) + buf[7]; + smbios_ver = get_unaligned_be16(buf + 6); /* Some BIOS report weird SMBIOS version, fix that up */ switch (smbios_ver) { @@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf) buf += 16; if (memcmp(buf, _DMI_, 5) == 0 dmi_checksum(buf, 15)) { - dmi_num = (buf[13] 8) | buf[12]; - dmi_len = (buf[7] 8) | buf[6]; - dmi_base = (buf[11] 24) | (buf[10] 16) | - (buf[9] 8) | buf[8]; + dmi_num = get_unaligned_le16(buf + 12); + dmi_len = get_unaligned_le16(buf + 6); + dmi_base = get_unaligned_le32(buf + 8); if (dmi_walk_early(dmi_decode) == 0) { if (smbios_ver) { @@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf) return 1; } +/* + * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy + * 32-bit entry point, there is no embedded DMI header (_DMI_) in here. + */ +static int __init dmi_smbios3_present(const u8 *buf) +{ + if (memcmp(buf, _SM3_, 5) == 0 + buf[6] 32 dmi_checksum(buf, buf[6])) { + dmi_ver = get_unaligned_be16(buf + 7); + dmi_len = get_unaligned_le32(buf + 12); + dmi_base = get_unaligned_le64(buf + 16); + + /* + * The 64-bit SMBIOS 3.0 entry point no longer has a field + * containing the number of structures present in the table. + * Instead, it defines the table size as a maximum size, and + * relies on the end-of-table structure type (#127) to be used + * to signal the end of the table. + * So let's define dmi_num as an upper bound as well: each + * structure has a 4 byte header, so dmi_len / 4 is an upper + * bound for the number
Re: [PATCH v2 08/10] arm64: dmi: Add SMBIOS/DMI support
On Tue, Oct 28, 2014 at 05:18:41PM +0100, Ard Biesheuvel wrote: From: Yi Li yi...@linaro.org SMBIOS is important for server hardware vendors. It implements a spec for providing descriptive information about the platform. Things like serial numbers, physical layout of the ports, build configuration data, and the like. Signed-off-by: Yi Li yi...@linaro.org Tested-by: Suravee Suthikulpanit suravee.suthikulpa...@amd.com Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org On FVP Base AEMv8-A (UEFI), and qemu (-kernel, so non-UEFI): Tested-by: Leif Lindholm leif.lindh...@linaro.org --- A short history of this patch: v4: Moved call to dmi_scan_machine() to separate core_initcall(), so that it is called unconditionally, i.e., even if UEFI fails to initialize. Otherwise, any drivers that attempt to consult DMI info for quirks handling start spewing errors, as Catalin unfortunately found out after merging (and subsequently reverting) this patch for the second time. v3: Moved call to dmi_scan_machine() into arm64_enter_virtual_mode(). This is necessary, because dmi_scan_machine() needs to be called before dmi_id_init(), which itself is invoked using an arch_initcall(). DMI depends on UEFI on arm64, so it is legal to only invoke dmi_scan_machine() when building with UEFI support. However, calling it from arm64_enter_virtual_mode() was a mistake, as it could result in dmi_scan_machine() not being called at all. v2: Use efi_lookup_mapped_addr() to obtain the virtual address of the SMBIOS structure table instead of calling ioremap_cache(). This seemed a good idea at the time, as the UEFI memory map covers those regions, so the virtual mapping should be known as well. However, this is only true if the firmware has requested a virtual remapping of the region by setting the EFI_MEMORY_RUNTIME bit, which Tianocore/EDK2 appears to do, but violates the UEFI spec. (In general, UEFI Configuration Tables loaded at boot time (e.g., SMBIOS table) can be contained in memory of type EfiRuntimeServicesData (recommended and the system firmware must not request a virtual mapping), [...], section 2.3.6, UEFI spec v2.4B). This version was merged into the arm64 for-next/core branch and reverted again per our request. --- arch/arm64/Kconfig | 11 +++ arch/arm64/include/asm/dmi.h | 31 +++ arch/arm64/kernel/efi.c | 13 + 3 files changed, 55 insertions(+) create mode 100644 arch/arm64/include/asm/dmi.h diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9532f8d5857e..2c3c2ca6f8bc 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -401,6 +401,17 @@ config EFI allow the kernel to be booted as an EFI application. This is only useful on systems that have UEFI firmware. +config DMI + bool Enable support for SMBIOS (DMI) tables + depends on EFI + default y + help + This enables SMBIOS/DMI feature for systems. + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + endmenu menu Userspace binary formats diff --git a/arch/arm64/include/asm/dmi.h b/arch/arm64/include/asm/dmi.h new file mode 100644 index ..69d37d87b159 --- /dev/null +++ b/arch/arm64/include/asm/dmi.h @@ -0,0 +1,31 @@ +/* + * arch/arm64/include/asm/dmi.h + * + * Copyright (C) 2013 Linaro Limited. + * Written by: Yi Li (yi...@linaro.org) + * + * based on arch/ia64/include/asm/dmi.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef __ASM_DMI_H +#define __ASM_DMI_H + +#include linux/io.h +#include linux/slab.h + +/* + * According to section 2.3.6 of the UEFI spec, the firmware should not + * request a virtual mapping for configuration tables such as SMBIOS. + * This means we have to map them before use. + */ +#define dmi_early_remap(x, l)ioremap_cache(x, l) +#define dmi_early_unmap(x, l)iounmap(x) +#define dmi_remap(x, l) ioremap_cache(x, l) +#define dmi_unmap(x) iounmap(x) +#define dmi_alloc(l) kzalloc(l, GFP_KERNEL) + +#endif diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 558572ef1ea3..9ae5e7918b8f 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,6 +11,7 @@ * */ +#include linux/dmi.h #include linux/efi.h #include linux/export.h #include linux/memblock.h @@ -469,3 +470,15 @@ err_unmap: return -1; } early_initcall(arm64_enter_virtual_mode); + +static int __init arm64_dmi_init(void
Re: [PATCH 2/2] dmi: add support for SMBIOS 3.0 64-bit entry point
= dmi_early_remap(efi.smbios3, 32); + if (p == NULL) + goto error; + memcpy_fromio(buf, p, 32); + dmi_early_unmap(p, 32); + + if (!dmi_smbios3_present(buf)) { + dmi_available = 1; + goto out; + } + } if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto error; @@ -552,7 +618,7 @@ void __init dmi_scan_machine(void) memset(buf, 0, 16); for (q = p; q p + 0x1; q += 16) { memcpy_fromio(buf + 16, q, 16); - if (!dmi_present(buf)) { + if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { dmi_available = 1; dmi_early_unmap(p, 0x1); goto out; -- 1.8.3.2 Apart from that one comment: Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
On Thu, Oct 16, 2014 at 06:35:42PM +0200, Ard Biesheuvel wrote: This adds support to the UEFI side for detecting the presence of a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS structure table to reside at a physical offset over 4 GB, which cannot be supported by the legacy SMBIOS 32-bit entry point. Since the firmware can legally provide both entry points, store the SMBIOS 3.0 entry point in a separate variable, and let the DMI decoding layer decide which one will be used. Tested-by: Suravee Suthikulpanit suravee.suthikulpa...@amd.com Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- drivers/firmware/efi/efi.c | 4 include/linux/efi.h| 6 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 64ecbb501c50..3947caccff2d 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -30,6 +30,7 @@ struct efi __read_mostly efi = { .acpi = EFI_INVALID_TABLE_ADDR, .acpi20 = EFI_INVALID_TABLE_ADDR, .smbios = EFI_INVALID_TABLE_ADDR, + .smbios3= EFI_INVALID_TABLE_ADDR, .sal_systab = EFI_INVALID_TABLE_ADDR, .boot_info = EFI_INVALID_TABLE_ADDR, .hcdp = EFI_INVALID_TABLE_ADDR, @@ -64,6 +65,8 @@ static ssize_t systab_show(struct kobject *kobj, str += sprintf(str, ACPI=0x%lx\n, efi.acpi); if (efi.smbios != EFI_INVALID_TABLE_ADDR) str += sprintf(str, SMBIOS=0x%lx\n, efi.smbios); + if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, SMBIOS3=0x%lx\n, efi.smbios3); The specification also refers to it as the less version-sensitive 64-bit entry point. Would it make sense to instead call it SMBIOS64/efi.smbios64? if (efi.hcdp != EFI_INVALID_TABLE_ADDR) str += sprintf(str, HCDP=0x%lx\n, efi.hcdp); if (efi.boot_info != EFI_INVALID_TABLE_ADDR) @@ -238,6 +241,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {MPS_TABLE_GUID, MPS, efi.mps}, {SAL_SYSTEM_TABLE_GUID, SALsystab, efi.sal_systab}, {SMBIOS_TABLE_GUID, SMBIOS, efi.smbios}, + {SMBIOS3_TABLE_GUID, SMBIOS 3.0, efi.smbios3}, {UGA_IO_PROTOCOL_GUID, UGA, efi.uga}, {NULL_GUID, NULL, NULL}, }; diff --git a/include/linux/efi.h b/include/linux/efi.h index 45cb4ffdea62..8760b9aed2bb 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -542,6 +542,9 @@ void efi_native_runtime_setup(void); #define SMBIOS_TABLE_GUID\ EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) +#define SMBIOS3_TABLE_GUID\ +EFI_GUID( 0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 ) + #define SAL_SYSTEM_TABLE_GUID\ EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) @@ -805,7 +808,8 @@ extern struct efi { unsigned long mps; /* MPS table */ unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ unsigned long acpi20; /* ACPI table (ACPI 2.0) */ - unsigned long smbios; /* SM BIOS table */ + unsigned long smbios; /* SM BIOS table (32 bit entry point) */ + unsigned long smbios3; /* SM BIOS table (64 bit entry point) */ unsigned long sal_systab; /* SAL system table */ unsigned long boot_info;/* boot info table */ unsigned long hcdp; /* HCDP table */ -- 1.8.3.2 Again, Apart from the one comment: Acked-by: Leif Lindholm leif.lindh...@linaro.org -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH] dmi: add support for SMBIOS 3.0 64-bit entry point
On Mon, Oct 13, 2014 at 03:48:33PM +0200, Ard Biesheuvel wrote: Version 3.0 of the DTMF SMBIOS reference spec defines a new entry point type that supports a 64-bit address for the SMBIOS structure table. This is needed by platforms whose system RAM resides above the 4 GB physical address boundary, such as upcoming 64-bit ARM platforms. This is a preliminary RFC implementation, as there is no definition available yet for SMBIOS3_TABLE_GUID, which the (currently still in draft) SMBIOS v3.0 spec refers to. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org --- goto out; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 8590099ac148..9035c1b74d58 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -30,6 +30,7 @@ struct efi __read_mostly efi = { .acpi = EFI_INVALID_TABLE_ADDR, .acpi20 = EFI_INVALID_TABLE_ADDR, .smbios = EFI_INVALID_TABLE_ADDR, + .smbios3= EFI_INVALID_TABLE_ADDR, Is there any particular need to add a separate pointer for v3? In both cases, the pointer is a physical address stored as an unsigned long. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] arm64: ignore DT memreserve entries when booting in UEFI mode
On Mon, Jul 28, 2014 at 07:14:49PM +0100, Mark Rutland wrote: On Mon, Jul 28, 2014 at 07:03:03PM +0100, Leif Lindholm wrote: UEFI provides its own method for marking regions to reserve, via the memory map which is also used to initialise memblock. So when using the UEFI memory map, ignore any memreserve entries present in the DT. It's worth noting that no-one is relying on this at present, and were they it would imply that their UEFI implementation is broken (providing a dodgy memory map). So before people start doing dodgy things, let's, close that hole. If we need a way of modifying the memory map we should come up with a more general plan. Catalin - any comments? As it is a bugfix, can it go into 3.17? / Leif Reported-by: Mark Rutland mark.rutl...@arm.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/kernel/efi.c |2 ++ arch/arm64/mm/init.c|4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 14db1f6..7ad17b2 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -188,6 +188,8 @@ static __init void reserve_regions(void) if (uefi_debug) pr_cont(\n); } + + set_bit(EFI_MEMMAP, efi.flags); Nothing outside of arch/x86 seems to hang off this, so using it here looks fine. } diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index e90c542..58dbf2e 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -32,6 +32,7 @@ #include linux/of_fdt.h #include linux/dma-mapping.h #include linux/dma-contiguous.h +#include linux/efi.h #include asm/sections.h #include asm/setup.h @@ -151,7 +152,8 @@ void __init arm64_memblock_init(void) memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); - early_init_fdt_scan_reserved_mem(); + if (!efi_enabled(EFI_MEMMAP)) + early_init_fdt_scan_reserved_mem(); And this is a false stub for !EFI, so that looks fine. FWIW: Reviewed-by: Mark Rutland mark.rutl...@arm.com I wonder if we have any other flat tree uses we need to be careful of when booting via EFI. -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/3 v2] arm64/efi: improve TEXT_OFFSET handling
On Wed, Jul 30, 2014 at 12:59:01PM +0200, Ard Biesheuvel wrote: Resending this series sent out yesterday with only minor changes and acks etc added. In summary: patch #3 relaxes the requirements imposed by the EFI stub on where Image may be loaded, but this breaks APM Mustang (if booting via UEFI) if patch #1 does not go in first. Patch #2 prevents potential boot issues when Image is loaded such that the stub does not have to relocate it. @Will: as discussed on the list yesterday, these patches should be kept in sequence when going upstream, so it is best to take them through a single tree. However, patch #3 will not apply cleanly to the arm64 tree until after 3.16-rc1 is released as it depends on a trivial change going in through x86/tip [efi]. [https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/commit/?h=nextid=6091c9c447370c4717ec9975813c874af490eb36] If you are ok with these patches, how would you like to proceed? Patches #1 and #2 could go in straight away (through arm64), and I can send Catalin and you a gentle reminder once -rc1 is released to take #3? Or instead, ack them and ask Matt to queue them for 3.17-late? It would be nice if this makes 3.17 as it fixes actual boot problems on hardware that is under development. Changes in v2: - add (__force void *) cast to patch #1, as suggested in LAKML discussion - add tested-by/acked-by lines - rebased patch #3 onto efi-next Mark Rutland (1): arm64: spin-table: handle unmapped cpu-release-addrs Ard Biesheuvel (2): arm64/efi: efistub: cover entire static mem footprint in PE/COFF .text arm64/efi: efistub: don't abort if base of DRAM is occupied arch/arm64/kernel/efi-stub.c | 18 ++ arch/arm64/kernel/head.S | 6 +++--- arch/arm64/kernel/smp_spin_table.c | 21 - 3 files changed, 25 insertions(+), 20 deletions(-) -- 1.8.3.2 Since this set fixes two separate bugs on actual hardware platforms, for the entire set - for what it's worth: Acked-by: Leif Lindholm leif.lindh...@linaro.org Tested-by: Leif Lindholm leif.lindh...@linaro.org / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] UEFI arm64: add noefi boot param
On Wed, Aug 06, 2014 at 04:38:25PM +0800, Dave Young wrote: Adding a noefi boot param like in X86 to disable efi runtime services support. This will be useful for debugging uefi problems. Also it will be useful for later kexec/kdump work. Kexec on uefi support in X86 depends on a fixed vm area specific for uefi runtime 1:1 mapping, kernel will switch to a different page table for any uefi runtime callback in virtual mode. In arm64 similar work probably is necessary. But kexec boot will just works with 'noefi' with the limitaion of lacking runtime services. The runtime services is not critical for kdump kernel for now. So as for kexec/kdump just leave the 1:1 mapping a future work. Since this is really turning an x86-specific feature into a generic one, could it be moved to core code? Maybe an efi.mask, reusing the efi_enabled defines, with an efi_disabled macro? Also, since this patch (and its x86 predecessor) is not really noefi, could this be integrated with the efi= patch (http://permalink.gmane.org/gmane.linux.kernel.efi/4405), as an efi=noruntime option? On x86, due to CSM, noefi was a useful fallback for completely broken (U)EFI implementations - but on an arm* UEFI system, there will be no fallback. Could it be wrapped in a kernel hacking config option? Partial code description, not even compile tested: --- diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 14db1f6..a295a5c 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -386,7 +386,7 @@ static int __init arm64_enter_virtual_mode(void) int count = 0; unsigned long flags; - if (!efi_enabled(EFI_BOOT)) { + if (!efi_enabled(EFI_BOOT) || efi_disabled(EFI_RUNTIME_SERVICES)) { pr_info(EFI services will not be available.\n); return -1; } diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 87fc96b..b59a7c6 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -77,14 +77,6 @@ static efi_config_table_type_t arch_tables[] __initdata = { u64 efi_setup; /* efi setup_data physical address */ -static bool disable_runtime __initdata = false; -static int __init setup_noefi(char *arg) -{ - disable_runtime = true; - return 0; -} -early_param(noefi, setup_noefi); - int add_efi_memmap; EXPORT_SYMBOL(add_efi_memmap); @@ -764,7 +756,7 @@ void __init efi_init(void) if (!efi_runtime_supported()) pr_info(No EFI runtime due to 32/64-bit mismatch with kernel\n); else { - if (disable_runtime || efi_runtime_init()) + if (efi_disabled(EFI_RUNTIME_SERVICES) || efi_runtime_init()) return; } if (efi_memmap_init()) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index dc79346..ffc4a45 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -43,6 +43,15 @@ EXPORT_SYMBOL(efi); static struct kobject *efi_kobj; static struct kobject *efivars_kobj; +static int __init setup_noefi(char *arg) +{ +#if defined(CONFIG_X86) || defined(CONFIG_EFI_DEBUG) + set_bit(EFI_RUNTIME_SERVICES, efi.mask); +#endif + return 0; +} +early_param(noefi, setup_noefi); + /* * Let's not leave out systab information that snuck into * the efivars driver diff --git a/include/linux/efi.h b/include/linux/efi.h index 41bbf8b..9533d0e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -826,6 +826,7 @@ extern struct efi { efi_set_virtual_address_map_t *set_virtual_address_map; struct efi_memory_map *memmap; unsigned long flags; + unsigned long mask; } efi; static inline int @@ -926,6 +927,10 @@ static inline bool efi_enabled(int feature) { return test_bit(feature, efi.flags) != 0; } +static inline bool efi_disabled(int feature) +{ + return test_bit(feature, efi.mask) == 0; +} #else static inline bool efi_enabled(int feature) { --- / Leif Signed-off-by: Dave Young dyo...@redhat.com --- arch/arm64/kernel/efi.c | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) Index: linux-2.6/arch/arm64/kernel/efi.c === --- linux-2.6.orig/arch/arm64/kernel/efi.c +++ linux-2.6/arch/arm64/kernel/efi.c @@ -31,6 +31,14 @@ static efi_runtime_services_t *runtime; static u64 efi_system_table; +static bool disable_runtime __initdata = false; +static int __init setup_noefi(char *arg) +{ + disable_runtime = true; + return 0; +} +early_param(noefi, setup_noefi); + static int uefi_debug __initdata; static int __init uefi_debug_setup(char *str) { @@ -391,11 +399,14 @@ static int __init arm64_enter_virtual_mo return -1; } - pr_info(Remapping and enabling EFI services.\n); - - /* replace early memmap mapping with permanent mapping */ mapsize =
Re: [PATCH 1/2] UEFI arm64: add noefi boot param
On Wed, Aug 06, 2014 at 02:20:21PM +0100, Matt Fleming wrote: Since this is really turning an x86-specific feature into a generic one, could it be moved to core code? Maybe an efi.mask, reusing the efi_enabled defines, with an efi_disabled macro? Why the new efi_disabled() and efi.mask? This is all achievable with efi_enabled() and efi.flags, in fact, this kind of thing is exactly why they were invented. Because this flag is indicating which facilities we should not try to enable, rather than which facilities we have enabled. The EFI_RUNTIME_SERVICES flag is set after successful call to set_virtual_address_map. The apparent intent of noefi is to prevent that call from being made in the first place. Anyway, it was just a suggestion - main point was it would make sense to share the code. Also, since this patch (and its x86 predecessor) is not really noefi, could this be integrated with the efi= patch (http://permalink.gmane.org/gmane.linux.kernel.efi/4405), as an efi=noruntime option? On x86, due to CSM, noefi was a useful fallback for completely broken (U)EFI implementations - but on an arm* UEFI system, there will be no fallback. Could it be wrapped in a kernel hacking config option? I don't mind making noefi a synonym for efi=noruntime on x86, as long as we keep noefi around with the same semantics it's always had. Yeah, that would be nice. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] UEFI arm64: add noefi boot param
On Wed, Aug 06, 2014 at 03:18:14PM +0100, Matt Fleming wrote: On Wed, 06 Aug, at 04:10:45PM, Ard Biesheuvel wrote: Shouldn't we clear the bit here if we failed to enable runtime services for some reason? Other code may test the bit assuming that it signifies that runtime services have been enabled successfully, while this patch changes it to mean that we /intended/ to enable them, which is not quite the same thing. Yep, good catch. We need to do something similar for efi_runtime_init() on x86 too. Since we're now overlaying two different meanings onto the EFI_RUNTIME_SERVICES bit, could we add comments at set/clear points to explicitly state the intended action? I.e.: /* Set to attempt runtime services initialisation */ /* Clear to indicate runtime services will not be available */ / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] arm64: ignore DT memreserve entries when booting in UEFI mode
UEFI provides its own method for marking regions to reserve, via the memory map which is also used to initialise memblock. So when using the UEFI memory map, ignore any memreserve entries present in the DT. Reported-by: Mark Rutland mark.rutl...@arm.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/kernel/efi.c |2 ++ arch/arm64/mm/init.c|4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 14db1f6..7ad17b2 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -188,6 +188,8 @@ static __init void reserve_regions(void) if (uefi_debug) pr_cont(\n); } + + set_bit(EFI_MEMMAP, efi.flags); } diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index e90c542..58dbf2e 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -32,6 +32,7 @@ #include linux/of_fdt.h #include linux/dma-mapping.h #include linux/dma-contiguous.h +#include linux/efi.h #include asm/sections.h #include asm/setup.h @@ -151,7 +152,8 @@ void __init arm64_memblock_init(void) memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); - early_init_fdt_scan_reserved_mem(); + if (!efi_enabled(EFI_MEMMAP)) + early_init_fdt_scan_reserved_mem(); /* 4GB maximum for 32-bit only capable devices */ if (IS_ENABLED(CONFIG_ZONE_DMA)) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/7] arm: add UEFI support
This set adds support for UEFI platforms 32-bit ARM platforms, consisting of: - UEFI stub support Turns the kernel into a UEFI executable, able to launch without a dedicated bootloader. - UEFI runtime services Lets the kernel interact with services provided by firmware. (Used by 'efibootmgr' application.) - UEFI system descriptions For now, adds the ability to extract information about available RAM from UEFI rather than hard-wired in .dtb or on command line. This set depends on: - Ard Biesheuvel efi: efistub: Convert into static library About to go into linux-next, aiming for 3.17. - Mark Salterarm: use generic fixmap.h - Mark Salterarm: add early_ioremap support The bits shared with arm64 went into 3.16-rc1. Changes from previous version: - Stub and runtime services support now merged (like on arm64) - they are no longer functionally separable. - Some fixes and cleanup. Leif Lindholm (4): arm: break part of __soft_restart out into separate function arm: add new asm macro update_sctlr arm: efi: use strcmp instead of strncmp for fdt parsing init: efi: arm: enable (U)EFI runtime services on arm Roy Franz (3): arm: add strstr to compressed string.c arm: Disable stack protection for decompressor/stub arm: add [U]EFI support arch/arm/Kconfig | 21 ++ arch/arm/boot/compressed/.gitignore |2 + arch/arm/boot/compressed/Makefile | 23 +- arch/arm/boot/compressed/efi-header.S | 117 + arch/arm/boot/compressed/efi-stub.c | 92 +++ arch/arm/boot/compressed/head.S | 78 +- arch/arm/boot/compressed/string.c | 21 ++ arch/arm/include/asm/assembler.h | 14 ++ arch/arm/include/asm/efi.h| 47 arch/arm/include/asm/idmap.h |1 + arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 435 + arch/arm/kernel/efi_phys.S| 66 + arch/arm/kernel/process.c | 12 +- arch/arm/kernel/setup.c |7 +- arch/arm/mm/idmap.c | 15 ++ drivers/firmware/efi/libstub/fdt.c|5 +- init/main.c |4 + 18 files changed, 938 insertions(+), 24 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/7] arm: break part of __soft_restart out into separate function
Certain operations can be considered mandatory for any piece of code preparing to switch off the MMU. Break this out into separate function idmap_prepare(). Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Suggested-by: Will Deacon will.dea...@arm.com Acked-by: Will Deacon will.dea...@arm.com --- arch/arm/include/asm/idmap.h |1 + arch/arm/kernel/process.c| 12 +--- arch/arm/mm/idmap.c | 15 +++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index bf863ed..2e914a8 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h @@ -10,5 +10,6 @@ extern pgd_t *idmap_pgd; void setup_mm_for_reboot(void); +void idmap_prepare(void); #endif /* __ASM_IDMAP_H */ diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 81ef686..6849e13 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -75,17 +75,7 @@ static void __soft_restart(void *addr) { phys_reset_t phys_reset; - /* Take out a flat memory mapping. */ - setup_mm_for_reboot(); - - /* Clean and invalidate caches */ - flush_cache_all(); - - /* Turn off caching */ - cpu_proc_fin(); - - /* Push out any further dirty data, and ensure cache is empty */ - flush_cache_all(); + idmap_prepare(); /* Switch to the identity mapping. */ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 8e0e52e..5c85779 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -122,3 +122,18 @@ void setup_mm_for_reboot(void) local_flush_tlb_all(); #endif } + +void idmap_prepare(void) +{ + /* Take out a flat memory mapping. */ + setup_mm_for_reboot(); + + /* Clean and invalidate caches */ + flush_cache_all(); + + /* Turn off caching */ + cpu_proc_fin(); + + /* Push out any further dirty data, and ensure cache is empty */ + flush_cache_all(); +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/7] arm: efi: use strcmp instead of strncmp for fdt parsing
The existing shared EFI arm/arm64 stub code uses strncmp when parsing the device tree. Since this function is missing from arm zImage, use strcmp instead, rather than growing the zImage further. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/libstub/fdt.c |5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index a56bb35..399374b 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -58,14 +58,13 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, prev = 0; for (;;) { const char *type; - int len; node = fdt_next_node(fdt, prev, NULL); if (node 0) break; - type = fdt_getprop(fdt, node, device_type, len); - if (type strncmp(type, memory, len) == 0) { + type = fdt_getprop(fdt, node, device_type, NULL); + if (type strcmp(type, memory) == 0) { fdt_del_node(fdt, node); continue; } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/7] arm: Disable stack protection for decompressor/stub
From: Roy Franz roy.fr...@linaro.org The ARM decompressor/EFI stub do not implement the functions (__stack_chk_guard_setup, etc) that are required for support of stack protection. The actual enablement of stack protection is controlled by heuristics in GCC, which the code added for the EFI stub triggers when CONFIG_STACKPROTECTOR is set. Even with CONFIG_STACKPROTECTOR set, the decompressor was never compiled with stack protection actually enabled. Adding -fno-stack-protector to the decompressor/stub build keeps it building without stack protection as it has always been built. The x86 decompressor/stub is also built with -fno-stack-protector. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/boot/compressed/Makefile |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 68c9183..27536b1 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -121,7 +121,7 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) endif -ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj) +ccflags-y := -fpic -mno-single-pic-base -fno-builtin -fno-stack-protector -I$(obj) asflags-y := -DZIMAGE # Supply kernel BSS size to the decompressor via a linker symbol. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 7/7] init: efi: arm: enable (U)EFI runtime services on arm
Since the efi_set_virtual_address_map call has strict init ordering requirements, add an explicit hook in the required place. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- init/main.c |4 1 file changed, 4 insertions(+) diff --git a/init/main.c b/init/main.c index e8ae1fe..744d271 100644 --- a/init/main.c +++ b/init/main.c @@ -996,6 +996,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + lockup_detector_init(); smp_init(); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/7] arm: add new asm macro update_sctlr
A new macro for setting/clearing bits in the SCTLR. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Suggested-by: Will Deacon will.dea...@arm.com Acked-by: Will Deacon will.dea...@arm.com --- arch/arm/include/asm/assembler.h | 14 ++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 57f0584..c0cabba 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -425,4 +425,18 @@ THUMB( orr \reg , \reg , #PSR_T_BIT) #endif .endm +#ifdef CONFIG_CPU_CP15 +/* Macro for setting/clearing bits in sctlr */ + .macro update_sctlr, tmp:req, set=, clear= + mrc p15, 0, \tmp, c1, c0, 0 + .ifnc \set, + orr \tmp, \tmp, \set + .endif + .ifnc \clear, + bic \tmp, \tmp, \clear + .endif + mcr p15, 0, \tmp, c1, c0, 0 + .endm +#endif + #endif /* __ASM_ASSEMBLER_H__ */ -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/7] arm: add [U]EFI support
From: Roy Franz roy.fr...@linaro.org This patch adds EFI stub support for the ARM Linux kernel. The EFI stub operates similarly to the x86 stub: it is a shim between the EFI firmware and the normal zImage entry point, and sets up the environment that the zImage is expecting. This includes optionally loading the initrd and device tree from the system partition based on the kernel command line. Much of this code is shared with arm64. This patch also implements basic support for UEFI runtime services in the ARM architecture - a requirement for (among other things) using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning code. [Initial stub support] Signed-off-by: Roy Franz roy.fr...@linaro.org [Runtime Services support] Signed-off-by: Leif Lindholm leif.lindh...@linaro.org [Stub as static library] Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig | 21 ++ arch/arm/boot/compressed/.gitignore |2 + arch/arm/boot/compressed/Makefile | 21 +- arch/arm/boot/compressed/efi-header.S | 117 + arch/arm/boot/compressed/efi-stub.c | 92 +++ arch/arm/boot/compressed/head.S | 78 +- arch/arm/include/asm/efi.h| 47 arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 435 + arch/arm/kernel/efi_phys.S| 66 + arch/arm/kernel/setup.c |7 +- 11 files changed, 879 insertions(+), 9 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0f33848..78d8140b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2100,6 +2100,25 @@ config AUTO_ZRELADDR 0xf800. This assumes the zImage being placed in the first 128MB from start of memory. +config EFI_STUB + bool + +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN + select UCS2_STRING + select EARLY_IOREMAP + select EFI_PARAMS_FROM_FDT + select EFI_STUB + select EFI_ARMSTUB + ---help--- + This option provides support for runtime services provided + by UEFI firmware (such as non-volatile variables, realtime + clock, and platform reset). A UEFI stub is also provided to + allow the kernel to be booted as an EFI application. This + is only useful for kernels that may run on systems that have + UEFI firmware. + endmenu menu CPU Power Management @@ -2224,6 +2243,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index 0714e03..cc3487e 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -14,8 +14,10 @@ vmlinux.lds # borrowed libfdt files fdt.c fdt.h +fdt_empty_tree.c fdt_ro.c fdt_rw.c +fdt_sw.c fdt_wip.c libfdt.h libfdt_internal.h diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 27536b1..841d38f 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -91,7 +91,7 @@ suffix_$(CONFIG_KERNEL_LZ4) = lz4 # Borrowed libfdt files for the ATAG compatibility mode -libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c +libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c libfdt_hdrs:= fdt.h libfdt.h libfdt_internal.h libfdt_objs:= $(addsuffix .o, $(basename $(libfdt))) @@ -99,11 +99,26 @@ libfdt_objs := $(addsuffix .o, $(basename $(libfdt))) $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/% $(call cmd,shipped) -$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \ +$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o efi-stub.o): \ $(addprefix $(obj)/,$(libfdt_hdrs)) ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) -OBJS += $(libfdt_objs) atags_to_fdt.o +OBJS += atags_to_fdt.o +USE_LIBFDT = y +endif + +ifeq ($(CONFIG_EFI),y) +CFLAGS_efi-stub.o += -DTEXT_OFFSET=$(TEXT_OFFSET) +OBJS += efi-stub.o banner.o ../../../../drivers/firmware/efi/libstub/lib.a +USE_LIBFDT = y + +$(obj)/banner.o: OBJCOPYFLAGS=-j .rodata +$(obj)/banner.o: $(objtree)/init/version.o FORCE + $(call if_changed,objcopy) +endif + +ifeq ($(USE_LIBFDT),y) +OBJS += $(libfdt_objs) endif targets := vmlinux vmlinux.lds \ diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S new file mode 100644 index 000..dbb7101 --- /dev/null +++ b/arch/arm/boot
[PATCH 3/7] arm: add strstr to compressed string.c
From: Roy Franz roy.fr...@linaro.org The shared efi-stub-helper.c functions require a strstr implementation. The EFI stub is part of the decompressor, so it does not use the kernel strstr() implementation. This patch adds a strstr() implementation to the string.c file for the decompressor, with the implementation copied from the arch/x86/boot/string.c file used by the x86 decompressor. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Reviewed-by: Grant Likely grant.lik...@linaro.org --- arch/arm/boot/compressed/string.c | 21 + 1 file changed, 21 insertions(+) diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 36e53ef..5397792 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -111,6 +111,27 @@ char *strchr(const char *s, int c) return (char *)s; } +/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char *strstr(const char *s1, const char *s2) +{ + size_t l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *)s1; + l1 = strlen(s1); + while (l1 = l2) { + l1--; + if (!memcmp(s1, s2, l2)) + return (char *)s1; + s1++; + } + return NULL; +} #undef memset void *memset(void *s, int c, size_t count) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] efi/arm64: efistub: don't abort if base of DRAM is occupied
On Mon, Jul 14, 2014 at 02:40:48PM -0400, Mark Salter wrote: On Mon, 2014-07-14 at 17:25 +0200, Ard Biesheuvel wrote: If we fail to relocate the kernel Image to its preferred offset of TEXT_OFFSET bytes above the base of DRAM, accept the lowest alternative mapping available instead of aborting. We may lose a bit of memory at the low end, but we can still proceed normally otherwise. This breaks APM Mustang because the spin-table holding pen for secondary CPUs is marked as reserved memory in the TEXT_OFFSET area and the kernel placement using your patch makes it unreachable by kernel. Here is a patch I've been working with to solve the same problem: Hmm. The thing I don't like about the below approach is that it hard wires in the memory below TEXT_OFFSET cannot be used aspect, beyond the current prectical limitation. Since we are likely to see platforms with UEFI memory in use around start of RAM, that is a limitation we should probably try to get rid of. From: Mark Salter msal...@redhat.com Date: Thu, 10 Jul 2014 09:25:30 -0400 Subject: [PATCH] arm64/efi: try to handle firmware located below kernel The rule for arm64 kernel image placement is that it must be located TEXT_OFFSET bytes past a 2MiB boundary. The kernel itself will use the TEXT_OFFSET sized area for initial page tables but that area is not part of the kernel image itself. The current EFI stub code finds the base of DRAM from the EFI memmap and relocates the kernel to dram_base+TEXT_OFFSET. This assumes that the low memory is not being used and the kernel relocation simply fails if the base memory allocation fails. At least one vendor has firmware which occupies memory near dram_base so kernel relocations always fail. This patch attempts to work with such firmware by searching the EFI memmap for the lowest available memory which may be used for the kernel image. There are several pitfalls remaining which may lead to boot failure: * The stub does not allocate the TEXT_OFFSET region, so it is required that the firmware not be using that area for anything which may interfere or overlap with the initial kernel page tables. We can't simply include that area in our search for available memory because firmware using the spin-table method for booting secondary CPUs may place the CPU pen in an out of the way part of that region and mark it as reserved memory. * The current code requires FDT to be placed within first 512MiB of DRAM (with the kernel below it). This requirement can be removed in the future, but would involve changes to generic stub code shared by other architectures. Signed-off-by: Mark Salter msal...@redhat.com --- arch/arm64/kernel/efi-stub.c | 45 +--- arch/arm64/kernel/efi.c | 19 --- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c index 60e98a63..f5da27f 100644 --- a/arch/arm64/kernel/efi-stub.c +++ b/arch/arm64/kernel/efi-stub.c @@ -54,21 +54,53 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, efi_loaded_image_t *image) { efi_status_t status; - unsigned long kernel_size, kernel_memsize = 0; + unsigned long kernel_size, kernel_memsize; + unsigned long desired_base = dram_base + TEXT_OFFSET; + unsigned long desired_end; + unsigned long map_size; + struct efi_memory_map map; + efi_memory_desc_t *md; /* Relocate the image, if required. */ kernel_size = _edata - _text; - if (*image_addr != (dram_base + TEXT_OFFSET)) { - kernel_memsize = kernel_size + (_end - _edata); + kernel_memsize = kernel_size + (_end - _edata); + + desired_end = desired_base + kernel_size; + + /* find lowest available address for kernel to live */ + status = efi_get_memory_map(sys_table, (efi_memory_desc_t **)map.map, + map_size, map.desc_size, NULL, NULL); + if (status == EFI_SUCCESS) { + map.map_end = map.map + map_size; + for_each_efi_memory_desc(map, md) { + unsigned long start, end, offset; + if (!(md-attribute EFI_MEMORY_WB)) + continue; + if (md-type != EFI_CONVENTIONAL_MEMORY) + continue; + start = md-phys_addr; + end = start + (md-num_pages EFI_PAGE_SHIFT); + offset = start (SZ_2M - 1); + if (offset TEXT_OFFSET) + start += (TEXT_OFFSET - offset); + else if (offset TEXT_OFFSET) + start = ALIGN(start, SZ_2M) + TEXT_OFFSET; + if (start end (start + kernel_memsize) = end) { +
Re: [PATCH] efi/arm64: efistub: don't abort if base of DRAM is occupied
On Tue, Jul 15, 2014 at 09:11:00AM -0400, Mark Salter wrote: On Tue, 2014-07-15 at 11:02 +0100, Leif Lindholm wrote: @@ -273,6 +282,10 @@ static void __init free_boot_services(void) continue; } + /* Don't free anything below kernel */ + if (md-phys_addr PHYS_OFFSET) + continue; + Is the spin table area really allocated as BOOT_SERVICES_*? No. It is EFI_RESERVED_TYPE. But if UEFI is allowed below the kernel, then there could be BS code/data memory which we'd want to ignore. Well, if it is boot service code/data - then there is no need for us to keep it around after ExitBootServices(). / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: EFI_STUB fails to boot non-EFI on arm64
On Tue, Jul 08, 2014 at 10:21:00AM +0100, Catalin Marinas wrote: I forgot about this thread. I think we need it sorted in some way. Agreed. On Fri, May 23, 2014 at 04:03:31PM +0100, Leif Lindholm wrote: My view is that this should be fixed in fdt_find_uefi_params(). A single info message that we can't find evidence of UEFI should be printed in the non-error case. [...] diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index cd36deb..4bb42e1e 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -366,11 +366,8 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, for (i = 0; i ARRAY_SIZE(dt_params); i++) { prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); - if (!prop) { - pr_err(Can't find %s in device tree!\n, - dt_params[i].name); - return 0; - } + if (!prop) + goto fail; dest = info-params + dt_params[i].offset; val = of_read_number(prop, len / sizeof(u32)); @@ -385,6 +382,14 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, dt_params[i].size * 2, val); } return 1; + + fail: + if (i == 0) + pr_info( UEFI not found.\n); + else + pr_err(Can't find %s in device tree!\n, dt_params[i].name); + + return 0; I'm ok with the idea but I don't particularly like the implementation. Does this look any better (functionally the same as yours)? It solves the problem, so sure. Acked-by: Leif Lindholm leif.lindh...@linaro.org Tested-by: Leif Lindholm leif.lindh...@linaro.org diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index eff1a2f22f09..dc79346689e6 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -346,6 +346,7 @@ static __initdata struct { struct param_info { int verbose; + int found; void *params; }; @@ -362,16 +363,12 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, (strcmp(uname, chosen) != 0 strcmp(uname, chosen@0) != 0)) return 0; - pr_info(Getting parameters from FDT:\n); - for (i = 0; i ARRAY_SIZE(dt_params); i++) { prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); - if (!prop) { - pr_err(Can't find %s in device tree!\n, -dt_params[i].name); + if (!prop) return 0; - } dest = info-params + dt_params[i].offset; + info-found++; val = of_read_number(prop, len / sizeof(u32)); @@ -390,10 +387,21 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) { struct param_info info; + int ret; + + pr_info(Getting EFI parameters from FDT:\n); info.verbose = verbose; + info.found = 0; info.params = params; - return of_scan_flat_dt(fdt_find_uefi_params, info); + ret = of_scan_flat_dt(fdt_find_uefi_params, info); + if (!info.found) + pr_info(UEFI not found.\n); + else if (!ret) + pr_err(Can't find '%s' in device tree!\n, +dt_params[info.found].name); + + return ret; } #endif /* CONFIG_EFI_PARAMS_FROM_FDT */ -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [GIT PULL] EFI urgent fix
On Fri, Jun 20, 2014 at 10:28:48AM +0100, Catalin Marinas wrote: On Fri, Jun 20, 2014 at 10:00:08AM +0100, Matt Fleming wrote: Please pull the following compiler warning fix. Sorry, I've been pretty slow in getting this pull request sent. Multiple people have reported hitting it and I've now received 4 patches for the same warning, BTW, one of them is not just a simple warning but a bug. Pointer to long variable on the stack passed to a function that only takes a pointer to int. We are probably lucky that we don't hit the bug on arm64. Anyway, thanks for pushing the fix. (and lesson learnt not to trust the ARM EFI_STUB developers, won't name them, with properly testing their code ;)) The code was tested and showed no runtime problems - but I did manage to miss the warnings. I did post an alternative patch for one half of this a week before anyone else, but that one seems to have been ignored, even by gmane: http://www.spinics.net/lists/linux-efi/msg03924.html That form will still be required for the 32-bit arm support, since strncmp is not available in the zImage. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [GIT PULL] EFI urgent fix
On Fri, Jun 20, 2014 at 02:49:38PM +0100, Matt Fleming wrote: On Fri, 20 Jun, at 02:39:19PM, Leif Lindholm wrote: I did post an alternative patch for one half of this a week before anyone else, but that one seems to have been ignored, even by gmane: http://www.spinics.net/lists/linux-efi/msg03924.html Sorry Leif, I don't know why I didn't pick that one up. I do see it in my mail archive. Chalk it up to human error. Well, it seemed to manage to trick at least one computer too... That form will still be required for the 32-bit arm support, since strncmp is not available in the zImage. Are you planning on incorporating this fix into the 32-bit arm support patch series Yeah, I'll do that. Just as soon as I get back off holiday :) / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: EFI_STUB fails to boot non-EFI on arm64
On Wed, May 28, 2014 at 07:40:43PM +0100, Will Deacon wrote: Well, but (for the output part) my patch already did that? If the Getting parameters from FDT:\n was too verbose, we could just drop it, and have the same effect on output. It's the pr_err which is annoying, not the Getting parameters from FDT:\n message. Why should I have an error logged to my console when I was never intending to boot using EFI anyway? The pr_err would now only be triggered if some UEFI properties were present and not others. I.e. if the UEFI stub loader failed miserably without detecting it, or something corrupted the DT later on. We would then be the proud owners of a system in an undefined state. Thing is - there is not really any error case available anywhere during the execution of efi_init() and its branches other than: - Information required for UEFI boot cannot be found. - Information exists, but is invalid. - Failed to early_memremap some UEFI regions into the kernel. which all amounts to UEFI not available or something went wrong, rather than UEFI failed to initialise. Fine, but in this case the DT had the relevant properties which is a good indication that the user was at least *trying* to boot using EFI, no? Having a partial/invalid DT is going to cause undefined behaviour regardless of your method of booting. And if the data provided proved inaccessible or broken, the symptom would be a complete lack of memblocks. So it may in fact not be possible for that pr_err to ever make it to the console :) If efi_init returns successfully, EFI_BOOT is set, and testable using the efi_enabled() macro. The proper UEFI failed to initialise bit does not come until the early_initcall arm64_enter_virtual_mode(), and is indicated not by a return value, but by setting the flag indicating that EFI_RUNTIME_SERVICES are available, which is checked later in core code using the efi_enabled() macro. Sorry, I naively assumed that with a name like efi_init it might, you know, initialise EFI? ;) Name cargo-culted from ia64/x86 by me, and from me by Mark :) So moving the call to efi_get_fdt_params() would have little effect other than adding a third call site for UEFI bits in setup_arch(). I don't mind having the extra call site if it allows us to distinguish errors from information. And I still don't see how an extra call site in setup_arch would make this more possible than it already is (with my suggested patch to the current version of the code). / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: EFI_STUB fails to boot non-EFI on arm64
On Fri, May 23, 2014 at 10:45:13AM +0100, Catalin Marinas wrote: As the EFI_STUB for arm64 got into tip and soon into -next, I thought about giving it a try (tip/arm64/efi). Using my boot-wrapper (non-EFI) is still supposed to work but I get the trace below. It looks like memmap.map is NULL but the code still assumes the kernel was started as an EFI app. Have you guys tested these patches properly? Apparently not sufficuently... Sorry about that. Fix appended: From 98433920394730d835f0061474832909c0740f29 Mon Sep 17 00:00:00 2001 From: Leif Lindholm leif.lindh...@linaro.org Date: Fri, 23 May 2014 11:23:23 +0100 Subject: [PATCH] arm64: efi: only attempt efi map setup if booting via EFI Booting a kernel with CONFIG_EFI enabled on a non-EFI system caused an oops with the current UEFI support code. Add the required test to prevent this. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/kernel/efi.c |3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 7bfd650..14db1f6 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -333,6 +333,9 @@ void __init efi_init(void) void __init efi_idmap_init(void) { + if (!efi_enabled(EFI_BOOT)) + return; + /* boot time idmap_pg_dir is incomplete, so fill in missing parts */ efi_setup_idmap(); } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: EFI_STUB fails to boot non-EFI on arm64
On Fri, May 23, 2014 at 02:47:20PM +0100, Catalin Marinas wrote: That's a first (possibly temporary) step and I think it's fine: Acked-by: Catalin Marinas catalin.mari...@arm.com But we need some further tweaking to the way we call efi_init(). Currently it doesn't matter whether Linux booted as an EFI application or not and efi_init() is always called, causing some pr_err() in fdt_find_uefi_params(). It's not really an error as we support the same image booting non-EFI as well. OK. Can we add another of detecting whether it's an EFI application and avoid calling efi_init()? I can see x86 sets some efi_loader_signature string in exit_boot() and checks against it later when calling efi_init(). Well, I agree that we shouldn't be spewing error messages for expected operation, but efi_init() is the function we call to determine whether we _are_ booting via UEFI - and it sets flags accordingly for the efi_enabled() macro. My view is that this should be fixed in fdt_find_uefi_params(). A single info message that we can't find evidence of UEFI should be printed in the non-error case. Like below? / Leif From 67283e60923c14c024460b4512c49563a92acce7 Mon Sep 17 00:00:00 2001 From: Leif Lindholm leif.lindh...@linaro.org Date: Fri, 23 May 2014 15:50:51 +0100 Subject: [PATCH] efi: fdt: Drop error messages for non-error case Change fdt_find_uefi_params() to only write error messages if actual error encountered, rather than if no UEFI information is encountered. For the non-error case, print a single info message. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index cd36deb..4bb42e1e 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -366,11 +366,8 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, for (i = 0; i ARRAY_SIZE(dt_params); i++) { prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); - if (!prop) { - pr_err(Can't find %s in device tree!\n, - dt_params[i].name); - return 0; - } + if (!prop) + goto fail; dest = info-params + dt_params[i].offset; val = of_read_number(prop, len / sizeof(u32)); @@ -385,6 +382,14 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname, dt_params[i].size * 2, val); } return 1; + + fail: + if (i == 0) + pr_info( UEFI not found.\n); + else + pr_err(Can't find %s in device tree!\n, dt_params[i].name); + + return 0; } int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] efi: arm64: memory node handling cleanup
Remove unused variable, and convert strncmp() to strcmp(), since the former is not available in arm zImage. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/fdt.c |7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c index 5c6a8e8..ab12870 100644 --- a/drivers/firmware/efi/fdt.c +++ b/drivers/firmware/efi/fdt.c @@ -63,15 +63,14 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, */ prev = 0; for (;;) { - const char *type, *name; - int len; + const char *type; node = fdt_next_node(fdt, prev, NULL); if (node 0) break; - type = fdt_getprop(fdt, node, device_type, len); - if (type strncmp(type, memory, len) == 0) { + type = fdt_getprop(fdt, node, device_type, NULL); + if (type strcmp(type, memory) == 0) { fdt_del_node(fdt, node); continue; } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: EFI_STUB fails to boot non-EFI on arm64
On Fri, May 23, 2014 at 05:17:39PM +0200, Ard Biesheuvel wrote: Can we add another of detecting whether it's an EFI application and avoid calling efi_init()? I can see x86 sets some efi_loader_signature string in exit_boot() and checks against it later when calling efi_init(). Well, I agree that we shouldn't be spewing error messages for expected operation, but efi_init() is the function we call to determine whether we _are_ booting via UEFI - and it sets flags accordingly for the efi_enabled() macro. Considering that a) the raw Image loader and the stub enter the kernel through different entry points (i.e., offset #0 and whatever entry point is specified in the PE/COFF header, respectively), and b) there is no decompressor etc involved so we jump straight into the kernel startup code c) head.S already deals with a similar problem, i.e., storing the CPU boot mode I would assume it shouldn't be so difficult to set a bit somewhere indicating which case we are dealing with? That would certainly be possible, but what would be the benefit of having two separate mechanisms for determining whether we are booting via UEFI - which could potentially end up disagreeing? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 08/10] arm64: efi: add EFI stub
From: Mark Salter msal...@redhat.com This patch adds PE/COFF header fields to the start of the kernel Image so that it appears as an EFI application to UEFI firmware. An EFI stub is included to allow direct booting of the kernel Image. Signed-off-by: Mark Salter msal...@redhat.com [Add support in PE/COFF header for signed images] Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/Kconfig |5 +- arch/arm64/kernel/Makefile |4 +- arch/arm64/kernel/efi-entry.S | 109 + arch/arm64/kernel/efi-stub.c| 81 + arch/arm64/kernel/head.S| 112 ++ drivers/firmware/efi/arm-stub.c | 247 +++ 6 files changed, 555 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 drivers/firmware/efi/arm-stub.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 392a2d5..a863663 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -290,8 +290,9 @@ config EFI help This option provides support for runtime services provided by UEFI firmware (such as non-volatile variables, realtime - clock, and platform reset). This is only useful on systems - that have UEFI firmware. + clock, and platform reset). A UEFI stub is also provided to + allow the kernel to be booted as an EFI application. This + is only useful on systems that have UEFI firmware. endmenu diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f57ccd7..db63a0a 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -4,6 +4,8 @@ CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \ + -I$(src)/../../../scripts/dtc/libfdt # Object file lists. arm64-obj-y:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ @@ -22,7 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o -arm64-obj-$(CONFIG_EFI)+= efi.o +arm64-obj-$(CONFIG_EFI)+= efi.o efi-stub.o efi-entry.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S new file mode 100644 index 000..66716c9 --- /dev/null +++ b/arch/arm64/kernel/efi-entry.S @@ -0,0 +1,109 @@ +/* + * EFI entry point. + * + * Copyright (C) 2013, 2014 Red Hat, Inc. + * Author: Mark Salter msal...@redhat.com + * + * 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 linux/linkage.h +#include linux/init.h + +#include asm/assembler.h + +#define EFI_LOAD_ERROR 0x8001 + + __INIT + + /* +* We arrive here from the EFI boot manager with: +* +** CPU in little-endian mode +** MMU on with identity-mapped RAM +** Icache and Dcache on +* +* We will most likely be running from some place other than where +* we want to be. The kernel image wants to be placed at TEXT_OFFSET +* from start of RAM. +*/ +ENTRY(efi_stub_entry) + /* +* Create a stack frame to save FP/LR with extra space +* for image_addr variable passed to efi_entry(). +*/ + stp x29, x30, [sp, #-32]! + + /* +* Call efi_entry to do the real work. +* x0 and x1 are already set up by firmware. Current runtime +* address of image is calculated and passed via *image_addr. +* +* unsigned long efi_entry(void *handle, +* efi_system_table_t *sys_table, +* unsigned long *image_addr) ; +*/ + adrpx8, _text + add x8, x8, #:lo12:_text + add x2, sp, 16 + str x8, [x2] + bl efi_entry + cmn x0, #1 + b.eqefi_load_fail + + /* +* efi_entry() will have relocated the kernel image if necessary +* and we return here with device tree address in x0 and the kernel +* entry point stored at *image_addr. Save those values in registers +* which are callee preserved. +*/ + mov x20, x0 // DTB address + ldr x0, [sp, #16] // relocated _text address + mov x21, x0 + + /* +* Flush dcache covering current runtime addresses
[PATCH v2 10/10] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
From: Ard Biesheuvel ard.biesheu...@linaro.org Loading unauthenticated FDT blobs directly from storage is a security hazard, so this should only be allowed when running with UEFI Secure Boot disabled. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/arm-stub.c | 39 +++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index 19239a9..41114ce 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -12,6 +12,30 @@ * */ +static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +{ + static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t const var_name[] __initconst = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + + efi_get_variable_t *f_getvar = sys_table_arg-runtime-get_variable; + unsigned long size = sizeof(u8); + efi_status_t status; + u8 val; + + status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)var_guid, + NULL, size, val); + + switch (status) { + case EFI_SUCCESS: + return val; + case EFI_NOT_FOUND: + return 0; + default: + return 1; + } +} + static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, void **__fh) { @@ -144,7 +168,7 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, /* addr/point and size pairs for memory management*/ unsigned long initrd_addr; u64 initrd_size = 0; - unsigned long fdt_addr; /* Original DTB */ + unsigned long fdt_addr = 0; /* Original DTB */ u64 fdt_size = 0; /* We don't get size from configuration table */ char *cmdline_ptr = NULL; int cmdline_size = 0; @@ -196,9 +220,13 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_image; } - /* Load a device tree from the configuration table, if present. */ - fdt_addr = (uintptr_t)get_fdt(sys_table); - if (!fdt_addr) { + /* +* Unauthenticated device tree data is a security hazard, so +* ignore 'dtb=' unless UEFI Secure Boot is disabled. +*/ + if (efi_secureboot_enabled(sys_table)) { + pr_efi(sys_table, UEFI Secure Boot is enabled.\n); + } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, dtb=, ~0UL, (unsigned long *)fdt_addr, @@ -209,6 +237,9 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_cmdline; } } + if (!fdt_addr) + /* Look for a device tree configuration table entry. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); status = handle_cmdline_files(sys_table, image, cmdline_ptr, initrd=, dram_base + SZ_512M, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 05/10] efi: Add shared FDT related functions for ARM/ARM64
From: Roy Franz roy.fr...@linaro.org Both ARM and ARM64 stubs will update the device tree that they pass to the kernel. In both cases they primarily need to add the same UEFI related information, so the function can be shared. Create a new FDT related file for this to avoid use of architecture #ifdefs in efi-stub-helper.c. Signed-off-by: Roy Franz roy.fr...@linaro.org [ Fixed memory node deletion code. ] Signed-off-by: Mark Rutland mark.rutl...@arm.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- drivers/firmware/efi/fdt.c | 285 include/linux/efi.h|3 + 2 files changed, 288 insertions(+) create mode 100644 drivers/firmware/efi/fdt.c diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c new file mode 100644 index 000..5c6a8e8 --- /dev/null +++ b/drivers/firmware/efi/fdt.c @@ -0,0 +1,285 @@ +/* + * 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. + * + */ + +static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, + unsigned long orig_fdt_size, + void *fdt, int new_fdt_size, char *cmdline_ptr, + u64 initrd_addr, u64 initrd_size, + efi_memory_desc_t *memory_map, + unsigned long map_size, unsigned long desc_size, + u32 desc_ver) +{ + int node, prev; + int status; + u32 fdt_val32; + u64 fdt_val64; + + /* +* Copy definition of linux_banner here. Since this code is +* built as part of the decompressor for ARM v7, pulling +* in version.c where linux_banner is defined for the +* kernel brings other kernel dependencies with it. +*/ + const char linux_banner[] = + Linux version UTS_RELEASE ( LINUX_COMPILE_BY @ + LINUX_COMPILE_HOST ) ( LINUX_COMPILER ) UTS_VERSION \n; + + /* 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); + return EFI_LOAD_ERROR; + } + /* +* We don't get the size of the FDT if we get if from a +* configuration table. +*/ + if (orig_fdt_size fdt_totalsize(orig_fdt) orig_fdt_size) { + pr_efi_err(sys_table, Truncated device tree! foo!\n); + return EFI_LOAD_ERROR; + } + } + + if (orig_fdt) + status = fdt_open_into(orig_fdt, fdt, new_fdt_size); + else + status = fdt_create_empty_tree(fdt, new_fdt_size); + + if (status != 0) + goto fdt_set_fail; + + /* +* Delete any memory nodes present. We must delete nodes which +* early_init_dt_scan_memory may try to use. +*/ + prev = 0; + for (;;) { + const char *type, *name; + int len; + + node = fdt_next_node(fdt, prev, NULL); + if (node 0) + break; + + type = fdt_getprop(fdt, node, device_type, len); + if (type strncmp(type, memory, len) == 0) { + fdt_del_node(fdt, node); + continue; + } + + prev = node; + } + + node = fdt_subnode_offset(fdt, 0, chosen); + if (node 0) { + node = fdt_add_subnode(fdt, 0, chosen); + if (node 0) { + status = node; /* node is error code when negative */ + goto fdt_set_fail; + } + } + + if ((cmdline_ptr != NULL) (strlen(cmdline_ptr) 0)) { + status = fdt_setprop(fdt, node, bootargs, cmdline_ptr, +strlen(cmdline_ptr) + 1); + if (status) + goto fdt_set_fail; + } + + /* Set initrd address/end in device tree, if present */ + if (initrd_size != 0) { + 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)); + if (status) + goto fdt_set_fail; + initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); + status = fdt_setprop(fdt, node, linux,initrd-end
[PATCH v2 02/10] doc: efi-stub.txt updates for ARM
From: Roy Franz roy.fr...@linaro.org Update efi-stub.txt documentation to be more general and not x86 specific. Add ARM only dtb= command line option description. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/efi-stub.txt | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt index c628788..26be7b0 100644 --- a/Documentation/efi-stub.txt +++ b/Documentation/efi-stub.txt @@ -1,13 +1,16 @@ The EFI Boot Stub --- -On the x86 platform, a bzImage can masquerade as a PE/COFF image, -thereby convincing EFI firmware loaders to load it as an EFI -executable. The code that modifies the bzImage header, along with the -EFI-specific entry point that the firmware loader jumps to are -collectively known as the EFI boot stub, and live in +On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade +as a PE/COFF image, thereby convincing EFI firmware loaders to load +it as an EFI executable. The code that modifies the bzImage header, +along with the EFI-specific entry point that the firmware loader +jumps to are collectively known as the EFI boot stub, and live in arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c, -respectively. +respectively. For ARM the EFI stub is implemented in +arch/arm/boot/compressed/efi-header.S and +arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared +between architectures is in drivers/firmware/efi/efi-stub-helper.c. By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or @@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI System Partition (ESP) and renamed with the extension .efi. Without the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems -because EFI firmware doesn't have support for them. +because EFI firmware doesn't have support for them. For ARM the +arch/arm/boot/zImage should be copied to the system partition, and it +may not need to be renamed. Passing kernel parameters from the EFI shell @@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's because the image we're executing is interpreted by the EFI shell, which understands relative paths, whereas the rest of the command line is passed to bzImage.efi. + + + The dtb= option + +For the ARM architecture, we also need to be able to provide a device +tree to the kernel. This is done with the dtb= command line option, +and is processed in the same manner as the initrd= option that is +described above. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 01/10] lib: add fdt_empty_tree.c
From: Mark Salter msal...@redhat.com CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- lib/Makefile |3 ++- lib/fdt_empty_tree.c |2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 0cd7b68..74a32dc 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -148,7 +148,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000..5d30c58 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include linux/libfdt_env.h +#include ../scripts/dtc/libfdt/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/10] arm64: UEFI support
This set adds support for UEFI to the arm64 port - a stub loader, as well as runtime services support for efivars. It depends on some core EFI patches currently in linux-next. This includes bits shared between arm and arm64 support. Remaining bits required for arm support will be submitted separately. Changes from previous version: - Reordered runtime and stub packages to avoid bisect breakage. - Added more comments to efi-entry.S. - Use actual instruction to generate MZ signature in head.S. - Redundant cache/tlb maintenance removed. - Properly use %pa instead of %llx in mm error messages.. - Stub deletes DT nodes of type memory instead of nodes called memory. Changes from earlier versions: - Enter_virtual_mode() is now an early initcall. - UEFI Reserved regions now preserved. - Bugfix for dtb= support with SecureBoot. - Stub now flushes instruction cache by address for kernel image area. - CONFIG_EFI_STUB merged into CONFIG_EFI since they are interdependent. - EFI_DEVICE_TREE_GUID renamed DEVICE_TREE_GUID. - Minor cleanups. Ard Biesheuvel (1): efi/arm64: ignore dtb= when UEFI SecureBoot is enabled Leif Lindholm (1): doc: arm: add UEFI support documentation Mark Salter (6): lib: add fdt_empty_tree.c efi: add helper function to get UEFI params from FDT arm64: Add function to create identity mappings arm64: add EFI runtime services arm64: efi: add EFI stub doc: arm64: add description of EFI stub support Roy Franz (2): doc: efi-stub.txt updates for ARM efi: Add shared FDT related functions for ARM/ARM64 Documentation/arm/00-INDEX |2 + Documentation/arm/uefi.txt | 64 ++ Documentation/arm64/booting.txt |4 + Documentation/efi-stub.txt | 33 ++- arch/arm64/Kconfig | 16 ++ arch/arm64/include/asm/efi.h| 14 ++ arch/arm64/include/asm/mmu.h|2 + arch/arm64/kernel/Makefile |3 + arch/arm64/kernel/efi-entry.S | 109 + arch/arm64/kernel/efi-stub.c| 81 +++ arch/arm64/kernel/efi.c | 466 +++ arch/arm64/kernel/head.S| 112 ++ arch/arm64/kernel/setup.c |5 + arch/arm64/mm/mmu.c | 65 -- drivers/firmware/efi/Kconfig|7 + drivers/firmware/efi/arm-stub.c | 278 +++ drivers/firmware/efi/efi.c | 79 +++ drivers/firmware/efi/fdt.c | 285 include/linux/efi.h | 12 + lib/Makefile|3 +- lib/fdt_empty_tree.c|2 + 21 files changed, 1616 insertions(+), 26 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 arch/arm64/kernel/efi.c create mode 100644 drivers/firmware/efi/arm-stub.c create mode 100644 drivers/firmware/efi/fdt.c create mode 100644 lib/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/5] efi: x86: Improve cmdline conversion
From: H. Peter Anvin h...@zytor.com Improve the conversion of the UTF-16 EFI command line to UTF-8 for passing to the kernel. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: H. Peter Anvin h...@zytor.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/efi-stub-helper.c | 91 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 1e61461..255d2aa 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -1086,8 +1086,7 @@ struct boot_params *make_boot_params(struct efi_config *c) hdr-type_of_loader = 0x21; /* Convert unicode cmdline to ascii */ - cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, - options_size); + cmdline_ptr = efi_convert_cmdline(sys_table, image, options_size); if (!cmdline_ptr) goto fail; hdr-cmd_line_ptr = (unsigned long)cmdline_ptr; diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 61230cb..3cc5ebe 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -503,52 +503,99 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, } /* - * Convert the unicode UEFI command line to ASCII to pass to kernel. + * Get the number of UTF-8 bytes corresponding to an UTF-16 character. + * This overestimates for surrogates, but that is okay. + */ +static int efi_utf8_bytes(u16 c) +{ + return 1 + (c = 0x80) + (c = 0x800); +} + +/* + * Convert an UTF-16 string, not necessarily null terminated, to UTF-8. + */ +static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) +{ + unsigned int c; + + while (n--) { + c = *src++; + if (n c = 0xd800 c = 0xdbff + *src = 0xdc00 *src = 0xdfff) { + c = 0x1 + ((c 0x3ff) 10) + (*src 0x3ff); + src++; + n--; + } + if (c = 0xd800 c = 0xdfff) + c = 0xfffd; /* Unmatched surrogate */ + if (c 0x80) { + *dst++ = c; + continue; + } + if (c 0x800) { + *dst++ = 0xc0 + (c 6); + goto t1; + } + if (c 0x1) { + *dst++ = 0xe0 + (c 12); + goto t2; + } + *dst++ = 0xf0 + (c 18); + *dst++ = 0x80 + ((c 12) 0x3f); +t2: + *dst++ = 0x80 + ((c 6) 0x3f); +t1: + *dst++ = 0x80 + (c 0x3f); + } + + return dst; +} + +/* + * Do proper conversion from UTF-16 to UTF-8 * Size of memory allocated return in *cmd_line_len. * Returns NULL on error. */ -static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg, - efi_loaded_image_t *image, - int *cmd_line_len) +static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, +efi_loaded_image_t *image, +int *cmd_line_len) { - u16 *s2; + const u16 *s2; u8 *s1 = NULL; unsigned long cmdline_addr = 0; - int load_options_size = image-load_options_size / 2; /* ASCII */ - void *options = image-load_options; - int options_size = 0; + int load_options_chars = image-load_options_size / 2; /* UTF-16 */ + const u16 *options = image-load_options; + int options_bytes = 0; /* UTF-8 bytes */ + int options_chars = 0; /* UTF-16 chars */ efi_status_t status; - int i; u16 zero = 0; if (options) { s2 = options; - while (*s2 *s2 != '\n' options_size load_options_size) { - s2++; - options_size++; + while (options_chars load_options_chars + *s2 *s2 != '\n') { + options_bytes += efi_utf8_bytes(*s2++); + options_chars++; } } - if (options_size == 0) { - /* No command line options, so return empty string*/ - options_size = 1; + if (!options_chars) { + /* No command line options, so return empty string */ options = zero; } - options_size++; /* NUL termination */ + options_bytes++; /* NUL termination */ - status = efi_low_alloc(sys_table_arg, options_size, 0, cmdline_addr); + status = efi_low_alloc(sys_table_arg, options_bytes, 0, cmdline_addr); if (status
[PATCH 2/5] efi: create memory map iteration helper
From: Mark Salter msal...@redhat.com There are a lot of places in the kernel which iterate through an EFI memory map. Most of these places use essentially the same for-loop code. This patch adds a for_each_efi_memory_desc() helper to clean up all of the existing duplicate code and avoid more in the future. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- include/linux/efi.h |6 ++ 1 file changed, 6 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h index 6c100ff..82d0abb 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -863,6 +863,12 @@ extern int efi_set_rtc_mmss(const struct timespec *now); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; +/* Iterate through an efi_memory_map */ +#define for_each_efi_memory_desc(m, md) \ + for ((md) = (m)-map; \ +(md) = (efi_memory_desc_t *)((m)-map_end - (m)-desc_size); \ +(md) = (void *)(md) + (m)-desc_size) + /** * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/5] efi: Add get_dram_base() helper function
From: Roy Franz roy.fr...@linaro.org Add the get_dram_base() function, shared by arm/arm64. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 183289c..998b884 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -11,6 +11,10 @@ */ #define EFI_READ_CHUNK_SIZE(1024 * 1024) +/* error code which can't be mistaken for valid address */ +#define EFI_ERROR (~0UL) + + struct file_info { efi_file_handle_t *handle; u64 size; @@ -83,6 +87,32 @@ fail: return status; } + +static unsigned long __init get_dram_base(efi_system_table_t *sys_table) +{ + efi_status_t status; + unsigned long map_size; + unsigned long membase = EFI_ERROR; + struct efi_memory_map map; + efi_memory_desc_t *md; + + status = efi_get_memory_map(sys_table, (efi_memory_desc_t **)map.map, + map_size, map.desc_size, NULL, NULL); + if (status != EFI_SUCCESS) + return membase; + + map.map_end = map.map + map_size; + + for_each_efi_memory_desc(map, md) + if (md-attribute EFI_MEMORY_WB) + if (membase md-phys_addr) + membase = md-phys_addr; + + efi_call_phys1(sys_table-boottime-free_pool, map.map); + + return membase; +} + /* * Allocate at the highest possible address that is not above 'max'. */ -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 00/10] arm64: UEFI support
This set adds support for UEFI to the arm64 port - a stub loader, as well as runtime services support for efivars. It depends on some core EFI patches currently in linux-next. This includes bits shared between arm and arm64 support. Remaining bits required for arm support will be submitted separately. Changes from previous version: - Enter_virtual_mode() is now an early initcall. - UEFI Reserved regions now preserved. - Bugfix for dtb= support with SecureBoot. - Stub now flushes instruction cache by address for kernel image area. - CONFIG_EFI_STUB merged into CONFIG_EFI since they are interdependent. - EFI_DEVICE_TREE_GUID renamed DEVICE_TREE_GUID. - Minor cleanups. Ard Biesheuvel (1): efi/arm64: ignore dtb= when UEFI SecureBoot is enabled Leif Lindholm (1): doc: arm: add UEFI support documentation Mark Salter (6): lib: add fdt_empty_tree.c efi: add helper function to get UEFI params from FDT arm64: Add function to create identity mappings arm64: efi: add EFI stub doc: arm64: add description of EFI stub support arm64: add EFI runtime services Roy Franz (2): doc: efi-stub.txt updates for ARM efi: Add shared FDT related functions for ARM/ARM64 Documentation/arm/00-INDEX |2 + Documentation/arm/uefi.txt | 64 + Documentation/arm64/booting.txt|4 + Documentation/efi-stub.txt | 33 ++- arch/arm64/Kconfig | 21 ++ arch/arm64/include/asm/efi.h | 14 + arch/arm64/include/asm/mmu.h |2 + arch/arm64/kernel/Makefile |3 + arch/arm64/kernel/efi-entry.S | 100 +++ arch/arm64/kernel/efi-stub.c | 97 +++ arch/arm64/kernel/efi.c| 469 arch/arm64/kernel/head.S | 112 arch/arm64/kernel/setup.c |5 + arch/arm64/mm/mmu.c| 65 +++-- drivers/firmware/efi/Kconfig |7 + drivers/firmware/efi/arm-stub.c| 255 + drivers/firmware/efi/efi-stub-helper.c | 24 ++ drivers/firmware/efi/efi.c | 79 ++ drivers/firmware/efi/fdt.c | 269 ++ include/linux/efi.h| 12 + lib/Makefile |3 +- lib/fdt_empty_tree.c |2 + 22 files changed, 1616 insertions(+), 26 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 arch/arm64/kernel/efi.c create mode 100644 drivers/firmware/efi/arm-stub.c create mode 100644 drivers/firmware/efi/fdt.c create mode 100644 lib/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 10/10] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
From: Ard Biesheuvel ard.biesheu...@linaro.org Loading unauthenticated FDT blobs directly from storage is a security hazard, so this should only be allowed when running with UEFI Secure Boot disabled. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Cc: Catalin Marinas catalin.mari...@arm.com Cc: Matt Fleming matt.flem...@intel.com --- drivers/firmware/efi/arm-stub.c| 15 +++ drivers/firmware/efi/efi-stub-helper.c | 24 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index b9b7c00..c8988b2 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -145,7 +145,7 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, /* addr/point and size pairs for memory management*/ unsigned long initrd_addr; u64 initrd_size = 0; - unsigned long fdt_addr; /* Original DTB */ + unsigned long fdt_addr = 0; /* Original DTB */ u64 fdt_size = 0; /* We don't get size from configuration table */ char *cmdline_ptr = NULL; int cmdline_size = 0; @@ -197,9 +197,13 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_image; } - /* Load a device tree from the configuration table, if present. */ - fdt_addr = (uintptr_t)get_fdt(sys_table); - if (!fdt_addr) { + /* +* Unauthenticated device tree data is a security hazard, so +* ignore 'dtb=' unless UEFI Secure Boot is disabled. +*/ + if (efi_secureboot_enabled(sys_table)) { + pr_efi(sys_table, UEFI Secure Boot is enabled.\n); + } else { status = handle_cmdline_files(sys_table, image, cmdline_ptr, dtb=, ~0UL, (unsigned long *)fdt_addr, @@ -210,6 +214,9 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_cmdline; } } + if (!fdt_addr) + /* Look for a device tree configuration table entry. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); status = handle_cmdline_files(sys_table, image, cmdline_ptr, initrd=, dram_base + SZ_512M, diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 998b884..8f8b538 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -632,3 +632,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, *cmd_line_len = options_bytes; return (char *)cmdline_addr; } + +static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +{ + static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t const var_name[] __initconst = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + + efi_get_variable_t *f_getvar = sys_table_arg-runtime-get_variable; + unsigned long size = sizeof(u8); + efi_status_t status; + u8 val; + + status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name, + (efi_guid_t *)var_guid, NULL, size, val); + + switch (status) { + case EFI_SUCCESS: + return val; + case EFI_NOT_FOUND: + return 0; + default: + return 1; + } +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 07/10] doc: arm64: add description of EFI stub support
From: Mark Salter msal...@redhat.com Add explanation of arm64 EFI stub and kernel image header changes needed to masquerade as a PE/COFF application. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org CC: linux-...@vger.kernel.org CC: Rob Landley r...@landley.net --- Documentation/arm64/booting.txt |4 Documentation/efi-stub.txt | 12 +--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index a9691cc..aa95d38c 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -85,6 +85,10 @@ The decompressed kernel image contains a 64-byte header as follows: Header notes: - code0/code1 are responsible for branching to stext. +- when booting through EFI, code0/code1 are initially skipped. + res5 is an offset to the PE header and the PE header has the EFI + entry point (efi_stub_entry). When the stub has done its work, it + jumps to code0 to resume the normal boot process. The image must be placed at the specified offset (currently 0x8) from the start of the system RAM and called there. The start of the diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt index 26be7b0..7747024 100644 --- a/Documentation/efi-stub.txt +++ b/Documentation/efi-stub.txt @@ -12,6 +12,11 @@ arch/arm/boot/compressed/efi-header.S and arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared between architectures is in drivers/firmware/efi/efi-stub-helper.c. +For arm64, there is no compressed kernel support, so the Image itself +masquerades as a PE/COFF image and the EFI stub is linked into the +kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S +and arch/arm64/kernel/efi-stub.c. + By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or elilo. Since the EFI boot stub performs the jobs of a boot loader, in @@ -28,7 +33,8 @@ the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems because EFI firmware doesn't have support for them. For ARM the arch/arm/boot/zImage should be copied to the system partition, and it -may not need to be renamed. +may not need to be renamed. Similarly for arm64, arch/arm64/boot/Image +should be copied but not necessarily renamed. Passing kernel parameters from the EFI shell @@ -72,7 +78,7 @@ is passed to bzImage.efi. The dtb= option -For the ARM architecture, we also need to be able to provide a device -tree to the kernel. This is done with the dtb= command line option, +For the ARM and arm64 architectures, we also need to be able to provide a +device tree to the kernel. This is done with the dtb= command line option, and is processed in the same manner as the initrd= option that is described above. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 09/10] doc: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime service and configuration features for the arm architecture. Cc: Rob Landley r...@landley.net Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/uefi.txt | 64 2 files changed, 66 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index a94090c..3b08bc2 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -46,5 +46,7 @@ swp_emulation - SWP/SWPB emulation handler/logging description tcm.txt - ARM Tightly Coupled Memory +uefi.txt + - [U]EFI configuration and runtime services documentation vlocks.txt - Voting locks, low-level mechanism relying on memory system atomic writes. diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..d60030a --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,64 @@ +UEFI, the Unified Extensible Firmware Interface, is a specification +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +UEFI is an evolution of its predecessor 'EFI', so the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers +to legacy code or specifications. + +UEFI support in Linux += +Booting on a platform with firmware compliant with the UEFI specification +makes it possible for the kernel to support additional features: +- UEFI Runtime Services +- Retrieving various configuration information through the standardised + interface of UEFI configuration tables. (ACPI, SMBIOS, ...) + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +The implementation depends on receiving information about the UEFI environment +in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF. + +UEFI stub += +The stub is a feature that extends the Image/zImage into a valid UEFI +PE/COFF executable, including a loader application that makes it possible to +load the kernel directly from the UEFI shell, boot menu, or one of the +lightweight bootloaders like Gummiboot or rEFInd. + +The kernel image built with stub support remains a valid kernel image for +booting in non-UEFI environments. + +UEFI kernel support on ARM +== +UEFI kernel support on the ARM architectures (arm and arm64) is only available +when boot is performed through the stub. + +When booting in UEFI mode, the stub deletes any memory nodes from a provided DT. +Instead, the kernel reads the UEFI memory map. + +The stub populates the FDT /chosen node with (and the kernel scans for) the +following parameters: + +Name | Size | Description + +linux,uefi-system-table | 64-bit | Physical address of the UEFI System Table. + +linux,uefi-mmap-start | 64-bit | Physical address of the UEFI memory map, + || populated by the UEFI GetMemoryMap() call. + +linux,uefi-mmap-size | 32-bit | Size in bytes of the UEFI memory map + || pointed to in previous entry. + +linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI + || memory map. + +linux,uefi-mmap-desc-ver | 32-bit | Version of the mmap descriptor format. + +linux,uefi-stub-kern-ver | string | Copy of linux_banner from build. + + +For verbose debug messages, specify 'uefi_debug' on the kernel command line. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 06/10] arm64: efi: add EFI stub
From: Mark Salter msal...@redhat.com This patch adds PE/COFF header fields to the start of the Image so that it appears as an EFI application to EFI firmware. An EFI stub is included to allow direct booting of the kernel Image. Support in the COFF header for signed images was provided by Ard Biesheuvel. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Cc: Catalin Marinas catalin.mari...@arm.com Cc: Matt Fleming matt.flem...@intel.com --- arch/arm64/Kconfig | 14 +++ arch/arm64/kernel/Makefile |3 + arch/arm64/kernel/efi-entry.S | 100 arch/arm64/kernel/efi-stub.c| 97 +++ arch/arm64/kernel/head.S| 112 ++ drivers/firmware/efi/arm-stub.c | 248 +++ 6 files changed, 574 insertions(+) create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 drivers/firmware/efi/arm-stub.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index d9f23ad..791ec61 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -280,6 +280,20 @@ config CMDLINE_FORCE This is useful if you cannot or don't want to change the command-line options your boot loader passes to the kernel. +config EFI + bool UEFI firmware support + depends on OF + select LIBFDT + default y + help + This option permits an Image to be loaded directly + by EFI firmware without the use of a bootloader. + See Documentation/efi-stub.txt for more information. + + This is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + endmenu menu Userspace binary formats diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 7d811d9..21009b7 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -4,6 +4,8 @@ CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \ + -I$(src)/../../../scripts/dtc/libfdt # Object file lists. arm64-obj-y:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ @@ -22,6 +24,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o +arm64-obj-$(CONFIG_EFI)+= efi-stub.o efi-entry.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S new file mode 100644 index 000..d99a034e --- /dev/null +++ b/arch/arm64/kernel/efi-entry.S @@ -0,0 +1,100 @@ +/* + * EFI entry point. + * + * Copyright (C) 2013, 2014 Red Hat, Inc. + * Author: Mark Salter msal...@redhat.com + * + * 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 linux/linkage.h +#include linux/init.h + +#include asm/assembler.h + +#define EFI_LOAD_ERROR 0x8001 + + __INIT + + /* +* We arrive here from the EFI boot manager with: +* +** MMU on with identity-mapped RAM. +** Icache and Dcache on +* +* We will most likely be running from some place other than where +* we want to be. The kernel image wants to be placed at TEXT_OFFSET +* from start of RAM. +*/ +ENTRY(efi_stub_entry) + stp x29, x30, [sp, #-32]! + + /* +* Call efi_entry to do the real work. +* x0 and x1 are already set up by firmware. Current runtime +* address of image is calculated and passed via *image_addr. +* +* unsigned long efi_entry(void *handle, +* efi_system_table_t *sys_table, +* unsigned long *image_addr) ; +*/ + adrpx8, _text + add x8, x8, #:lo12:_text + add x2, sp, 16 + str x8, [x2] + bl efi_entry + cmn x0, #1 + b.eqefi_load_fail + + /* +* efi_entry() will have relocated the kernel image if necessary +* and we return here with device tree address in x0 and the kernel +* entry point stored at *image_addr. Save those values in registers +* which are callee preserved. +*/ + mov x20, x0 // DTB address + ldr x0, [sp, #16] // relocated _text address + mov x21, x0
[PATCH v3 01/10] lib: add fdt_empty_tree.c
From: Mark Salter msal...@redhat.com CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Cc: Andrew Morton a...@linux-foundation.org --- lib/Makefile |3 ++- lib/fdt_empty_tree.c |2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 02da5b6..5f5b6a2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -149,7 +149,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000..5d30c58 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include linux/libfdt_env.h +#include ../scripts/dtc/libfdt/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/14] UEFI support for arm(64)
Since all prerequisites are not ready for the (32-bit) arm patches to go in, I have broken these out of this set and will be resubmitting them separately. This set now provides arm64 support only - but includes the code that is common between the ARM ports. Prerequisites for this set are: - Mark Salter's generic early_ioremap() - Matt Fleming's efi_enabled() rework Changes from the last upstream posting: - Some cleanup based on feedback - Fixed range test in create_id_mapping() - Fixed name of guard ifdef in arch/arm64/include/asm/efi.h - Fixed memory corruption bug caused by late use of create_id_mapping(). That function uses memblock_alloc() to allocate new pmd/pte pages and it was being called after slab allocator was initialized. This led to possibility that the allocated memory for pmd/pte was already in use by something else. Now, create_id_mapping() gets called just after paging_init() when it is still okay to use memblock_alloc(). - Fixed whitespace error in efi-entry.S - Now support 64K pagesize in EFI runtime - Undid the breakage I caused to Ard's dtb= SecureBoot patch --- Ard Biesheuvel (1): efi/arm64: ignore dtb= when UEFI SecureBoot is enabled H. Peter Anvin (1): efi: x86: Improve cmdline conversion Leif Lindholm (2): efi: delete stray ARM ifdef doc: arm: add UEFI support documentation Mark Salter (7): efi: create memory map iteration helper lib: add fdt_empty_tree.c efi: add helper function to get UEFI params from FDT arm64: Add function to create identity mappings arm64: add EFI stub doc: arm64: add description of EFI stub support arm64: add EFI runtime services Roy Franz (4): doc: efi-stub.txt updates for ARM efi: Add shared printk wrapper for consistent prefixing efi: Add get_dram_base() helper function efi: Add shared FDT related functions for ARM/ARM64 Documentation/arm/00-INDEX |2 + Documentation/arm/uefi.txt | 64 + Documentation/arm64/booting.txt|4 + Documentation/efi-stub.txt | 33 ++- arch/arm64/Kconfig | 26 ++ arch/arm64/include/asm/efi.h | 14 + arch/arm64/include/asm/mmu.h |2 + arch/arm64/kernel/Makefile |4 + arch/arm64/kernel/efi-entry.S | 93 +++ arch/arm64/kernel/efi-stub.c | 83 ++ arch/arm64/kernel/efi.c| 465 arch/arm64/kernel/head.S | 112 arch/arm64/kernel/setup.c |5 + arch/arm64/mm/mmu.c| 65 +++-- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/Kconfig |7 + drivers/firmware/efi/arm-stub.c| 149 ++ drivers/firmware/efi/efi-stub-helper.c | 182 ++--- drivers/firmware/efi/efi.c | 79 ++ drivers/firmware/efi/fdt.c | 268 ++ include/linux/efi.h| 18 ++ init/main.c|4 + lib/Makefile |3 +- lib/fdt_empty_tree.c |2 + 24 files changed, 1615 insertions(+), 72 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 arch/arm64/kernel/efi.c create mode 100644 drivers/firmware/efi/arm-stub.c create mode 100644 drivers/firmware/efi/fdt.c create mode 100644 lib/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 04/15] lib: add fdt_empty_tree.c
From: Mark Salter msal...@redhat.com CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- lib/Makefile |3 ++- lib/fdt_empty_tree.c |2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 48140e3..befe555 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -147,7 +147,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000..5d30c58 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include linux/libfdt_env.h +#include ../scripts/dtc/libfdt/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 15/15] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
From: Ard Biesheuvel ard.biesheu...@linaro.org Loading unauthenticated FDT blobs directly from storage is a security hazard, so this should only be allowed when running with UEFI Secure Boot disabled. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/arm-stub.c| 23 ++- drivers/firmware/efi/efi-stub-helper.c | 24 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index b505fde..733723c 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -41,7 +41,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, /* addr/point and size pairs for memory management*/ unsigned long initrd_addr; u64 initrd_size = 0; - unsigned long fdt_addr; /* Original DTB */ + unsigned long fdt_addr = 0; /* Original DTB */ u64 fdt_size = 0; /* We don't get size from configuration table */ char *cmdline_ptr = NULL; int cmdline_size = 0; @@ -93,15 +93,20 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_image; } - /* Load a device tree from the configuration table, if present. */ - fdt_addr = (uintptr_t)get_fdt(sys_table); + /* +* Unauthenticated device tree data is a security hazard, so +* ignore 'dtb=' unless UEFI Secure Boot is disabled. +*/ + if (efi_secureboot_enabled(sys_table)) + pr_efi(sys_table, UEFI Secure Boot is enabled.\n); + else + handle_cmdline_files(sys_table, image, cmdline_ptr, dtb=, +~0UL, (unsigned long *)fdt_addr, +(unsigned long *)fdt_size); if (!fdt_addr) { - status = handle_cmdline_files(sys_table, image, cmdline_ptr, - dtb=, - ~0UL, (unsigned long *)fdt_addr, - (unsigned long *)fdt_size); - - if (status != EFI_SUCCESS) { + /* Look for a device tree configuration table entry. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); + if (!fdt_addr) { pr_efi_err(sys_table, Failed to load device tree!\n); goto fail_free_cmdline; } diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 4a9986b..f2014f2 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -704,3 +704,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, *cmd_line_len = options_bytes; return (char *)cmdline_addr; } + +static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +{ + static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t const var_name[] __initconst = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + + efi_get_variable_t *f_getvar = sys_table_arg-runtime-get_variable; + unsigned long size = sizeof(u8); + efi_status_t status; + u8 val; + + status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name, + (efi_guid_t *)var_guid, NULL, size, val); + + switch (status) { + case EFI_SUCCESS: + return val; + case EFI_NOT_FOUND: + return 0; + default: + return 1; + } +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 12/15] doc: arm64: add description of EFI stub support
From: Mark Salter msal...@redhat.com Add explanation of arm64 EFI stub and kernel image header changes needed to masquerade as a PE/COFF application. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org CC: linux-...@vger.kernel.org CC: Rob Landley r...@landley.net --- Documentation/arm64/booting.txt |4 Documentation/efi-stub.txt | 12 +--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index a9691cc..aa95d38c 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -85,6 +85,10 @@ The decompressed kernel image contains a 64-byte header as follows: Header notes: - code0/code1 are responsible for branching to stext. +- when booting through EFI, code0/code1 are initially skipped. + res5 is an offset to the PE header and the PE header has the EFI + entry point (efi_stub_entry). When the stub has done its work, it + jumps to code0 to resume the normal boot process. The image must be placed at the specified offset (currently 0x8) from the start of the system RAM and called there. The start of the diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt index 26be7b0..7747024 100644 --- a/Documentation/efi-stub.txt +++ b/Documentation/efi-stub.txt @@ -12,6 +12,11 @@ arch/arm/boot/compressed/efi-header.S and arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared between architectures is in drivers/firmware/efi/efi-stub-helper.c. +For arm64, there is no compressed kernel support, so the Image itself +masquerades as a PE/COFF image and the EFI stub is linked into the +kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S +and arch/arm64/kernel/efi-stub.c. + By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or elilo. Since the EFI boot stub performs the jobs of a boot loader, in @@ -28,7 +33,8 @@ the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems because EFI firmware doesn't have support for them. For ARM the arch/arm/boot/zImage should be copied to the system partition, and it -may not need to be renamed. +may not need to be renamed. Similarly for arm64, arch/arm64/boot/Image +should be copied but not necessarily renamed. Passing kernel parameters from the EFI shell @@ -72,7 +78,7 @@ is passed to bzImage.efi. The dtb= option -For the ARM architecture, we also need to be able to provide a device -tree to the kernel. This is done with the dtb= command line option, +For the ARM and arm64 architectures, we also need to be able to provide a +device tree to the kernel. This is done with the dtb= command line option, and is processed in the same manner as the initrd= option that is described above. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 14/15] doc: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime service and configuration features for the arm architecture. Cc: Rob Landley r...@landley.net Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/uefi.txt | 64 2 files changed, 66 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index a94090c..3b08bc2 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -46,5 +46,7 @@ swp_emulation - SWP/SWPB emulation handler/logging description tcm.txt - ARM Tightly Coupled Memory +uefi.txt + - [U]EFI configuration and runtime services documentation vlocks.txt - Voting locks, low-level mechanism relying on memory system atomic writes. diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..d60030a --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,64 @@ +UEFI, the Unified Extensible Firmware Interface, is a specification +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +UEFI is an evolution of its predecessor 'EFI', so the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers +to legacy code or specifications. + +UEFI support in Linux += +Booting on a platform with firmware compliant with the UEFI specification +makes it possible for the kernel to support additional features: +- UEFI Runtime Services +- Retrieving various configuration information through the standardised + interface of UEFI configuration tables. (ACPI, SMBIOS, ...) + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +The implementation depends on receiving information about the UEFI environment +in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF. + +UEFI stub += +The stub is a feature that extends the Image/zImage into a valid UEFI +PE/COFF executable, including a loader application that makes it possible to +load the kernel directly from the UEFI shell, boot menu, or one of the +lightweight bootloaders like Gummiboot or rEFInd. + +The kernel image built with stub support remains a valid kernel image for +booting in non-UEFI environments. + +UEFI kernel support on ARM +== +UEFI kernel support on the ARM architectures (arm and arm64) is only available +when boot is performed through the stub. + +When booting in UEFI mode, the stub deletes any memory nodes from a provided DT. +Instead, the kernel reads the UEFI memory map. + +The stub populates the FDT /chosen node with (and the kernel scans for) the +following parameters: + +Name | Size | Description + +linux,uefi-system-table | 64-bit | Physical address of the UEFI System Table. + +linux,uefi-mmap-start | 64-bit | Physical address of the UEFI memory map, + || populated by the UEFI GetMemoryMap() call. + +linux,uefi-mmap-size | 32-bit | Size in bytes of the UEFI memory map + || pointed to in previous entry. + +linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI + || memory map. + +linux,uefi-mmap-desc-ver | 32-bit | Version of the mmap descriptor format. + +linux,uefi-stub-kern-ver | string | Copy of linux_banner from build. + + +For verbose debug messages, specify 'uefi_debug' on the kernel command line. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 08/15] efi: Add get_dram_base() helper function
From: Roy Franz roy.fr...@linaro.org Add the get_dram_base() function, shared by arm/arm64. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 4c8ab86..4a9986b 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -11,6 +11,10 @@ */ #define EFI_READ_CHUNK_SIZE(1024 * 1024) +/* error code which can't be mistaken for valid address */ +#define EFI_ERROR (~0UL) + + struct file_info { efi_file_handle_t *handle; u64 size; @@ -92,6 +96,32 @@ fail: return status; } + +static unsigned long __init get_dram_base(efi_system_table_t *sys_table) +{ + efi_status_t status; + unsigned long map_size; + unsigned long membase = EFI_ERROR; + struct efi_memory_map map; + efi_memory_desc_t *md; + + status = efi_get_memory_map(sys_table, (efi_memory_desc_t **)map.map, + map_size, map.desc_size, NULL, NULL); + if (status != EFI_SUCCESS) + return membase; + + map.map_end = map.map + map_size; + + for_each_efi_memory_desc(map, md) + if (md-attribute EFI_MEMORY_WB) + if (membase md-phys_addr) + membase = md-phys_addr; + + efi_call_phys1(sys_table-boottime-free_pool, map.map); + + return membase; +} + /* * Allocate at the highest possible address that is not above 'max'. */ -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 13/15] arm64: add EFI runtime services
From: Mark Salter msal...@redhat.com This patch adds EFI runtime support for arm64. The runtime support allows the kernel to access various EFI runtime services provided by EFI firmware. Things like reboot, real time clock, EFI boot variables, and others. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/Kconfig | 16 ++ arch/arm64/include/asm/efi.h | 14 ++ arch/arm64/kernel/Makefile |1 + arch/arm64/kernel/efi.c | 465 ++ arch/arm64/kernel/setup.c|5 + init/main.c |4 + 6 files changed, 505 insertions(+) create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 6333d49..52d846e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -259,6 +259,20 @@ config CMDLINE_FORCE This is useful if you cannot or don't want to change the command-line options your boot loader passes to the kernel. +config EFI +bool EFI runtime service support + depends on OF + select UCS2_STRING + select LIBFDT + select UEFI_PARAMS_FROM_FDT + help + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + config EFI_STUB bool EFI stub support depends on OF @@ -318,6 +332,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm64/kvm/Kconfig diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h new file mode 100644 index 000..5a46c4e --- /dev/null +++ b/arch/arm64/include/asm/efi.h @@ -0,0 +1,14 @@ +#ifndef _ASM_EFI_H +#define _ASM_EFI_H + +#include asm/io.h + +#ifdef CONFIG_EFI +extern void efi_init(void); +extern void efi_idmap_init(void); +#else +#define efi_init() +#define efi_idmap_init() +#endif + +#endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 0f60b45..4c5a797 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -23,6 +23,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o +arm64-obj-$(CONFIG_EFI)+= efi.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c new file mode 100644 index 000..87c4910 --- /dev/null +++ b/arch/arm64/kernel/efi.c @@ -0,0 +1,465 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.4 + * + * 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 linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/bootmem.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/efi.h +#include asm/tlbflush.h +#include asm/mmu_context.h + +struct efi_memory_map memmap; + +static efi_runtime_services_t *runtime; + +static u64 efi_system_table; + +static int uefi_debug __initdata; +static int __init uefi_debug_setup(char *str) +{ + uefi_debug = 1; + + return 0; +} +early_param(uefi_debug, uefi_debug_setup); + +static int __init is_normal_ram(efi_memory_desc_t *md) +{ + if (md-attribute EFI_MEMORY_WB) + return 1; + return 0; +} + +static void __init efi_setup_idmap(void) +{ + struct memblock_region *r; + efi_memory_desc_t *md; + u64 paddr, npages, size; + + for_each_memblock(memory, r) + create_id_mapping(r-base, r-size, 0); + + /* map runtime io spaces */ + for_each_efi_memory_desc(memmap, md) { + if (!(md-attribute EFI_MEMORY_RUNTIME) || is_normal_ram(md)) + continue; + paddr = md-phys_addr; + npages = md-num_pages; + memrange_efi_to_native(paddr, npages); + size = npages PAGE_SHIFT; + create_id_mapping(paddr, size, 1); + } +} + +static int __init uefi_init(void) +{ + efi_char16_t *c16; + char vendor[100] = unknown; + int i, retval; + + efi.systab = early_memremap(efi_system_table, + sizeof
[PATCH v2 09/15] efi: Add shared FDT related functions for ARM/ARM64
From: Roy Franz roy.fr...@linaro.org Both ARM and ARM64 stubs will update the device tree that they pass to the kernel. In both cases they primarily need to add the same UEFI related information, so the function can be shared. Create a new FDT related file for this to avoid use of architecture #ifdefs in efi-stub-helper.c. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- drivers/firmware/efi/fdt.c | 268 include/linux/efi.h|3 + 2 files changed, 271 insertions(+) create mode 100644 drivers/firmware/efi/fdt.c diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c new file mode 100644 index 000..4510f97 --- /dev/null +++ b/drivers/firmware/efi/fdt.c @@ -0,0 +1,268 @@ +/* + * 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. + * + */ + +static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, + unsigned long orig_fdt_size, + void *fdt, int new_fdt_size, char *cmdline_ptr, + u64 initrd_addr, u64 initrd_size, + efi_memory_desc_t *memory_map, + unsigned long map_size, unsigned long desc_size, + u32 desc_ver) +{ + int node; + int status; + u32 fdt_val32; + u64 fdt_val64; + + /* +* Copy definition of linux_banner here. Since this code is +* built as part of the decompressor for ARM v7, pulling +* in version.c where linux_banner is defined for the +* kernel brings other kernel dependencies with it. +*/ + const char linux_banner[] = + Linux version UTS_RELEASE ( LINUX_COMPILE_BY @ + LINUX_COMPILE_HOST ) ( LINUX_COMPILER ) UTS_VERSION \n; + + /* 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); + return EFI_LOAD_ERROR; + } + /* +* We don't get the size of the FDT if we get if from a +* configuration table. +*/ + if (orig_fdt_size fdt_totalsize(orig_fdt) orig_fdt_size) { + pr_efi_err(sys_table, Truncated device tree! foo!\n); + return EFI_LOAD_ERROR; + } + } + + if (orig_fdt) + status = fdt_open_into(orig_fdt, fdt, new_fdt_size); + else + status = fdt_create_empty_tree(fdt, new_fdt_size); + + if (status != 0) + goto fdt_set_fail; + + /* Delete any memory nodes present */ + while ((node = fdt_subnode_offset(fdt, 0, memory)) = 0) + fdt_del_node(fdt, node); + + node = fdt_subnode_offset(fdt, 0, chosen); + if (node 0) { + node = fdt_add_subnode(fdt, 0, chosen); + if (node 0) { + status = node; /* node is error code when negative */ + goto fdt_set_fail; + } + } + + if ((cmdline_ptr != NULL) (strlen(cmdline_ptr) 0)) { + status = fdt_setprop(fdt, node, bootargs, cmdline_ptr, +strlen(cmdline_ptr) + 1); + if (status) + goto fdt_set_fail; + } + + /* Set initrd address/end in device tree, if present */ + if (initrd_size != 0) { + 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)); + 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)); + if (status) + goto fdt_set_fail; + } + + /* 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)); + if (status) + goto fdt_set_fail; + + fdt_val64 = cpu_to_fdt64((u64)(unsigned long
[PATCH v2 03/15] efi: create memory map iteration helper
From: Mark Salter msal...@redhat.com There are a lot of places in the kernel which iterate through an EFI memory map. Most of these places use essentially the same for-loop code. This patch adds a for_each_efi_memory_desc() helper to clean up all of the existing duplicate code and avoid more in the future. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- include/linux/efi.h |6 ++ 1 file changed, 6 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h index 64d532c..a3276da 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -622,6 +622,12 @@ extern int efi_set_rtc_mmss(const struct timespec *now); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; +/* Iterate through an efi_memory_map */ +#define for_each_efi_memory_desc(m, md) \ + for ((md) = (m)-map; \ +(md) = (efi_memory_desc_t *)((m)-map_end - (m)-desc_size); \ +(md) = (void *)(md) + (m)-desc_size) + /** * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 05/15] efi: add helper function to get UEFI params from FDT
From: Mark Salter msal...@redhat.com ARM and ARM64 architectures use the device tree to pass UEFI parameters from stub to kernel. These parameters are things known to the stub but not discoverable by the kernel after the stub calls ExitBootSerives(). There is a helper function in: drivers/firmware/efi/fdt.c which the stub uses to add the UEFI parameters to the device tree. This patch adds a complimentary helper function which UEFI runtime support may use to retrieve the parameters from the device tree. If an architecture wants to use this helper, it should select CONFIG_UEFI_PARAMS_FROM_FDT. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/Kconfig |7 drivers/firmware/efi/efi.c | 79 ++ include/linux/efi.h |9 + 3 files changed, 95 insertions(+) diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 1e75f48..d3fe28d 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -47,6 +47,13 @@ config EFI_RUNTIME_MAP See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. +config UEFI_PARAMS_FROM_FDT + bool + help + Select this config option from the architecture Kconfig if + the EFI runtime support gets system table address, memory + map address, and other parameters from the device tree. + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index b25b36b..7f6e977 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -20,6 +20,8 @@ #include linux/init.h #include linux/device.h #include linux/efi.h +#include linux/of.h +#include linux/of_fdt.h #include linux/io.h struct efi __read_mostly efi = { @@ -318,3 +320,80 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) return 0; } + +#ifdef CONFIG_UEFI_PARAMS_FROM_FDT + +#define UEFI_PARAM(name, prop, field) \ + { \ + { name }, \ + { prop }, \ + offsetof(struct efi_fdt_params, field),\ + FIELD_SIZEOF(struct efi_fdt_params, field) \ + } + +static __initdata struct { + const char name[32]; + const char propname[32]; + int offset; + int size; +} dt_params[] = { + UEFI_PARAM(System Table, linux,uefi-system-table, system_table), + UEFI_PARAM(MemMap Address, linux,uefi-mmap-start, mmap), + UEFI_PARAM(MemMap Size, linux,uefi-mmap-size, mmap_size), + UEFI_PARAM(MemMap Desc. Size, linux,uefi-mmap-desc-size, desc_size), + UEFI_PARAM(MemMap Desc. Version, linux,uefi-mmap-desc-ver, desc_ver) +}; + +struct param_info { + int verbose; + void *params; +}; + +static int __init fdt_find_uefi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + struct param_info *info = data; + void *prop, *dest; + unsigned long len; + u64 val; + int i; + + if (depth != 1 || + (strcmp(uname, chosen) != 0 strcmp(uname, chosen@0) != 0)) + return 0; + + pr_info(Getting parameters from FDT:\n); + + for (i = 0; i ARRAY_SIZE(dt_params); i++) { + prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); + if (!prop) { + pr_err(Can't find %s in device tree!\n, + dt_params[i].name); + return 0; + } + dest = info-params + dt_params[i].offset; + + val = of_read_number(prop, len / sizeof(u32)); + + if (dt_params[i].size == sizeof(u32)) + *(u32 *)dest = val; + else + *(u64 *)dest = val; + + if (info-verbose) + pr_info( %s: 0x%0*llx\n, dt_params[i].name, + dt_params[i].size * 2, val); + } + return 1; +} + +int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) +{ + struct param_info info; + + info.verbose = verbose; + info.params = params; + + return of_scan_flat_dt(fdt_find_uefi_params, info); +} +#endif /* CONFIG_UEFI_PARAMS_FROM_FDT */ diff --git a/include/linux/efi.h b/include/linux/efi.h index a3276da..d450673 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -483,6 +483,14 @@ struct efi_memory_map { unsigned long desc_size; }; +struct efi_fdt_params { + u64 system_table; + u64 mmap; + u32 mmap_size; + u32 desc_size; + u32 desc_ver; +}; + typedef struct { u32 revision; void *parent_handle; @@ -620,6 +628,7 @@ extern void
[PATCH v2 07/15] efi: Add shared printk wrapper for consistent prefixing
From: Roy Franz roy.fr...@linaro.org Add a wrapper for printk to standardize the prefix for informational and error messages from the EFI stub. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 661f425..4c8ab86 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -45,6 +45,9 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str) } } +#define pr_efi(sys_table, msg) efi_printk(sys_table, EFI stub: msg) +#define pr_efi_err(sys_table, msg) efi_printk(sys_table, EFI stub: ERROR: msg) + static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, efi_memory_desc_t **map, @@ -324,7 +327,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, nr_files * sizeof(*files), (void **)files); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc mem for file handle list\n); + pr_efi_err(sys_table_arg, Failed to alloc mem for file handle list\n); goto fail; } @@ -376,13 +379,13 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, image-device_handle, fs_proto, (void **)io); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to handle fs_proto\n); + pr_efi_err(sys_table_arg, Failed to handle fs_proto\n); goto free_files; } status = efi_call_phys2(io-open_volume, io, fh); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to open volume\n); + pr_efi_err(sys_table_arg, Failed to open volume\n); goto free_files; } } @@ -390,7 +393,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, status = efi_call_phys5(fh-open, fh, h, filename_16, EFI_FILE_MODE_READ, (u64)0); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to open file: ); + pr_efi_err(sys_table_arg, Failed to open file: ); efi_char16_printk(sys_table_arg, filename_16); efi_printk(sys_table_arg, \n); goto close_handles; @@ -402,7 +405,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, status = efi_call_phys4(h-get_info, h, info_guid, info_sz, NULL); if (status != EFI_BUFFER_TOO_SMALL) { - efi_printk(sys_table_arg, Failed to get file info size\n); + pr_efi_err(sys_table_arg, Failed to get file info size\n); goto close_handles; } @@ -411,7 +414,7 @@ grow: EFI_LOADER_DATA, info_sz, (void **)info); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc mem for file info\n); + pr_efi_err(sys_table_arg, Failed to alloc mem for file info\n); goto close_handles; } @@ -427,7 +430,7 @@ grow: efi_call_phys1(sys_table_arg-boottime-free_pool, info); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to get file info\n); + pr_efi_err(sys_table_arg, Failed to get file info\n); goto close_handles; } @@ -446,13 +449,13 @@ grow: status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000, file_addr, max_addr); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc highmem for files\n); + pr_efi_err(sys_table_arg, Failed to alloc highmem for files\n); goto close_handles; } /* We've run out of free low memory. */ if (file_addr max_addr) { - efi_printk(sys_table_arg, We've run out of free low memory\n); + pr_efi_err(sys_table_arg, We've run out of free low
[PATCH v2 02/15] efi: x86: Improve cmdline conversion
From: H. Peter Anvin h...@zytor.com Improve the conversion of the UTF-16 EFI command line to UTF-8 for passing to the kernel. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: H. Peter Anvin h...@zytor.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/efi-stub-helper.c | 91 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index a7677ba..feca05f 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -488,8 +488,7 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) hdr-type_of_loader = 0x21; /* Convert unicode cmdline to ascii */ - cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, - options_size); + cmdline_ptr = efi_convert_cmdline(sys_table, image, options_size); if (!cmdline_ptr) goto fail; hdr-cmd_line_ptr = (unsigned long)cmdline_ptr; diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 6811af7..661f425 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -575,52 +575,99 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, } /* - * Convert the unicode UEFI command line to ASCII to pass to kernel. + * Get the number of UTF-8 bytes corresponding to an UTF-16 character. + * This overestimates for surrogates, but that is okay. + */ +static int efi_utf8_bytes(u16 c) +{ + return 1 + (c = 0x80) + (c = 0x800); +} + +/* + * Convert an UTF-16 string, not necessarily null terminated, to UTF-8. + */ +static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) +{ + unsigned int c; + + while (n--) { + c = *src++; + if (n c = 0xd800 c = 0xdbff + *src = 0xdc00 *src = 0xdfff) { + c = 0x1 + ((c 0x3ff) 10) + (*src 0x3ff); + src++; + n--; + } + if (c = 0xd800 c = 0xdfff) + c = 0xfffd; /* Unmatched surrogate */ + if (c 0x80) { + *dst++ = c; + continue; + } + if (c 0x800) { + *dst++ = 0xc0 + (c 6); + goto t1; + } + if (c 0x1) { + *dst++ = 0xe0 + (c 12); + goto t2; + } + *dst++ = 0xf0 + (c 18); + *dst++ = 0x80 + ((c 12) 0x3f); +t2: + *dst++ = 0x80 + ((c 6) 0x3f); +t1: + *dst++ = 0x80 + (c 0x3f); + } + + return dst; +} + +/* + * Do proper conversion from UTF-16 to UTF-8 * Size of memory allocated return in *cmd_line_len. * Returns NULL on error. */ -static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg, - efi_loaded_image_t *image, - int *cmd_line_len) +static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, +efi_loaded_image_t *image, +int *cmd_line_len) { - u16 *s2; + const u16 *s2; u8 *s1 = NULL; unsigned long cmdline_addr = 0; - int load_options_size = image-load_options_size / 2; /* ASCII */ - void *options = image-load_options; - int options_size = 0; + int load_options_chars = image-load_options_size / 2; /* UTF-16 */ + const u16 *options = image-load_options; + int options_bytes = 0; /* UTF-8 bytes */ + int options_chars = 0; /* UTF-16 chars */ efi_status_t status; - int i; u16 zero = 0; if (options) { s2 = options; - while (*s2 *s2 != '\n' options_size load_options_size) { - s2++; - options_size++; + while (options_chars load_options_chars + *s2 *s2 != '\n') { + options_bytes += efi_utf8_bytes(*s2++); + options_chars++; } } - if (options_size == 0) { - /* No command line options, so return empty string*/ - options_size = 1; + if (!options_chars) { + /* No command line options, so return empty string */ options = zero; } - options_size++; /* NUL termination */ + options_bytes++; /* NUL termination */ - status = efi_low_alloc(sys_table_arg, options_size, 0, cmdline_addr); + status = efi_low_alloc(sys_table_arg, options_bytes, 0, cmdline_addr
[PATCH 20/22] Improve cmdline conversion
From: H. Peter Anvin h...@zytor.com Improve the conversion of the UTF-16 EFI command line to UTF-8 for passing to the kernel. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: H. Peter Anvin h...@zytor.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/arm-stub.c|3 +- drivers/firmware/efi/efi-stub-helper.c | 89 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index a7677ba..feca05f 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -488,8 +488,7 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) hdr-type_of_loader = 0x21; /* Convert unicode cmdline to ascii */ - cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, - options_size); + cmdline_ptr = efi_convert_cmdline(sys_table, image, options_size); if (!cmdline_ptr) goto fail; hdr-cmd_line_ptr = (unsigned long)cmdline_ptr; diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index aefe963..b505fde 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -87,8 +87,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, * protocol. We are going to copy the command line into the * device tree, so this can be allocated anywhere. */ - cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, - cmdline_size); + cmdline_ptr = efi_convert_cmdline(sys_table, image, cmdline_size); if (!cmdline_ptr) { pr_efi_err(sys_table, getting command line via LOADED_IMAGE_PROTOCOL\n); goto fail_free_image; diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 8477a72..2ee69ea 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -625,52 +625,99 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, } /* - * Convert the unicode UEFI command line to ASCII to pass to kernel. + * Get the number of UTF-8 bytes corresponding to an UTF-16 character. + * This overestimates for surrogates, but that is okay. + */ +static int efi_utf8_bytes(u16 c) +{ + return 1 + (c = 0x80) + (c = 0x800); +} + +/* + * Convert an UTF-16 string, not necessarily null terminated, to UTF-8. + */ +static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) +{ + unsigned int c; + + while (n--) { + c = *src++; + if (n c = 0xd800 c = 0xdbff + *src = 0xdc00 *src = 0xdfff) { + c = 0x1 + ((c 0x3ff) 10) + (*src 0x3ff); + src++; + n--; + } + if (c = 0xd800 c = 0xdfff) + c = 0xfffd; /* Unmatched surrogate */ + if (c 0x80) { + *dst++ = c; + continue; + } + if (c 0x800) { + *dst++ = 0xc0 + (c 6); + goto t1; + } + if (c 0x1) { + *dst++ = 0xe0 + (c 12); + goto t2; + } + *dst++ = 0xf0 + (c 18); + *dst++ = 0x80 + ((c 12) 0x3f); +t2: + *dst++ = 0x80 + ((c 6) 0x3f); +t1: + *dst++ = 0x80 + (c 0x3f); + } + + return dst; +} + +/* + * Do proper conversion from UTF-16 to UTF-8 * Size of memory allocated return in *cmd_line_len. * Returns NULL on error. */ -static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg, - efi_loaded_image_t *image, - int *cmd_line_len) +static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, +efi_loaded_image_t *image, +int *cmd_line_len) { - u16 *s2; + const u16 *s2; u8 *s1 = NULL; unsigned long cmdline_addr = 0; - int load_options_size = image-load_options_size / 2; /* ASCII */ - void *options = image-load_options; - int options_size = 0; + int load_options_chars = image-load_options_size / 2; /* UTF-16 */ + const u16 *options = image-load_options; + int options_bytes = 0; /* UTF-8 bytes */ + int options_chars = 0; /* UTF-16 chars */ efi_status_t status; - int i; u16 zero = 0; if (options) { s2 = options; - while (*s2 *s2 != '\n' options_size load_options_size
[PATCH 00/22] arm/arm64: UEFI stubs + runtime services
This is a combined set of patches for the arm and arm64 kernel support for UEFI firmware. The set depends on the following prerequisite sets: - Laura Abbott's 'Remove ARM meminfo' - Matt Fleming's 'Move facility flags to struct efi' - Mark Salter's 'Generic fixmap' - Mark Salter's 'Generic early_ioremap' - Mark Salter's 'EFI memory map iteration helper' All of these are held on top of 3.14-rc1, with the patches in this set, in git://git.linaro.org/people/leif.lindholm/linux.git, rebasing branch uefi-for-upstream. New in this version: - Much more stub code shared arm/arm64. - Stub looks in configuration tables for DT. - Stub creates empty DT if none found/specified. - Stub ignores dtb= option when UEFI Secure Boot active. - Stub deletes any memory nodes in DT. - Kernel sets up available RAM for memblock from UEFI memory map. (So no longer need different DTs or command line parameters for otherwise identical platforms with different amounts of RAM.) - arm64 now compatible with 64K pages (with 4K UEFI page size). - Fix mapping of runtime mmio regions on arm64. - Reworked update_sctlr asm macro. - Various cleanup and style fixes. --- Ard Biesheuvel (1): arm: efistub: ignore dtb= when UEFI SecureBoot is enabled H. Peter Anvin (1): Improve cmdline conversion Leif Lindholm (6): arm: break part of __soft_restart out into separate function arm: add new asm macro update_sctlr Documentation: arm: add UEFI support documentation arm: Add [U]EFI runtime services support init: efi: arm: enable (U)EFI runtime services on arm arm: update boot/compressed/.gitignore Mark Salter (6): efi: add helper function to get UEFI params from FDT lib: add fdt_empty_tree.c arm64: Add function to create identity mappings arm64: add EFI stub doc: arm64: add description of EFI stub support arm64: add EFI runtime services Roy Franz (8): efi-stub.txt updates for ARM Add shared printk wrapper for consistent prefixing Add helper functions used by arm/arm64 Add shared FDT related functions for ARM/ARM64 Add strstr to compressed string.c for ARM. Add shared arm/arm64 EFI stub Add EFI stub for ARM Disable stack protection for decompressor/stub Documentation/arm/00-INDEX |3 + Documentation/arm/uefi.txt | 64 + Documentation/arm64/booting.txt|4 + Documentation/efi-stub.txt | 33 ++- arch/arm/Kconfig | 27 ++ arch/arm/boot/compressed/.gitignore|3 + arch/arm/boot/compressed/Makefile | 19 +- arch/arm/boot/compressed/efi-header.S | 117 arch/arm/boot/compressed/efi-stub.c| 118 arch/arm/boot/compressed/efi-stub.h|5 + arch/arm/boot/compressed/head.S| 83 +- arch/arm/boot/compressed/string.c | 21 ++ arch/arm/include/asm/assembler.h | 14 + arch/arm/include/asm/idmap.h |1 + arch/arm/include/asm/uefi.h| 28 ++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/process.c | 12 +- arch/arm/kernel/setup.c|7 +- arch/arm/kernel/uefi.c | 413 arch/arm/kernel/uefi_phys.S| 69 + arch/arm/mm/idmap.c| 15 ++ arch/arm64/Kconfig | 26 ++ arch/arm64/include/asm/efi.h | 12 + arch/arm64/include/asm/mmu.h |2 + arch/arm64/kernel/Makefile |4 + arch/arm64/kernel/efi-entry.S | 93 +++ arch/arm64/kernel/efi-stub.c | 67 + arch/arm64/kernel/efi.c| 462 arch/arm64/kernel/head.S | 112 arch/arm64/kernel/setup.c |3 + arch/arm64/mm/mmu.c| 66 +++-- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/Kconfig |7 + drivers/firmware/efi/arm-stub.c| 146 ++ drivers/firmware/efi/efi-stub-helper.c | 199 +++--- drivers/firmware/efi/efi.c | 79 ++ drivers/firmware/efi/fdt.c | 268 ++ include/linux/efi.h| 12 + init/main.c|5 + lib/Makefile |3 +- lib/fdt_empty_tree.c |2 + 41 files changed, 2534 insertions(+), 95 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/boot/compressed/efi-stub.h create mode 100644 arch/arm/include/asm/uefi.h create mode 100644 arch/arm/kernel/uefi.c create mode 100644 arch/arm/kernel/uefi_phys.S create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 arch/arm64/kernel/efi.c create mode 100644
[PATCH 21/22] arm: efistub: ignore dtb= when UEFI SecureBoot is enabled
From: Ard Biesheuvel ard.biesheu...@linaro.org Loading unauthenticated FDT blobs directly from storage is a security hazard, so this should only be allowed when running with UEFI Secure Boot disabled. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/arm-stub.c|4 +++- drivers/firmware/efi/efi-stub-helper.c | 24 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index b505fde..c651082 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -95,7 +95,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, /* Load a device tree from the configuration table, if present. */ fdt_addr = (uintptr_t)get_fdt(sys_table); - if (!fdt_addr) { + if (efi_secureboot_enabled(sys_table)) + pr_efi(sys_table, UEFI Secure Boot is enabled, ignoring dtb= commandline option.\n); + else if (!fdt_addr) { status = handle_cmdline_files(sys_table, image, cmdline_ptr, dtb=, ~0UL, (unsigned long *)fdt_addr, diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 2ee69ea..6221be7 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -721,3 +721,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, *cmd_line_len = options_bytes; return (char *)cmdline_addr; } + +static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +{ + static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t const var_name[] __initconst = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + + efi_get_variable_t *f_getvar = sys_table_arg-runtime-get_variable; + unsigned long size = sizeof(u8); + efi_status_t status; + u8 val; + + status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name, + (efi_guid_t *)var_guid, NULL, size, val); + + switch (status) { + case EFI_SUCCESS: + return val; + case EFI_NOT_FOUND: + return 0; + default: + return 1; + } +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 15/22] lib: add fdt_empty_tree.c
From: Mark Salter msal...@redhat.com CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- lib/Makefile |3 ++- lib/fdt_empty_tree.c |2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 126b34f..ce085d2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -146,7 +146,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000..5d30c58 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include linux/libfdt_env.h +#include ../scripts/dtc/libfdt/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 22/22] arm: update boot/compressed/.gitignore
Add bswapsdi2.S, fdt_empty_tree.c and fdt_sw.c to ignore list. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/boot/compressed/.gitignore |3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index 47279aa..cc3487e 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1,4 +1,5 @@ ashldi3.S +bswapsdi2.S font.c lib1funcs.S hyp-stub.S @@ -13,8 +14,10 @@ vmlinux.lds # borrowed libfdt files fdt.c fdt.h +fdt_empty_tree.c fdt_ro.c fdt_rw.c +fdt_sw.c fdt_wip.c libfdt.h libfdt_internal.h -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-efi in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html