diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-06 21:04:10 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-02-06 21:04:10 +0000 |
commit | cabe6937f2c9d0a50e4631c0545bddd650233ae8 (patch) | |
tree | 76d9e0cabe45c1ed6d9ea87a5deb9c75c4345653 /common | |
parent | fb75a334a971078f2f231280ca87837aef5a2000 (diff) | |
parent | 1d4a3be615bde2ff311fece1ab3225cb0a0cb65d (diff) | |
download | platform_external_arm-trusted-firmware-android11-dev.tar.gz platform_external_arm-trusted-firmware-android11-dev.tar.bz2 platform_external_arm-trusted-firmware-android11-dev.zip |
Merge '5f62213e684dbea03b5a2bb732405a03ccc1a815' into master am: 5dfd96a0b3 am: 780068d4ee am: 1d4a3be615android-mainline-11.0.0_r9android-mainline-11.0.0_r8android-mainline-11.0.0_r7android-mainline-11.0.0_r6android-mainline-11.0.0_r5android-mainline-11.0.0_r44android-mainline-11.0.0_r43android-mainline-11.0.0_r42android-mainline-11.0.0_r41android-mainline-11.0.0_r40android-mainline-11.0.0_r4android-mainline-11.0.0_r39android-mainline-11.0.0_r38android-mainline-11.0.0_r37android-mainline-11.0.0_r36android-mainline-11.0.0_r35android-mainline-11.0.0_r34android-mainline-11.0.0_r33android-mainline-11.0.0_r32android-mainline-11.0.0_r31android-mainline-11.0.0_r30android-mainline-11.0.0_r3android-mainline-11.0.0_r29android-mainline-11.0.0_r28android-mainline-11.0.0_r27android-mainline-11.0.0_r26android-mainline-11.0.0_r25android-mainline-11.0.0_r24android-mainline-11.0.0_r23android-mainline-11.0.0_r22android-mainline-11.0.0_r21android-mainline-11.0.0_r20android-mainline-11.0.0_r2android-mainline-11.0.0_r19android-mainline-11.0.0_r18android-mainline-11.0.0_r17android-mainline-11.0.0_r16android-mainline-11.0.0_r15android-mainline-11.0.0_r14android-mainline-11.0.0_r13android-mainline-11.0.0_r12android-mainline-11.0.0_r10android-mainline-11.0.0_r1android-11.0.0_r45android-11.0.0_r44android-11.0.0_r43android-11.0.0_r42android-11.0.0_r41android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android-11.0.0_r37android-11.0.0_r36android-11.0.0_r35android-11.0.0_r34android-11.0.0_r33android-11.0.0_r32android-11.0.0_r31android-11.0.0_r30android-11.0.0_r29android-11.0.0_r28android-11.0.0_r27android-11.0.0_r26android-11.0.0_r24android-11.0.0_r23android-11.0.0_r22android-11.0.0_r21android-11.0.0_r20android-11.0.0_r19android-11.0.0_r18android-11.0.0_r16android11-qpr3-s1-releaseandroid11-qpr3-releaseandroid11-qpr2-releaseandroid11-qpr1-s2-releaseandroid11-qpr1-s1-releaseandroid11-qpr1-releaseandroid11-qpr1-d-s1-releaseandroid11-qpr1-d-releaseandroid11-qpr1-c-releaseandroid11-mainline-tethering-releaseandroid11-mainline-sparse-2021-jan-releaseandroid11-mainline-sparse-2020-dec-releaseandroid11-mainline-releaseandroid11-mainline-permission-releaseandroid11-mainline-os-statsd-releaseandroid11-mainline-networkstack-releaseandroid11-mainline-media-swcodec-releaseandroid11-mainline-media-releaseandroid11-mainline-extservices-releaseandroid11-mainline-documentsui-releaseandroid11-mainline-conscrypt-releaseandroid11-mainline-cellbroadcast-releaseandroid11-mainline-captiveportallogin-releaseandroid11-devandroid11-d2-releaseandroid11-d1-b-release
Change-Id: Ia911040759d199f8c1ec0b51abd4fa556a6b8b40
Diffstat (limited to 'common')
-rw-r--r-- | common/aarch64/debug.S | 10 | ||||
-rw-r--r-- | common/bl_common.c | 142 | ||||
-rw-r--r-- | common/fdt_fixup.c | 212 | ||||
-rw-r--r-- | common/fdt_wrappers.c | 79 |
4 files changed, 359 insertions, 84 deletions
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S index ac47cbe9e..e6e329853 100644 --- a/common/aarch64/debug.S +++ b/common/aarch64/debug.S @@ -11,6 +11,7 @@ .globl asm_print_str .globl asm_print_hex .globl asm_print_hex_bits + .globl asm_print_newline .globl asm_assert .globl do_panic @@ -130,6 +131,15 @@ asm_print_hex_bits: ret x3 endfunc asm_print_hex +/* + * Helper function to print newline to console + * Clobber: x0 + */ +func asm_print_newline + mov x0, '\n' + b plat_crash_console_putc +endfunc asm_print_newline + /*********************************************************** * The common implementation of do_panic for all BL stages ***********************************************************/ diff --git a/common/bl_common.c b/common/bl_common.c index a09cd7171..b74225b13 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -143,26 +143,45 @@ exit: return io_result; } -static int load_auth_image_internal(unsigned int image_id, +/* + * Load an image and flush it out to main memory so that it can be executed + * later by any CPU, regardless of cache and MMU state. + */ +static int load_image_flush(unsigned int image_id, + image_info_t *image_data) +{ + int rc; + + rc = load_image(image_id, image_data); + if (rc == 0) { + flush_dcache_range(image_data->image_base, + image_data->image_size); + } + + return rc; +} + + +#if TRUSTED_BOARD_BOOT +/* + * This function uses recursion to authenticate the parent images up to the root + * of trust. + */ +static int load_auth_image_recursive(unsigned int image_id, image_info_t *image_data, int is_parent_image) { int rc; + unsigned int parent_id; -#if TRUSTED_BOARD_BOOT - if (dyn_is_auth_disabled() == 0) { - unsigned int parent_id; - - /* Use recursion to authenticate parent images */ - rc = auth_mod_get_parent_id(image_id, &parent_id); - if (rc == 0) { - rc = load_auth_image_internal(parent_id, image_data, 1); - if (rc != 0) { - return rc; - } + /* Use recursion to authenticate parent images */ + rc = auth_mod_get_parent_id(image_id, &parent_id); + if (rc == 0) { + rc = load_auth_image_recursive(parent_id, image_data, 1); + if (rc != 0) { + return rc; } } -#endif /* TRUSTED_BOARD_BOOT */ /* Load the image */ rc = load_image(image_id, image_data); @@ -170,51 +189,58 @@ static int load_auth_image_internal(unsigned int image_id, return rc; } -#if TRUSTED_BOARD_BOOT - if (dyn_is_auth_disabled() == 0) { - /* Authenticate it */ - rc = auth_mod_verify_img(image_id, - (void *)image_data->image_base, - image_data->image_size); - if (rc != 0) { - /* Authentication error, zero memory and flush it right away. */ - zero_normalmem((void *)image_data->image_base, + /* Authenticate it */ + rc = auth_mod_verify_img(image_id, + (void *)image_data->image_base, + image_data->image_size); + if (rc != 0) { + /* Authentication error, zero memory and flush it right away. */ + zero_normalmem((void *)image_data->image_base, image_data->image_size); - flush_dcache_range(image_data->image_base, - image_data->image_size); - return -EAUTH; - } + flush_dcache_range(image_data->image_base, + image_data->image_size); + return -EAUTH; } -#endif /* TRUSTED_BOARD_BOOT */ /* * Flush the image to main memory so that it can be executed later by - * any CPU, regardless of cache and MMU state. If TBB is enabled, then - * the file has been successfully loaded and authenticated and flush - * only for child images, not for the parents (certificates). + * any CPU, regardless of cache and MMU state. This is only needed for + * child images, not for the parents (certificates). */ if (is_parent_image == 0) { flush_dcache_range(image_data->image_base, image_data->image_size); } - return 0; } +#endif /* TRUSTED_BOARD_BOOT */ + +static int load_auth_image_internal(unsigned int image_id, + image_info_t *image_data) +{ +#if TRUSTED_BOARD_BOOT + if (dyn_is_auth_disabled() == 0) { + return load_auth_image_recursive(image_id, image_data, 0); + } +#endif + + return load_image_flush(image_id, image_data); +} /******************************************************************************* * Generic function to load and authenticate an image. The image is actually * loaded by calling the 'load_image()' function. Therefore, it returns the * same error codes if the loading operation failed, or -EAUTH if the * authentication failed. In addition, this function uses recursion to - * authenticate the parent images up to the root of trust. + * authenticate the parent images up to the root of trust (if TBB is enabled). ******************************************************************************/ int load_auth_image(unsigned int image_id, image_info_t *image_data) { int err; do { - err = load_auth_image_internal(image_id, image_data, 0); + err = load_auth_image_internal(image_id, image_data); } while ((err != 0) && (plat_try_next_boot_source() != 0)); return err; @@ -244,53 +270,3 @@ void print_entry_point_info(const entry_point_info_t *ep_info) #endif #undef PRINT_IMAGE_ARG } - -#ifdef __aarch64__ -/******************************************************************************* - * Handle all possible cases regarding ARMv8.3-PAuth. - ******************************************************************************/ -void bl_handle_pauth(void) -{ -#if ENABLE_PAUTH - /* - * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1 - * - * Check that the system supports address authentication to avoid - * getting an access fault when accessing the registers. This is all - * that is needed to check. If any of the authentication mechanisms is - * supported, the system knows about ARMv8.3-PAuth, so all the registers - * are available and accessing them won't generate a fault. - * - * Obtain 128-bit instruction key A from the platform and save it to the - * system registers. Pointer authentication can't be enabled here or the - * authentication will fail when returning from this function. - */ - assert(is_armv8_3_pauth_apa_api_present()); - - uint64_t *apiakey = plat_init_apiakey(); - - write_apiakeylo_el1(apiakey[0]); - write_apiakeyhi_el1(apiakey[1]); -#else /* if !ENABLE_PAUTH */ - -# if CTX_INCLUDE_PAUTH_REGS - /* - * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1 - * - * Assert that the ARMv8.3-PAuth registers are present or an access - * fault will be triggered when they are being saved or restored. - */ - assert(is_armv8_3_pauth_present()); -# else - /* - * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0 - * - * Pointer authentication is allowed in the Non-secure world, but - * prohibited in the Secure world. The Trusted Firmware doesn't save the - * registers during a world switch. No check needed. - */ -# endif /* CTX_INCLUDE_PAUTH_REGS */ - -#endif /* ENABLE_PAUTH */ -} -#endif /* __aarch64__ */ diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c new file mode 100644 index 000000000..d518eb2a4 --- /dev/null +++ b/common/fdt_fixup.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains generic routines to fix up the device tree blob passed on to + * payloads like BL32 and BL33 (and further down the boot chain). + * This allows to easily add PSCI nodes, when the original DT does not have + * it or advertises another method. + * Also it supports to add reserved memory nodes to describe memory that + * is used by the secure world, so that non-secure software avoids using + * that. + */ + +#include <string.h> + +#include <libfdt.h> + +#include <common/debug.h> +#include <drivers/console.h> +#include <lib/psci/psci.h> + +#include <common/fdt_fixup.h> + +static int append_psci_compatible(void *fdt, int offs, const char *str) +{ + return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); +} + +/* + * Those defines are for PSCI v0.1 legacy clients, which we expect to use + * the same execution state (AArch32/AArch64) as TF-A. + * Kernels running in AArch32 on an AArch64 TF-A should use PSCI v0.2. + */ +#ifdef __aarch64__ +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH64 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH64 +#else +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH32 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH32 +#endif + +/******************************************************************************* + * dt_add_psci_node() - Add a PSCI node into an existing device tree + * @fdt: pointer to the device tree blob in memory + * + * Add a device tree node describing PSCI into the root level of an existing + * device tree blob in memory. + * This will add v0.1, v0.2 and v1.0 compatible strings and the standard + * function IDs for v0.1 compatibility. + * An existing PSCI node will not be touched, the function will return success + * in this case. This function will not touch the /cpus enable methods, use + * dt_add_psci_cpu_enable_methods() for that. + * + * Return: 0 on success, -1 otherwise. + ******************************************************************************/ +int dt_add_psci_node(void *fdt) +{ + int offs; + + if (fdt_path_offset(fdt, "/psci") >= 0) { + WARN("PSCI Device Tree node already exists!\n"); + return 0; + } + + offs = fdt_path_offset(fdt, "/"); + if (offs < 0) + return -1; + offs = fdt_add_subnode(fdt, offs, "psci"); + if (offs < 0) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-1.0")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-0.2")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci")) + return -1; + if (fdt_setprop_string(fdt, offs, "method", "smc")) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_FNID)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_FNID)) + return -1; + return 0; +} + +/* + * Find the first subnode that has a "device_type" property with the value + * "cpu" and which's enable-method is not "psci" (yet). + * Returns 0 if no such subnode is found, so all have already been patched + * or none have to be patched in the first place. + * Returns 1 if *one* such subnode has been found and successfully changed + * to "psci". + * Returns negative values on error. + * + * Call in a loop until it returns 0. Recalculate the node offset after + * it has returned 1. + */ +static int dt_update_one_cpu_node(void *fdt, int offset) +{ + int offs; + + /* Iterate over all subnodes to find those with device_type = "cpu". */ + for (offs = fdt_first_subnode(fdt, offset); offs >= 0; + offs = fdt_next_subnode(fdt, offs)) { + const char *prop; + int len; + int ret; + + prop = fdt_getprop(fdt, offs, "device_type", &len); + if (prop == NULL) + continue; + if ((strcmp(prop, "cpu") != 0) || (len != 4)) + continue; + + /* Ignore any nodes which already use "psci". */ + prop = fdt_getprop(fdt, offs, "enable-method", &len); + if ((prop != NULL) && + (strcmp(prop, "psci") == 0) && (len == 5)) + continue; + + ret = fdt_setprop_string(fdt, offs, "enable-method", "psci"); + if (ret < 0) + return ret; + /* + * Subnode found and patched. + * Restart to accommodate potentially changed offsets. + */ + return 1; + } + + if (offs == -FDT_ERR_NOTFOUND) + return 0; + + return offs; +} + +/******************************************************************************* + * dt_add_psci_cpu_enable_methods() - switch CPU nodes in DT to use PSCI + * @fdt: pointer to the device tree blob in memory + * + * Iterate over all CPU device tree nodes (/cpus/cpu@x) in memory to change + * the enable-method to PSCI. This will add the enable-method properties, if + * required, or will change existing properties to read "psci". + * + * Return: 0 on success, or a negative error value otherwise. + ******************************************************************************/ + +int dt_add_psci_cpu_enable_methods(void *fdt) +{ + int offs, ret; + + do { + offs = fdt_path_offset(fdt, "/cpus"); + if (offs < 0) + return offs; + + ret = dt_update_one_cpu_node(fdt, offs); + } while (ret > 0); + + return ret; +} + +#define HIGH_BITS(x) ((sizeof(x) > 4) ? ((x) >> 32) : (typeof(x))0) + +/******************************************************************************* + * fdt_add_reserved_memory() - reserve (secure) memory regions in DT + * @dtb: pointer to the device tree blob in memory + * @node_name: name of the subnode to be used + * @base: physical base address of the reserved region + * @size: size of the reserved region + * + * Add a region of memory to the /reserved-memory node in a device tree in + * memory, creating that node if required. Each region goes into a subnode + * of that node and has a @node_name, a @base address and a @size. + * This will prevent any device tree consumer from using that memory. It + * can be used to announce secure memory regions, as it adds the "no-map" + * property to prevent mapping and speculative operations on that region. + * + * See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding + * documentation for details. + * + * Return: 0 on success, a negative error value otherwise. + ******************************************************************************/ +int fdt_add_reserved_memory(void *dtb, const char *node_name, + uintptr_t base, size_t size) +{ + int offs = fdt_path_offset(dtb, "/reserved-memory"); + uint32_t addresses[3]; + + if (offs < 0) { /* create if not existing yet */ + offs = fdt_add_subnode(dtb, 0, "reserved-memory"); + if (offs < 0) + return offs; + fdt_setprop_u32(dtb, offs, "#address-cells", 2); + fdt_setprop_u32(dtb, offs, "#size-cells", 1); + fdt_setprop(dtb, offs, "ranges", NULL, 0); + } + + addresses[0] = cpu_to_fdt32(HIGH_BITS(base)); + addresses[1] = cpu_to_fdt32(base & 0xffffffff); + addresses[2] = cpu_to_fdt32(size & 0xffffffff); + offs = fdt_add_subnode(dtb, offs, node_name); + fdt_setprop(dtb, offs, "no-map", NULL, 0); + fdt_setprop(dtb, offs, "reg", addresses, 12); + + return 0; +} diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c index e67fdb005..ca5b4556d 100644 --- a/common/fdt_wrappers.c +++ b/common/fdt_wrappers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -103,6 +103,41 @@ int fdtw_read_array(const void *dtb, int node, const char *prop, } /* + * Read bytes from a given property of the given node. Any number of + * bytes of the property can be read. The fdt pointer is updated. + * Returns 0 on success, and -1 on error. + */ +int fdtw_read_bytes(const void *dtb, int node, const char *prop, + unsigned int length, void *value) +{ + const void *ptr; + int value_len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), + &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + (void)memcpy(value, ptr, length); + + return 0; +} + +/* * Read string from a given property of the given node. Up to 'size - 1' * characters are read, and a NUL terminator is added. Returns 0 on success, * and -1 upon error. @@ -167,3 +202,45 @@ int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, return 0; } + +/* + * Write bytes in place to a given property of the given node. + * Any number of bytes of the property can be written. + * Returns 0 on success, and < 0 on error. + */ +int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, + unsigned int length, const void *data) +{ + const void *ptr; + int namelen, value_len, err; + + assert(dtb != NULL); + assert(prop != NULL); + assert(data != NULL); + assert(node >= 0); + + namelen = (int)strlen(prop); + + /* Access property and obtain its length in bytes */ + ptr = fdt_getprop_namelen(dtb, node, prop, namelen, &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + /* Set property value in place */ + err = fdt_setprop_inplace_namelen_partial(dtb, node, prop, + namelen, 0, + data, (int)length); + if (err != 0) { + WARN("Set property %s failed with error %d\n", prop, err); + } + + return err; +} |