[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