summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mach-efi/elf_x86_64_efi.lds.S3
-rw-r--r--common/efi/Makefile1
-rw-r--r--common/efi/efi-iomem.c175
-rw-r--r--common/memory.c2
-rw-r--r--include/efi.h9
5 files changed, 189 insertions, 1 deletions
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 ed79118a36..ab4a9e815c 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 ef19969f93..d746fabe21 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 0000000000..e223c595c4
--- /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 a56eaf9494..392522bfc3 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 b9f3428dc5..439803c294 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,