[PATCH] resource: enable use of iomem command on EFI systems
Sascha Hauer
sha at pengutronix.de
Tue Apr 13 08:31:02 BST 2021
On Sat, Apr 10, 2021 at 01:03:55PM +0200, Ahmad Fatoum wrote:
> iomem was so far unimplemented for EFI, because barebox didn't know what
> to put there as the UEFI implementation does the heavy lifting.
>
> Add an initcall that uses the EFI get_memory_map entry point to
> remedy this.
>
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
> ---
> arch/x86/mach-efi/elf_x86_64_efi.lds.S | 3 +
> common/efi/Makefile | 1 +
> common/efi/efi-iomem.c | 175 +++++++++++++++++++++++++
> common/memory.c | 2 +-
> include/efi.h | 9 ++
> 5 files changed, 189 insertions(+), 1 deletion(-)
> create mode 100644 common/efi/efi-iomem.c
Applied, thanks
Sascha
>
> diff --git a/arch/x86/mach-efi/elf_x86_64_efi.lds.S b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> index ed79118a3615..ab4a9e815c00 100644
> --- a/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> +++ b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> @@ -42,6 +42,7 @@ SECTIONS
> *(.got.plt)
> *(.got)
> *(.data*)
> + __bss_start = .;
> *(.sdata)
> /* the EFI loader doesn't seem to like a .bss section, so we stick
> * it all into .data: */
> @@ -51,7 +52,9 @@ SECTIONS
> *(.bss)
> *(COMMON)
> *(.rel.local)
> + __bss_stop = .;
> }
> + _edata = .;
>
> . = ALIGN(4096);
> .dynamic : { *(.dynamic) }
> diff --git a/common/efi/Makefile b/common/efi/Makefile
> index ef19969f93d5..d746fabe2109 100644
> --- a/common/efi/Makefile
> +++ b/common/efi/Makefile
> @@ -1,3 +1,4 @@
> obj-y += efi.o
> obj-y += efi-image.o
> bbenv-y += env-efi
> +obj-$(CONFIG_CMD_IOMEM) += efi-iomem.o
> diff --git a/common/efi/efi-iomem.c b/common/efi/efi-iomem.c
> new file mode 100644
> index 000000000000..e223c595c478
> --- /dev/null
> +++ b/common/efi/efi-iomem.c
> @@ -0,0 +1,175 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2019 Ahmad Fatoum, Pengutronix
> +
> +#define pr_fmt(fmt) "efi-iomem: " fmt
> +
> +#include <common.h>
> +#include <init.h>
> +#include <efi.h>
> +#include <efi/efi.h>
> +#include <memory.h>
> +#include <linux/sizes.h>
> +
> +static int efi_parse_mmap(struct efi_memory_desc *desc)
> +{
> + struct resource *res;
> + u32 flags;
> + const char *name;
> + char *fullname;
> + resource_size_t va_base, va_size;
> + int ret = 0;
> +
> + va_size = desc->npages * SZ_4K;
> + if (!va_size)
> + return 0;
> +
> + /* XXX At least OVMF doesn't populate ->virt_start and leaves it at zero
> + * for all mapping. Thus assume a 1:1 mapping and ignore virt_start
> + */
> + va_base = desc->phys_start;
> +
> + switch (desc->type) {
> + case EFI_RESERVED_TYPE:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "reserved";
> + flags = IORESOURCE_MEM | IORESOURCE_DISABLED;
> + break;
> + case EFI_LOADER_CODE:
> + return barebox_add_memory_bank("loader code", va_base, va_size);
> + case EFI_LOADER_DATA:
> + return barebox_add_memory_bank("loader data", va_base, va_size);
> + case EFI_BOOT_SERVICES_CODE:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "boot services code";
> + flags = IORESOURCE_MEM | IORESOURCE_READONLY;
> + break;
> + case EFI_BOOT_SERVICES_DATA:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "boot services data";
> + flags = IORESOURCE_MEM;
> + break;
> + case EFI_RUNTIME_SERVICES_CODE:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "runtime services code";
> + flags = IORESOURCE_MEM | IORESOURCE_READONLY;
> + break;
> + case EFI_RUNTIME_SERVICES_DATA:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "runtime services data";
> + flags = IORESOURCE_MEM;
> + break;
> + case EFI_CONVENTIONAL_MEMORY:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "conventional memory";
> + flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_CACHEABLE;
> + break;
> + case EFI_UNUSABLE_MEMORY:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "unusable";
> + flags = IORESOURCE_MEM | IORESOURCE_DISABLED;
> + break;
> + case EFI_ACPI_RECLAIM_MEMORY:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "ACPI reclaim memory";
> + flags = IORESOURCE_MEM | IORESOURCE_READONLY;
> + break;
> + case EFI_ACPI_MEMORY_NVS:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "ACPI NVS memory";
> + flags = IORESOURCE_MEM | IORESOURCE_READONLY;
> + break;
> + case EFI_MEMORY_MAPPED_IO:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "MMIO";
> + flags = IORESOURCE_MEM;
> + break;
> + case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "MMIOPORT";
> + flags = IORESOURCE_IO;
> + break;
> + case EFI_PAL_CODE:
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> + name = "PAL code";
> + flags = IORESOURCE_MEM | IORESOURCE_ROM_BIOS_COPY;
> + break;
> + default:
> + if (!(desc->type & (1U << 31))) {
> + pr_warn("illegal memory type = %u >= %u\n",
> + desc->type, EFI_MAX_MEMORY_TYPE);
> + return -EINVAL;
> + }
> +
> + if (!IS_ENABLED(DEBUG))
> + return 0;
> +
> + name = "vendor reserved";
> + flags = IORESOURCE_MEM | IORESOURCE_ROM_BIOS_COPY;
> + }
> +
> + fullname = xasprintf("%s@%llx", name, desc->phys_start);
> +
> + pr_debug("%s: (0x%llx+0x%llx)\n", fullname, va_base, va_size);
> +
> + res = request_iomem_region(fullname, va_base, va_base + va_size - 1);
> + if (IS_ERR(res)) {
> + ret = PTR_ERR(res);
> + goto out;
> + }
> +
> + res->flags |= flags;
> +
> +out:
> + free(fullname);
> + return ret;
> +}
> +
> +static int efi_barebox_populate_mmap(void)
> +{
> + void *desc;
> + u8 *mmap_buf = NULL;
> + efi_status_t efiret;
> + size_t mmap_size;
> + size_t mapkey;
> + size_t descsz;
> + u32 descver;
> + int ret = 0;
> +
> + mmap_size = sizeof(struct efi_memory_desc);
> +
> + do {
> + mmap_buf = xrealloc(mmap_buf, mmap_size);
> + efiret = BS->get_memory_map(&mmap_size, mmap_buf,
> + &mapkey, &descsz, &descver);
> + } while (efiret == EFI_BUFFER_TOO_SMALL);
> +
> + if (EFI_ERROR(efiret)) {
> + ret = -efi_errno(efiret);
> + goto out;
> + }
> +
> + if (descver != 1) {
> + ret = -ENOSYS;
> + goto out;
> + }
> +
> + for (desc = mmap_buf; (u8 *)desc < &mmap_buf[mmap_size]; desc += descsz)
> + efi_parse_mmap(desc);
> +
> +out:
> + free(mmap_buf);
> + return ret;
> +}
> +mem_initcall(efi_barebox_populate_mmap);
> diff --git a/common/memory.c b/common/memory.c
> index a56eaf949411..392522bfc3db 100644
> --- a/common/memory.c
> +++ b/common/memory.c
> @@ -53,7 +53,7 @@ void mem_malloc_init(void *start, void *end)
> mem_malloc_initialized = 1;
> }
>
> -#if !defined __SANDBOX__ && !defined CONFIG_EFI_BOOTUP
> +#if !defined __SANDBOX__
> static int mem_malloc_resource(void)
> {
> /*
> diff --git a/include/efi.h b/include/efi.h
> index b9f3428dc550..439803c29437 100644
> --- a/include/efi.h
> +++ b/include/efi.h
> @@ -91,6 +91,15 @@ typedef struct {
> * Memory map descriptor:
> */
>
> +struct efi_memory_desc {
> + u32 type; /* enum efi_memory_type */
> + u32 _padding;
> + efi_physical_addr_t phys_start;
> + void *virt_start;
> + u64 npages;
> + u64 attrs;
> +};
> +
> /* Memory types: */
> enum efi_memory_type {
> EFI_RESERVED_TYPE,
> --
> 2.30.0
>
>
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list