diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/Makefile | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 15 | ||||
-rw-r--r-- | lib/efi_loader/efi_disk.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 9 | ||||
-rw-r--r-- | lib/efi_selftest/Makefile | 7 | ||||
-rw-r--r-- | lib/fdtdec.c | 17 | ||||
-rw-r--r-- | lib/optee/optee.c | 140 |
7 files changed, 178 insertions, 17 deletions
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 01769ea58b..7db4060286 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -6,6 +6,9 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it +asflags-y += -DHOST_ARCH="$(HOST_ARCH)" +ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" + CFLAGS_efi_boottime.o += \ -DFW_VERSION="0x$(VERSION)" \ -DFW_PATCHLEVEL="0x$(PATCHLEVEL)" diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index ac5e6f7e14..17a0c5bb45 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -1032,6 +1032,16 @@ out: return EFI_SUCCESS; } +/** + * efi_dp_from_name() - convert U-Boot device and file path to device path + * + * @dev: U-Boot device, e.g. 'mmc' + * @devnr: U-Boot device number, e.g. 1 for 'mmc:1' + * @path: file path relative to U-Boot device, may be NULL + * @device: pointer to receive device path of the device + * @file: pointer to receive device path for the file + * Return: status code + */ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, const char *path, struct efi_device_path **device, @@ -1071,10 +1081,9 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, s = filename; while ((s = strchr(s, '/'))) *s++ = '\\'; - *file = efi_dp_from_file(((!is_net && device) ? desc : NULL), - part, filename); + *file = efi_dp_from_file(is_net ? NULL : desc, part, filename); - if (!file) + if (!*file) return EFI_INVALID_PARAMETER; return EFI_SUCCESS; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 861fcaf374..ed7fb3f7d3 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -337,7 +337,9 @@ static efi_status_t efi_disk_add_dev( diskobj->dp); if (ret != EFI_SUCCESS) return ret; - if (part >= 1 && efi_fs_exists(desc, part)) { + /* partitions or whole disk without partitions */ + if ((part || desc->part_type == PART_TYPE_UNKNOWN) && + efi_fs_exists(desc, part)) { diskobj->volume = efi_simple_file_system(desc, part, diskobj->dp); ret = efi_add_protocol(&diskobj->header, diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 83cbc9154f..d46001f608 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -738,8 +738,10 @@ static void add_u_boot_and_runtime(void) unsigned long uboot_stack_size = 16 * 1024 * 1024; /* Add U-Boot */ - uboot_start = (gd->start_addr_sp - uboot_stack_size) & ~EFI_PAGE_MASK; - uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT; + uboot_start = ((uintptr_t)map_sysmem(gd->start_addr_sp, 0) - + uboot_stack_size) & ~EFI_PAGE_MASK; + uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) - + uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false); #if defined(__aarch64__) @@ -767,8 +769,7 @@ int efi_memory_init(void) { efi_add_known_memory(); - if (!IS_ENABLED(CONFIG_SANDBOX)) - add_u_boot_and_runtime(); + add_u_boot_and_runtime(); #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER /* Request a 32bit 64MB bounce buffer region */ diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 8348014077..487cb4c674 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -5,6 +5,9 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it +asflags-y += -DHOST_ARCH="$(HOST_ARCH)" +ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" + CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding @@ -55,8 +58,8 @@ obj-y += efi_selftest_block_device.o endif # TODO: As of v2019.10 the relocation code for the EFI application cannot -# be built on ARMv7-M and Sandbox. -ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M),) +# be built on ARMv7-M. +ifeq ($(CONFIG_CPU_V7M),) obj-y += \ efi_selftest_exception.o \ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 125d9dbf26..61af3472e6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1309,7 +1309,8 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, } if (addr == carveout->start && (addr + size) == carveout->end) { - *phandlep = fdt_get_phandle(blob, node); + if (phandlep) + *phandlep = fdt_get_phandle(blob, node); return 0; } } @@ -1338,13 +1339,15 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, if (node < 0) return node; - err = fdt_generate_phandle(blob, &phandle); - if (err < 0) - return err; + if (phandlep) { + err = fdt_generate_phandle(blob, &phandle); + if (err < 0) + return err; - err = fdtdec_set_phandle(blob, node, phandle); - if (err < 0) - return err; + err = fdtdec_set_phandle(blob, node, phandle); + if (err < 0) + return err; + } /* store one or two address cells */ if (na > 1) diff --git a/lib/optee/optee.c b/lib/optee/optee.c index db92cd9af2..c883c498e1 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -5,6 +5,8 @@ */ #include <common.h> +#include <malloc.h> +#include <linux/libfdt.h> #include <tee/optee.h> #define optee_hdr_err_msg \ @@ -63,3 +65,141 @@ error: return ret; } + +#if defined(CONFIG_OF_LIBFDT) +static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob) +{ + int old_offs, offs, ret, len; + const void *prop; + + old_offs = fdt_path_offset(old_blob, "/firmware/optee"); + if (old_offs < 0) { + debug("Original OP-TEE Device Tree node not found"); + return old_offs; + } + + offs = fdt_path_offset(fdt_blob, "/firmware"); + if (offs < 0) { + offs = fdt_path_offset(fdt_blob, "/"); + if (offs < 0) + return offs; + + offs = fdt_add_subnode(fdt_blob, offs, "firmware"); + if (offs < 0) + return offs; + } + + offs = fdt_add_subnode(fdt_blob, offs, "optee"); + if (offs < 0) + return ret; + + /* copy the compatible property */ + prop = fdt_getprop(old_blob, old_offs, "compatible", &len); + if (!prop) { + debug("missing OP-TEE compatible property"); + return -EINVAL; + } + + ret = fdt_setprop(fdt_blob, offs, "compatible", prop, len); + if (ret < 0) + return ret; + + /* copy the method property */ + prop = fdt_getprop(old_blob, old_offs, "method", &len); + if (!prop) { + debug("missing OP-TEE method property"); + return -EINVAL; + } + + ret = fdt_setprop(fdt_blob, offs, "method", prop, len); + if (ret < 0) + return ret; + + return 0; +} + +int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) +{ + int nodeoffset, subnode, ret; + struct fdt_resource res; + + if (fdt_check_header(old_blob)) + return -EINVAL; + + if (fdt_check_header(new_blob)) + return -EINVAL; + + /* only proceed if there is an /firmware/optee node */ + if (fdt_path_offset(old_blob, "/firmware/optee") < 0) { + debug("No OP-TEE firmware node in old fdt, nothing to do"); + return 0; + } + + /* + * Do not proceed if the target dt already has an OP-TEE node. + * In this case assume that the system knows better somehow, + * so do not interfere. + */ + if (fdt_path_offset(new_blob, "/firmware/optee") >= 0) { + debug("OP-TEE Device Tree node already exists in target"); + return 0; + } + + ret = optee_copy_firmware_node(old_blob, new_blob); + if (ret < 0) { + printf("Failed to add OP-TEE firmware node\n"); + return ret; + } + + /* optee inserts its memory regions as reserved-memory nodes */ + nodeoffset = fdt_subnode_offset(old_blob, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(old_blob, nodeoffset); + while (subnode >= 0) { + const char *name = fdt_get_name(old_blob, + subnode, NULL); + if (!name) + return -EINVAL; + + /* only handle optee reservations */ + if (strncmp(name, "optee", 5)) + continue; + + /* check if this subnode has a reg property */ + ret = fdt_get_resource(old_blob, subnode, "reg", 0, + &res); + if (!ret) { + struct fdt_memory carveout = { + .start = res.start, + .end = res.end, + }; + char *oldname, *nodename, *tmp; + + oldname = strdup(name); + if (!oldname) + return -ENOMEM; + + tmp = oldname; + nodename = strsep(&tmp, "@"); + if (!nodename) { + free(oldname); + return -EINVAL; + } + + ret = fdtdec_add_reserved_memory(new_blob, + nodename, + &carveout, + NULL); + free(oldname); + + if (ret < 0) + return ret; + } + + subnode = fdt_next_subnode(old_blob, subnode); + } + } + + return 0; +} +#endif |