mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] resource: enable use of iomem command on EFI systems
@ 2021-04-10 11:03 Ahmad Fatoum
  2021-04-13  7:31 ` Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Ahmad Fatoum @ 2021-04-10 11:03 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

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@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

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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] resource: enable use of iomem command on EFI systems
  2021-04-10 11:03 [PATCH] resource: enable use of iomem command on EFI systems Ahmad Fatoum
@ 2021-04-13  7:31 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2021-04-13  7:31 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox

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@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@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 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-04-13  7:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-10 11:03 [PATCH] resource: enable use of iomem command on EFI systems Ahmad Fatoum
2021-04-13  7:31 ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox