From cddb08a7a26739b53234fb2865e178a5ec91d385 Mon Sep 17 00:00:00 2001 From: Ben Horgan Date: Wed, 14 Apr 2021 15:39:07 +0000 Subject: [PATCH] arm-trusted-services: Add recipes for arm trusted services Signed-off-by: Ben Horgan Change-Id: I14ac7649ae5899578167efca45d5c19d6248cb8f --- .../trusted-services/crypto-sp_git.bb | 14 + ...nment-to-run-TS-with-a-shim-layer-in.patch | 13960 ++++++++++++++++ ...on-access-permissions-of-shared-memo.patch | 41 + ...on_count-to-0-during-memory-retrieve.patch | 39 + ...buffer-after-memory-retrieve-request.patch | 44 + ...-a-new-deployment-with-the-shim-envi.patch | 364 + ...reate-a-new-deployment-with-the-shim.patch | 268 + ...-t-link-against-unrequired-libraries.patch | 30 + ...ts-arm-linux-Add-version-to-libts.so.patch | 34 + ...ts-Add-option-to-use-installed-libts.patch | 81 + ...ion-to-use-local-source-or-installed.patch | 599 + ...e-stack-to-be-further-than-1MB-from-.patch | 49 + ...d-missing-libc-function-declarations.patch | 93 + ...y-FFA-ABIs-with-supported-convention.patch | 69 + .../trusted-services/libts_git.bb | 41 + .../trusted-services/secure-storage_git.bb | 14 + .../recipes-security/trusted-services/sp.inc | 68 + .../ts-cpputest/cpputest-cmake-fix.patch | 59 + .../trusted-services/ts-cpputest_3.8.bb | 30 + .../trusted-services/ts-demo_git.bb | 42 + .../trusted-services/ts-mbedcrypto_3.1.0.bb | 46 + .../trusted-services/ts-service-test_git.bb | 42 + 22 files changed, 16027 insertions(+) create mode 100644 meta-arm/recipes-security/trusted-services/crypto-sp_git.bb create mode 100644 meta-arm/recipes-security/trusted-services/files/0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0002-Change-instruction-access-permissions-of-shared-memo.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0003-Set-in_region_count-to-0-during-memory-retrieve.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0004-Release-rx-buffer-after-memory-retrieve-request.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0006-secure-storage-Create-a-new-deployment-with-the-shim.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0008-libts-arm-linux-Add-version-to-libts.so.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0009-libts-Add-option-to-use-installed-libts.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0010-external-Add-option-to-use-local-source-or-installed.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0012-libc-Add-missing-libc-function-declarations.patch create mode 100644 meta-arm/recipes-security/trusted-services/files/0013-libsp-modify-FFA-ABIs-with-supported-convention.patch create mode 100644 meta-arm/recipes-security/trusted-services/libts_git.bb create mode 100644 meta-arm/recipes-security/trusted-services/secure-storage_git.bb create mode 100644 meta-arm/recipes-security/trusted-services/sp.inc create mode 100644 meta-arm/recipes-security/trusted-services/ts-cpputest/cpputest-cmake-fix.patch create mode 100644 meta-arm/recipes-security/trusted-services/ts-cpputest_3.8.bb create mode 100644 meta-arm/recipes-security/trusted-services/ts-demo_git.bb create mode 100644 meta-arm/recipes-security/trusted-services/ts-mbedcrypto_3.1.0.bb create mode 100644 meta-arm/recipes-security/trusted-services/ts-service-test_git.bb diff --git a/meta-arm/recipes-security/trusted-services/crypto-sp_git.bb b/meta-arm/recipes-security/trusted-services/crypto-sp_git.bb new file mode 100644 index 00000000..f9ed9292 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/crypto-sp_git.bb @@ -0,0 +1,14 @@ +SUMMARY = "crypto-sp secure partition" + +require sp.inc + +TS_DEPLOYMENT = "${S}/deployments/crypto/shim/" + +do_install () { + install -d -m 755 ${D}/firmware + install -m 0644 "${B}/crypto-sp.bin" "${D}/firmware/crypto-sp.bin" + install -m 0644 "${S}/deployments/crypto/shim/crypto.dts" \ + "${D}/firmware/crypto.dts" +} + +FILES_${PN} = "/firmware/crypto-sp.bin /firmware/crypto.dts" diff --git a/meta-arm/recipes-security/trusted-services/files/0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch b/meta-arm/recipes-security/trusted-services/files/0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch new file mode 100644 index 00000000..053f69d1 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch @@ -0,0 +1,13960 @@ +From 69831e0a5668c7659257b6d812c177adf0801129 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Mon, 8 Mar 2021 19:07:00 +0530 +Subject: [PATCH 01/13] Add a new environment to run TS with a shim layer in + S-EL1 + +To run the trusted services with Hafnium as the Hypervisor executing +at S-EL2, a shim layer that executes at S-EL1 is implemented. The +main purpose of the shim layer is to forward the synchronous exceptions +between Hafnium and Trusted Service. + +The following files in this commit were forked from tf-a-tests, keeping +the original license header intact: + tag name: v2.4 + tagged commit: 272065470e4d1939e59609a932a64955ec965921 + +From 'tftf/framework' of tf-a-tests to + 'environments/shim/framework': + aarch64/asm_debug.S (modified content) + debug.c + +From 'include' of tf-a-tests to + 'environments/shim/include': + common/aarch64/asm_macros.S (modified content) + common/aarch64/assert_macros.S (modified content) + common/asm_macros_common.S (modified content) + common/debug.h + drivers/arm/pl011.h + drivers/console.h + lib/aarch64/arch.h + lib/aarch64/arch_features.h + lib/aarch64/arch_helpers.h + lib/cassert.h + lib/libc/aarch64/endian_.h + lib/libc/aarch64/limits_.h + lib/libc/aarch64/setjmp_.h + lib/libc/aarch64/stddef_.h + lib/libc/aarch64/stdio_.h + lib/libc/cdefs.h + lib/libc/endian.h + lib/libc/errno.h + lib/libc/limits.h + lib/libc/setjmp.h + lib/libc/stdarg.h + lib/libc/assert.h + lib/libc/stdbool.h + lib/libc/stddef.h + lib/libc/stdint.h (modified content) + lib/libc/stdio.h (modified content) + lib/libc/stdlib.h (modified content) + lib/libc/string.h + lib/libc/time.h + lib/libc/uuid.h + lib/mmio.h + lib/spinlock.h + lib/status.h + lib/tftf_lib.h + lib/utils_def.h + lib/xlat_tables/aarch64/xlat_tables_aarch64.h + lib/xlat_tables/xlat_mmu_helpers.h + lib/xlat_tables/xlat_tables_arch.h + lib/xlat_tables/xlat_tables_defs.h + lib/xlat_tables/xlat_tables_v2.h + lib/xlat_tables/xlat_tables_v2_helpers.h + runtime_services/ffa_helpers.h + runtime_services/ffa_svc.h + runtime_services/smccc.h + +From 'plat/arm/tc0/include' of tf-a-tests to + 'environments/shim/include': + platform_def.h (modified content) + +From 'tftf/framework/include' of tf-a-tests to + 'environments/shim/include': + tftf.h (modified content) + +From 'lib/aarch64' of tf-a-tests to + 'environments/shim/lib/aarch64': + cache_helpers.S (modified content) + misc_helpers.S (modified content) + +From 'lib/libc' of tf-a-tests to + 'environments/shim/lib/libc': + assert.c + memcmp.c + memcpy.c + memmove.c + memset.c + printf.c + putchar.c + rand.c + snprintf.c (modified content) + strcmp.c + strlen.c + +From 'lib/locks' of tf-a-tests to + 'environments/shim/lib/locks': + aarch64/spinlock.S (modified content) + +From 'lib/smc' of tf-a-tests to + 'environments/shim/lib/smc': + aarch64/asm_smc.S (modified content) + aarch64/hvc.c + +From 'lib/utils' of tf-a-tests to + 'environments/shim/lib/utils': + mp_printf.c + +From 'lib/xlat_tables_v2' of tf-a-tests to + 'environments/shim/lib/xlat_tables_v2': + aarch64/enable_mmu.S (modified content) + aarch64/xlat_tables_arch.c + xlat_tables_context.c + xlat_tables_core.c + xlat_tables_private.h + xlat_tables_utils.c + +From 'drivers/arm/pl011/aarch64' of tf-a-tests to + 'environments/shim/pl011/aarch64/': + pl011_console.S (modified content) + +From 'plat/arm/tc0/aarch64' of tf-a-tests to + 'environments/shim/plat': + plat_helpers.S + +From 'spm/common' of tf-a-tests to + 'environments/shim/spm/common': + aarch64/sp_arch_helpers.S (modified content) + sp_helpers.c + sp_helpers.h + +The following files in this commit were forked from optee_os, keeping +the original license header intact: + branch name: psa-development + tagged commit: ac7f4110cee21afd7124791b41a4ca28cac119f5 + +From 'lib/libc/' of optee_os to + 'environments/shim/lib/libc': + bget_malloc.c + +From 'lib/libutils/ext/include' of optee_os to + 'environments/shim/include/common': + asm.S + +From 'lib/libutils/ext/include' of optee_os to + 'environments/shim/include/lib/libc': + compiler.h (modified content) + util.h + +From 'lib/libutils/isoc/include' of optee_os to + 'environments/shim/include/lib/libc': + inttypes.h + malloc.h (modified content) + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: Id1c8ffb9464eb29a97a354eedc23603115980791 +Signed-off-by: Ben Horgan +Signed-off-by: Davidson K +Signed-off-by: Olivier Deprez +Signed-off-by: Ruari Phipps +--- + environments/shim/.gitignore | 9 + + environments/shim/aarch64/sp_entrypoint.S | 31 + + .../shim/aarch64/spm_shim_entrypoint.S | 86 ++ + .../shim/aarch64/spm_shim_exceptions.S | 127 ++ + environments/shim/component.cmake | 97 ++ + .../shim/default_toolchain_file.cmake | 20 + + environments/shim/env.cmake | 23 + + .../shim/framework/aarch64/asm_debug.S | 120 ++ + environments/shim/framework/debug.c | 24 + + .../shim/include/common/aarch64/asm_macros.S | 218 +++ + .../include/common/aarch64/assert_macros.S | 31 + + environments/shim/include/common/asm.S | 46 + + .../shim/include/common/asm_macros_common.S | 72 + + environments/shim/include/common/debug.h | 89 ++ + environments/shim/include/common/trace.h | 15 + + environments/shim/include/drivers/arm/pl011.h | 87 ++ + environments/shim/include/drivers/console.h | 56 + + environments/shim/include/lib/aarch64/arch.h | 955 +++++++++++++ + .../shim/include/lib/aarch64/arch_features.h | 95 ++ + .../shim/include/lib/aarch64/arch_helpers.h | 526 +++++++ + environments/shim/include/lib/cassert.h | 18 + + .../shim/include/lib/libc/aarch64/endian_.h | 128 ++ + .../shim/include/lib/libc/aarch64/limits_.h | 26 + + .../shim/include/lib/libc/aarch64/setjmp_.h | 30 + + .../shim/include/lib/libc/aarch64/stddef_.h | 15 + + .../shim/include/lib/libc/aarch64/stdio_.h | 15 + + environments/shim/include/lib/libc/assert.h | 28 + + environments/shim/include/lib/libc/cdefs.h | 33 + + environments/shim/include/lib/libc/compiler.h | 32 + + environments/shim/include/lib/libc/endian.h | 191 +++ + environments/shim/include/lib/libc/errno.h | 169 +++ + environments/shim/include/lib/libc/inttypes.h | 54 + + environments/shim/include/lib/libc/limits.h | 19 + + environments/shim/include/lib/libc/malloc.h | 131 ++ + environments/shim/include/lib/libc/setjmp.h | 20 + + environments/shim/include/lib/libc/stdarg.h | 20 + + environments/shim/include/lib/libc/stdbool.h | 17 + + environments/shim/include/lib/libc/stddef.h | 27 + + environments/shim/include/lib/libc/stdint.h | 148 ++ + environments/shim/include/lib/libc/stdio.h | 33 + + environments/shim/include/lib/libc/stdlib.h | 34 + + environments/shim/include/lib/libc/string.h | 30 + + environments/shim/include/lib/libc/time.h | 18 + + environments/shim/include/lib/libc/util.h | 165 +++ + environments/shim/include/lib/libc/uuid.h | 56 + + environments/shim/include/lib/mmio.h | 42 + + environments/shim/include/lib/spinlock.h | 18 + + environments/shim/include/lib/status.h | 28 + + environments/shim/include/lib/tftf_lib.h | 236 ++++ + environments/shim/include/lib/utils_def.h | 165 +++ + .../xlat_tables/aarch64/xlat_tables_aarch64.h | 96 ++ + .../lib/xlat_tables/xlat_mmu_helpers.h | 91 ++ + .../lib/xlat_tables/xlat_tables_arch.h | 31 + + .../lib/xlat_tables/xlat_tables_defs.h | 182 +++ + .../include/lib/xlat_tables/xlat_tables_v2.h | 367 +++++ + .../lib/xlat_tables/xlat_tables_v2_helpers.h | 163 +++ + environments/shim/include/platform_def.h | 150 ++ + .../include/runtime_services/ffa_helpers.h | 399 ++++++ + .../shim/include/runtime_services/ffa_svc.h | 140 ++ + .../shim/include/runtime_services/smccc.h | 80 ++ + environments/shim/include/shim_sp.h | 47 + + environments/shim/include/tftf.h | 174 +++ + environments/shim/lib/aarch64/cache_helpers.S | 210 +++ + environments/shim/lib/aarch64/misc_helpers.S | 226 +++ + environments/shim/lib/libc/assert.c | 17 + + environments/shim/lib/libc/bget_malloc.c | 951 +++++++++++++ + environments/shim/lib/libc/memcmp.c | 24 + + environments/shim/lib/libc/memcpy.c | 18 + + environments/shim/lib/libc/memmove.c | 31 + + environments/shim/lib/libc/memset.c | 17 + + environments/shim/lib/libc/printf.c | 251 ++++ + environments/shim/lib/libc/putchar.c | 20 + + environments/shim/lib/libc/rand.c | 65 + + environments/shim/lib/libc/snprintf.c | 250 ++++ + environments/shim/lib/libc/strcmp.c | 52 + + environments/shim/lib/libc/strlen.c | 17 + + environments/shim/lib/libc/strstr.c | 25 + + .../shim/lib/locks/aarch64/spinlock.S | 34 + + environments/shim/lib/smc/aarch64/asm_smc.S | 76 + + environments/shim/lib/smc/aarch64/hvc.c | 30 + + environments/shim/lib/utils/mp_printf.c | 24 + + .../lib/xlat_tables_v2/aarch64/enable_mmu.S | 98 ++ + .../xlat_tables_v2/aarch64/xlat_tables_arch.c | 295 ++++ + .../lib/xlat_tables_v2/xlat_tables_context.c | 181 +++ + .../lib/xlat_tables_v2/xlat_tables_core.c | 1226 +++++++++++++++++ + .../lib/xlat_tables_v2/xlat_tables_private.h | 108 ++ + .../lib/xlat_tables_v2/xlat_tables_utils.c | 573 ++++++++ + .../shim/pl011/aarch64/pl011_console.S | 246 ++++ + environments/shim/plat/plat_helpers.S | 90 ++ + environments/shim/shim_main.c | 119 ++ + environments/shim/sp.ld.S | 120 ++ + .../shim/spm/common/aarch64/sp_arch_helpers.S | 42 + + environments/shim/spm/common/sp_debug.c | 68 + + environments/shim/spm/common/sp_debug.h | 13 + + environments/shim/spm/common/sp_helpers.c | 97 ++ + environments/shim/spm/common/sp_helpers.h | 76 + + external/bget/bget.cmake | 52 + + external/bget/bget.patch | 675 +++++++++ + 98 files changed, 13010 insertions(+) + create mode 100644 environments/shim/.gitignore + create mode 100644 environments/shim/aarch64/sp_entrypoint.S + create mode 100644 environments/shim/aarch64/spm_shim_entrypoint.S + create mode 100644 environments/shim/aarch64/spm_shim_exceptions.S + create mode 100644 environments/shim/component.cmake + create mode 100644 environments/shim/default_toolchain_file.cmake + create mode 100644 environments/shim/env.cmake + create mode 100644 environments/shim/framework/aarch64/asm_debug.S + create mode 100644 environments/shim/framework/debug.c + create mode 100644 environments/shim/include/common/aarch64/asm_macros.S + create mode 100644 environments/shim/include/common/aarch64/assert_macros.S + create mode 100644 environments/shim/include/common/asm.S + create mode 100644 environments/shim/include/common/asm_macros_common.S + create mode 100644 environments/shim/include/common/debug.h + create mode 100644 environments/shim/include/common/trace.h + create mode 100644 environments/shim/include/drivers/arm/pl011.h + create mode 100644 environments/shim/include/drivers/console.h + create mode 100644 environments/shim/include/lib/aarch64/arch.h + create mode 100644 environments/shim/include/lib/aarch64/arch_features.h + create mode 100644 environments/shim/include/lib/aarch64/arch_helpers.h + create mode 100644 environments/shim/include/lib/cassert.h + create mode 100644 environments/shim/include/lib/libc/aarch64/endian_.h + create mode 100644 environments/shim/include/lib/libc/aarch64/limits_.h + create mode 100644 environments/shim/include/lib/libc/aarch64/setjmp_.h + create mode 100644 environments/shim/include/lib/libc/aarch64/stddef_.h + create mode 100644 environments/shim/include/lib/libc/aarch64/stdio_.h + create mode 100644 environments/shim/include/lib/libc/assert.h + create mode 100644 environments/shim/include/lib/libc/cdefs.h + create mode 100644 environments/shim/include/lib/libc/compiler.h + create mode 100644 environments/shim/include/lib/libc/endian.h + create mode 100644 environments/shim/include/lib/libc/errno.h + create mode 100644 environments/shim/include/lib/libc/inttypes.h + create mode 100644 environments/shim/include/lib/libc/limits.h + create mode 100644 environments/shim/include/lib/libc/malloc.h + create mode 100644 environments/shim/include/lib/libc/setjmp.h + create mode 100644 environments/shim/include/lib/libc/stdarg.h + create mode 100644 environments/shim/include/lib/libc/stdbool.h + create mode 100644 environments/shim/include/lib/libc/stddef.h + create mode 100644 environments/shim/include/lib/libc/stdint.h + create mode 100644 environments/shim/include/lib/libc/stdio.h + create mode 100644 environments/shim/include/lib/libc/stdlib.h + create mode 100644 environments/shim/include/lib/libc/string.h + create mode 100644 environments/shim/include/lib/libc/time.h + create mode 100644 environments/shim/include/lib/libc/util.h + create mode 100644 environments/shim/include/lib/libc/uuid.h + create mode 100644 environments/shim/include/lib/mmio.h + create mode 100644 environments/shim/include/lib/spinlock.h + create mode 100644 environments/shim/include/lib/status.h + create mode 100644 environments/shim/include/lib/tftf_lib.h + create mode 100644 environments/shim/include/lib/utils_def.h + create mode 100644 environments/shim/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h + create mode 100644 environments/shim/include/lib/xlat_tables/xlat_mmu_helpers.h + create mode 100644 environments/shim/include/lib/xlat_tables/xlat_tables_arch.h + create mode 100644 environments/shim/include/lib/xlat_tables/xlat_tables_defs.h + create mode 100644 environments/shim/include/lib/xlat_tables/xlat_tables_v2.h + create mode 100644 environments/shim/include/lib/xlat_tables/xlat_tables_v2_helpers.h + create mode 100644 environments/shim/include/platform_def.h + create mode 100644 environments/shim/include/runtime_services/ffa_helpers.h + create mode 100644 environments/shim/include/runtime_services/ffa_svc.h + create mode 100644 environments/shim/include/runtime_services/smccc.h + create mode 100644 environments/shim/include/shim_sp.h + create mode 100644 environments/shim/include/tftf.h + create mode 100644 environments/shim/lib/aarch64/cache_helpers.S + create mode 100644 environments/shim/lib/aarch64/misc_helpers.S + create mode 100644 environments/shim/lib/libc/assert.c + create mode 100644 environments/shim/lib/libc/bget_malloc.c + create mode 100644 environments/shim/lib/libc/memcmp.c + create mode 100644 environments/shim/lib/libc/memcpy.c + create mode 100644 environments/shim/lib/libc/memmove.c + create mode 100644 environments/shim/lib/libc/memset.c + create mode 100644 environments/shim/lib/libc/printf.c + create mode 100644 environments/shim/lib/libc/putchar.c + create mode 100644 environments/shim/lib/libc/rand.c + create mode 100644 environments/shim/lib/libc/snprintf.c + create mode 100644 environments/shim/lib/libc/strcmp.c + create mode 100644 environments/shim/lib/libc/strlen.c + create mode 100644 environments/shim/lib/libc/strstr.c + create mode 100644 environments/shim/lib/locks/aarch64/spinlock.S + create mode 100644 environments/shim/lib/smc/aarch64/asm_smc.S + create mode 100644 environments/shim/lib/smc/aarch64/hvc.c + create mode 100644 environments/shim/lib/utils/mp_printf.c + create mode 100644 environments/shim/lib/xlat_tables_v2/aarch64/enable_mmu.S + create mode 100644 environments/shim/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c + create mode 100644 environments/shim/lib/xlat_tables_v2/xlat_tables_context.c + create mode 100644 environments/shim/lib/xlat_tables_v2/xlat_tables_core.c + create mode 100644 environments/shim/lib/xlat_tables_v2/xlat_tables_private.h + create mode 100644 environments/shim/lib/xlat_tables_v2/xlat_tables_utils.c + create mode 100644 environments/shim/pl011/aarch64/pl011_console.S + create mode 100644 environments/shim/plat/plat_helpers.S + create mode 100644 environments/shim/shim_main.c + create mode 100644 environments/shim/sp.ld.S + create mode 100644 environments/shim/spm/common/aarch64/sp_arch_helpers.S + create mode 100644 environments/shim/spm/common/sp_debug.c + create mode 100644 environments/shim/spm/common/sp_debug.h + create mode 100644 environments/shim/spm/common/sp_helpers.c + create mode 100644 environments/shim/spm/common/sp_helpers.h + create mode 100644 external/bget/bget.cmake + create mode 100644 external/bget/bget.patch + +diff --git a/environments/shim/.gitignore b/environments/shim/.gitignore +new file mode 100644 +index 0000000..ca5ed3a +--- /dev/null ++++ b/environments/shim/.gitignore +@@ -0,0 +1,9 @@ ++# ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++ ++# Ignore bget files. These are downloaded from the net ++include/lib/libc/bget.h ++lib/libc/bget.c +diff --git a/environments/shim/aarch64/sp_entrypoint.S b/environments/shim/aarch64/sp_entrypoint.S +new file mode 100644 +index 0000000..8ef330b +--- /dev/null ++++ b/environments/shim/aarch64/sp_entrypoint.S +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++ ++ .globl sp_entrypoint ++ ++.section .bss.stacks ++ .balign CACHE_WRITEBACK_GRANULE ++ .fill SP_STACKS_SIZE ++stacks_end: ++ ++func sp_entrypoint ++ ++ /* Setup the stack pointer. */ ++ adr x0, stacks_end ++ mov sp, x0 ++ /* Mask FIQs */ ++ msr daifset, #DAIF_FIQ_BIT ++ isb ++ ++ /* And jump to the C entrypoint. */ ++ b sp_main ++ ++endfunc sp_entrypoint +diff --git a/environments/shim/aarch64/spm_shim_entrypoint.S b/environments/shim/aarch64/spm_shim_entrypoint.S +new file mode 100644 +index 0000000..53222be +--- /dev/null ++++ b/environments/shim/aarch64/spm_shim_entrypoint.S +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++ ++ .globl shim_entrypoint ++ ++.section .bss.shim_stacks ++ .balign CACHE_WRITEBACK_GRANULE ++ .fill SP_STACKS_SIZE ++shim_stacks_end: ++ ++func shim_entrypoint ++ ++ /* Setup the stack pointer. */ ++ adr x0, shim_stacks_end ++ mov sp, x0 ++ ++ /* Setup vector base address */ ++ adr x0, spm_shim_exceptions_ptr ++ msr vbar_el1, x0 ++ isb ++ ++ /* Enable I-Cache */ ++ /* Enable setting DAIF from S-EL0 */ ++ mrs x0, sctlr_el1 ++ orr x0, x0, #SCTLR_I_BIT ++ orr x0, x0, #SCTLR_UMA_BIT ++ msr sctlr_el1, x0 ++ isb ++ ++ /* Relocate symbols */ ++#shim_pie_fixup: ++# ldr x0, =shim_pie_fixup ++# and x0, x0, #~(0x1000 - 1) ++# mov x1, #SP_IMAGE_SIZE ++# add x1, x1, x0 ++# bl fixup_gdt_reloc ++ ++ /* Clear S-EL1 shim BSS */ ++ adrp x0, __SHIM_BSS_START__ ++ adrp x2, __SHIM_BSS_END__ ++ sub x2, x2, x0 ++ mov x1, xzr ++ bl memset ++ ++ /* Clear S-EL0 partition BSS */ ++ adrp x0, __BSS_START__ ++ adrp x2, __BSS_END__ ++ sub x2, x2, x0 ++ mov x1, xzr ++ bl memset ++ ++ /* And jump to the C entrypoint. */ ++ bl shim_main ++ ++ cbz x0, 1f ++ ++0: mov x0, #0x60 ++ movk x0, #0x8400, lsl #16 ++ mov x1, xzr ++ mov x2, xzr ++ mov x3, xzr ++ smc #0 ++ b 0b ++ ++ /* Exception return to S-EL0 TS application code */ ++1: adrp x0, sp_entrypoint ++ msr elr_el1, x0 ++ ++ /* AArch64 EL0t */ ++ mov x0, xzr ++ msr spsr_el1, x0 ++ ++ /* TODO: clear GP/SIMD registers */ ++ /* TODO: tune EL0 system registers */ ++ ++ eret ++ ++endfunc shim_entrypoint +diff --git a/environments/shim/aarch64/spm_shim_exceptions.S b/environments/shim/aarch64/spm_shim_exceptions.S +new file mode 100644 +index 0000000..7eca49b +--- /dev/null ++++ b/environments/shim/aarch64/spm_shim_exceptions.S +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++ ++/* ----------------------------------------------------------------------------- ++ * Very simple stackless exception handlers used by the spm shim layer. ++ * ----------------------------------------------------------------------------- ++ */ ++ .globl spm_shim_exceptions_ptr ++ ++vector_base spm_shim_exceptions_ptr ++ ++ /* ----------------------------------------------------- ++ * Current EL with SP0 : 0x0 - 0x200 ++ * ----------------------------------------------------- ++ */ ++vector_entry SynchronousExceptionSP0 ++ b . ++end_vector_entry SynchronousExceptionSP0 ++ ++vector_entry IrqSP0 ++ b . ++end_vector_entry IrqSP0 ++ ++vector_entry FiqSP0 ++ b . ++end_vector_entry FiqSP0 ++ ++vector_entry SErrorSP0 ++ b . ++end_vector_entry SErrorSP0 ++ ++ /* ----------------------------------------------------- ++ * Current EL with SPx: 0x200 - 0x400 ++ * ----------------------------------------------------- ++ */ ++vector_entry SynchronousExceptionSPx ++ b . ++end_vector_entry SynchronousExceptionSPx ++ ++vector_entry IrqSPx ++ b . ++end_vector_entry IrqSPx ++ ++vector_entry FiqSPx ++ b . ++end_vector_entry FiqSPx ++ ++vector_entry SErrorSPx ++ b . ++end_vector_entry SErrorSPx ++ ++ /* ----------------------------------------------------- ++ * Lower EL using AArch64 : 0x400 - 0x600. No exceptions ++ * are handled since secure_partition does not implement ++ * a lower EL ++ * ----------------------------------------------------- ++ */ ++vector_entry SynchronousExceptionA64 ++ msr tpidr_el1, x30 ++ mrs x30, esr_el1 ++ ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH ++ ++ cmp x30, #EC_AARCH64_SVC ++ b.eq do_smc ++ ++ cmp x30, #EC_AARCH32_SVC ++ b.eq do_smc ++ ++ cmp x30, #EC_AARCH64_SYS ++ b.eq handle_sys_trap ++ ++ /* Fail in all the other cases */ ++ b panic ++ ++ /* --------------------------------------------- ++ * Tell SPM that we are done initialising ++ * --------------------------------------------- ++ */ ++do_smc: ++ mrs x30, tpidr_el1 ++ smc #0 ++ eret ++ ++ /* AArch64 system instructions trap are handled as a panic for now */ ++handle_sys_trap: ++panic: ++ b panic ++end_vector_entry SynchronousExceptionA64 ++ ++vector_entry IrqA64 ++ b . ++end_vector_entry IrqA64 ++ ++vector_entry FiqA64 ++ b . ++end_vector_entry FiqA64 ++ ++vector_entry SErrorA64 ++ b . ++end_vector_entry SErrorA64 ++ ++ /* ----------------------------------------------------- ++ * Lower EL using AArch32 : 0x600 - 0x800 ++ * ----------------------------------------------------- ++ */ ++vector_entry SynchronousExceptionA32 ++ b . ++end_vector_entry SynchronousExceptionA32 ++ ++vector_entry IrqA32 ++ b . ++end_vector_entry IrqA32 ++ ++vector_entry FiqA32 ++ b . ++end_vector_entry FiqA32 ++ ++vector_entry SErrorA32 ++ b . ++end_vector_entry SErrorA32 +diff --git a/environments/shim/component.cmake b/environments/shim/component.cmake +new file mode 100644 +index 0000000..faa445d +--- /dev/null ++++ b/environments/shim/component.cmake +@@ -0,0 +1,97 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++ ++if (NOT DEFINED TGT) ++ message(FATAL_ERROR "mandatory parameter TGT is not defined.") ++endif() ++ ++include(${TS_ROOT}/external/bget/bget.cmake) ++ ++target_sources(${TGT} PRIVATE ++ "${CMAKE_CURRENT_LIST_DIR}/aarch64/spm_shim_entrypoint.S" ++ "${CMAKE_CURRENT_LIST_DIR}/aarch64/spm_shim_exceptions.S" ++ "${CMAKE_CURRENT_LIST_DIR}/aarch64/sp_entrypoint.S" ++ "${CMAKE_CURRENT_LIST_DIR}/framework/aarch64/asm_debug.S" ++ "${CMAKE_CURRENT_LIST_DIR}/framework/debug.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/aarch64/cache_helpers.S" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/aarch64/misc_helpers.S" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/assert.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/bget_malloc.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/memcmp.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/memcpy.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/memmove.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/memset.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/printf.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/putchar.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/rand.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/snprintf.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/strcmp.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/strlen.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/libc/strstr.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/locks/aarch64/spinlock.S" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/smc/aarch64/asm_smc.S" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/smc/aarch64/hvc.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/utils/mp_printf.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2/aarch64/enable_mmu.S" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2/xlat_tables_context.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2/xlat_tables_core.c" ++ "${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2/xlat_tables_utils.c" ++ "${CMAKE_CURRENT_LIST_DIR}/pl011/aarch64/pl011_console.S" ++ "${CMAKE_CURRENT_LIST_DIR}/plat/plat_helpers.S" ++ "${CMAKE_CURRENT_LIST_DIR}/spm/common/aarch64/sp_arch_helpers.S" ++ "${CMAKE_CURRENT_LIST_DIR}/spm/common/sp_debug.c" ++ "${CMAKE_CURRENT_LIST_DIR}/spm/common/sp_helpers.c" ++ "${CMAKE_CURRENT_LIST_DIR}/shim_main.c" ++ ) ++ ++set(SHIM_HEADER_FILES ++ ${CMAKE_CURRENT_LIST_DIR} ++ ${CMAKE_CURRENT_LIST_DIR}/include ++ ${CMAKE_CURRENT_LIST_DIR}/include/common ++ ${CMAKE_CURRENT_LIST_DIR}/include/common/aarch64 ++ ${CMAKE_CURRENT_LIST_DIR}/include/drivers ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib/aarch64 ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib/libc ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib/libc/aarch64 ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib/xlat_tables ++ ${CMAKE_CURRENT_LIST_DIR}/include/lib/xlat_tables/aarch64 ++ ${CMAKE_CURRENT_LIST_DIR}/include/runtime_services ++ ${CMAKE_CURRENT_LIST_DIR}/spm/common ++ ${CMAKE_CURRENT_LIST_DIR}/lib/xlat_tables_v2 ++) ++ ++target_include_directories(${TGT} PRIVATE ${SHIM_HEADER_FILES}) ++ ++if(TARGET secure-storage) ++ set(SHIM_DEFINES ++ SECURE_STORAGE=1 ++ __ASSEMBLY__=1 ++ ) ++ set(LD_OUTPUT ++ ${CMAKE_BINARY_DIR}/secure-storage.ld ++ ) ++elseif(TARGET crypto-sp) ++ set(SHIM_DEFINES ++ CRYPTO=1 ++ __ASSEMBLY__=1 ++ ) ++ set(LD_OUTPUT ++ ${CMAKE_BINARY_DIR}/crypto-sp.ld ++ ) ++endif() ++ ++compiler_preprocess_file( ++ SRC ${CMAKE_CURRENT_LIST_DIR}/sp.ld.S ++ DST ${LD_OUTPUT} ++ DEFINES ${SHIM_DEFINES} ++ INCLUDES ${SHIM_HEADER_FILES} ++) ++ ++add_custom_target(${TGT}-pplscript DEPENDS ${LD_OUTPUT}) ++add_dependencies(${TGT} ${TGT}-pplscript) +diff --git a/environments/shim/default_toolchain_file.cmake b/environments/shim/default_toolchain_file.cmake +new file mode 100644 +index 0000000..be0d686 +--- /dev/null ++++ b/environments/shim/default_toolchain_file.cmake +@@ -0,0 +1,20 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++ ++#GNUARM v8 and v9 compilers use a different triplet. ++if(NOT DEFINED ENV{CROSS_COMPILE}) ++ set(CROSS_COMPILE "aarch64-none-linux-gnu-;aarch64-linux-gnu-" CACHE STRING "List of GCC prefix triplets to use.") ++endif() ++ ++set(CMAKE_CROSSCOMPILING True) ++set(CMAKE_SYSTEM_NAME Generic) ++set(CMAKE_SYSTEM_PROCESSOR arm) ++set(CMAKE_POSITION_INDEPENDENT_CODE True) ++ ++set(CMAKE_C_FLAGS_INIT "-nostdinc -I$ENV{TS_ROOT}/environments/shim/include/lib/libc -I$ENV{TS_ROOT}/environments/shim/include/lib/libc/aarch64") ++ ++include($ENV{TS_ROOT}/tools/cmake/compiler/GCC.cmake REQUIRED) +diff --git a/environments/shim/env.cmake b/environments/shim/env.cmake +new file mode 100644 +index 0000000..1bdab88 +--- /dev/null ++++ b/environments/shim/env.cmake +@@ -0,0 +1,23 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++ ++#------------------------------------------------------------------------------- ++# Environment file for deployments to Hafnium. This is a cross-compiled ++# enviroment where built executables run within secure partitions ++# with hafnium acting as the secure partition manager. ++#------------------------------------------------------------------------------- ++set(TS_ENV "shim" CACHE STRING "Environment identifier") ++ ++# Default to using the base toolcahin file for the enviroment ++set(TS_BASE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/default_toolchain_file.cmake" CACHE STRING "Base toolchainfile") ++ ++# Replicate in environment variable for access from child cmake contexts ++set(ENV{TS_BASE_TOOLCHAIN_FILE} "${TS_BASE_TOOLCHAIN_FILE}") ++ ++# Set toolchain files to use ++set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/default_toolchain_file.cmake" CACHE STRING "Toolchain file") ++set(TS_EXTERNAL_LIB_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE STRING "External lib Toolchain file") +diff --git a/environments/shim/framework/aarch64/asm_debug.S b/environments/shim/framework/aarch64/asm_debug.S +new file mode 100644 +index 0000000..bada3f5 +--- /dev/null ++++ b/environments/shim/framework/aarch64/asm_debug.S +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++ ++#if ENABLE_ASSERTIONS ++ ++ .globl asm_assert ++ ++/* Since the max decimal input number is 65536 */ ++#define MAX_DEC_DIVISOR 10000 ++/* The offset to add to get ascii for numerals '0 - 9' */ ++#define ASCII_OFFSET_NUM 0x30 ++ ++.section .rodata.assert_str, "aS" ++assert_msg1: ++ .asciz "ASSERT: File " ++assert_msg2: ++ .asciz " Line " ++ ++ /* ++ * This macro is intended to be used to print the ++ * line number in decimal. Used by asm_assert macro. ++ * The max number expected is 65536. ++ * In: x4 = the decimal to print. ++ * Clobber: x30, x0, x1, x2, x5, x6 ++ */ ++ .macro asm_print_line_dec ++ mov x6, #10 /* Divide by 10 after every loop iteration */ ++ mov x5, #MAX_DEC_DIVISOR ++dec_print_loop: ++ udiv x0, x4, x5 /* Get the quotient */ ++ msub x4, x0, x5, x4 /* Find the remainder */ ++ add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ ++ bl plat_crash_console_putc ++ udiv x5, x5, x6 /* Reduce divisor */ ++ cbnz x5, dec_print_loop ++ .endm ++ ++/* --------------------------------------------------------------------------- ++ * Assertion support in assembly. ++ * The below function helps to support assertions in assembly where we do not ++ * have a C runtime stack. Arguments to the function are : ++ * x0 - File name ++ * x1 - Line no ++ * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6. ++ * --------------------------------------------------------------------------- ++ */ ++func asm_assert ++ mov x5, x0 ++ mov x6, x1 ++ /* Ensure the console is initialized */ ++ bl plat_crash_console_init ++ /* Check if the console is initialized */ ++ cbz x0, _assert_loop ++ /* The console is initialized */ ++ adr x4, assert_msg1 ++ bl asm_print_str ++ mov x4, x5 ++ bl asm_print_str ++ adr x4, assert_msg2 ++ bl asm_print_str ++ /* Check if line number higher than max permitted */ ++ tst x6, #~0xffff ++ b.ne _assert_loop ++ mov x4, x6 ++ asm_print_line_dec ++ bl plat_crash_console_flush ++_assert_loop: ++ wfi ++ b _assert_loop ++endfunc asm_assert ++ ++/* ++ * This function prints a string from address in x4. ++ * In: x4 = pointer to string. ++ * Clobber: x30, x0, x1, x2, x3 ++ */ ++func asm_print_str ++ mov x3, x30 ++1: ++ ldrb w0, [x4], #0x1 ++ cbz x0, 2f ++ bl plat_crash_console_putc ++ b 1b ++2: ++ ret x3 ++endfunc asm_print_str ++ ++/* ++ * This function prints a hexadecimal number in x4. ++ * In: x4 = the hexadecimal to print. ++ * Clobber: x30, x0 - x3, x5 ++ */ ++func asm_print_hex ++ mov x3, x30 ++ mov x5, #64 /* No of bits to convert to ascii */ ++1: ++ sub x5, x5, #4 ++ lsrv x0, x4, x5 ++ and x0, x0, #0xf ++ cmp x0, #0xA ++ b.lo 2f ++ /* Add by 0x27 in addition to ASCII_OFFSET_NUM ++ * to get ascii for characters 'a - f'. ++ */ ++ add x0, x0, #0x27 ++2: ++ add x0, x0, #ASCII_OFFSET_NUM ++ bl plat_crash_console_putc ++ cbnz x5, 1b ++ ret x3 ++endfunc asm_print_hex ++ ++#endif /* ENABLE_ASSERTIONS */ +diff --git a/environments/shim/framework/debug.c b/environments/shim/framework/debug.c +new file mode 100644 +index 0000000..66fc03b +--- /dev/null ++++ b/environments/shim/framework/debug.c +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++void __attribute__((__noreturn__)) do_panic(const char *file, int line) ++{ ++ printf("PANIC in file: %s line: %d\n", file, line); ++ ++ console_flush(); ++ ++ while (1) ++ continue; ++} ++ ++void __attribute__((__noreturn__)) do_bug_unreachable(const char *file, int line) ++{ ++ mp_printf("BUG: Unreachable code!\n"); ++ do_panic(file, line); ++} +diff --git a/environments/shim/include/common/aarch64/asm_macros.S b/environments/shim/include/common/aarch64/asm_macros.S +new file mode 100644 +index 0000000..3921d80 +--- /dev/null ++++ b/environments/shim/include/common/aarch64/asm_macros.S +@@ -0,0 +1,218 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#ifndef __ASM_MACROS_S__ ++#define __ASM_MACROS_S__ ++ ++#include ++#include ++ ++#define TLB_INVALIDATE(_type) \ ++ tlbi _type ++ ++ .macro func_prologue ++ stp x29, x30, [sp, #-0x10]! ++ mov x29,sp ++ .endm ++ ++ .macro func_epilogue ++ ldp x29, x30, [sp], #0x10 ++ .endm ++ ++ ++ .macro dcache_line_size reg, tmp ++ mrs \tmp, ctr_el0 ++ ubfx \tmp, \tmp, #16, #4 ++ mov \reg, #4 ++ lsl \reg, \reg, \tmp ++ .endm ++ ++ ++ .macro icache_line_size reg, tmp ++ mrs \tmp, ctr_el0 ++ and \tmp, \tmp, #0xf ++ mov \reg, #4 ++ lsl \reg, \reg, \tmp ++ .endm ++ ++ /* ++ * Declare the exception vector table, enforcing it is aligned on a ++ * 2KB boundary, as required by the ARMv8 architecture. ++ * Use zero bytes as the fill value to be stored in the padding bytes ++ * so that it inserts illegal AArch64 instructions. This increases ++ * security, robustness and potentially facilitates debugging. ++ */ ++ .macro vector_base label ++ .section .vectors, "ax" ++ .align 11, 0 ++ \label: ++ .endm ++ ++ /* ++ * Create an entry in the exception vector table, enforcing it is ++ * aligned on a 128-byte boundary, as required by the ARMv8 ++ * architecture. Use zero bytes as the fill value to be stored in the ++ * padding bytes so that it inserts illegal AArch64 instructions. ++ * This increases security, robustness and potentially facilitates ++ * debugging. ++ */ ++ .macro vector_entry label ++ .section .vectors, "ax" ++ .cfi_sections .debug_frame ++ .align 7, 0 ++ .type \label, %function ++ .cfi_startproc ++ \label: ++ .endm ++ ++ /* ++ * Add the bytes until fill the full exception vector, whose size is always ++ * 32 instructions. If there are more than 32 instructions in the ++ * exception vector then an error is emitted. ++ */ ++ .macro end_vector_entry label ++ .cfi_endproc ++ .fill \label + (32 * 4) - . ++ .endm ++ ++ /* ++ * This macro calculates the base address of an MP stack using the ++ * platform_get_core_pos() index, the name of the stack storage and ++ * the size of each stack ++ * Out: X0 = physical address of stack base ++ * Clobber: X30, X1, X2 ++ */ ++ .macro get_mp_stack _name, _size ++ bl platform_get_core_pos ++ ldr x2, =(\_name + \_size) ++ mov x1, #\_size ++ madd x0, x0, x1, x2 ++ .endm ++ ++ /* ++ * This macro calculates the base address of a UP stack using the ++ * name of the stack storage and the size of the stack ++ * Out: X0 = physical address of stack base ++ */ ++ .macro get_up_stack _name, _size ++ ldr x0, =(\_name + \_size) ++ .endm ++ ++ /* ++ * Helper macro to generate the best mov/movk combinations according ++ * the value to be moved. The 16 bits from '_shift' are tested and ++ * if not zero, they are moved into '_reg' without affecting ++ * other bits. ++ */ ++ .macro _mov_imm16 _reg, _val, _shift ++ .if (\_val >> \_shift) & 0xffff ++ .if (\_val & (1 << \_shift - 1)) ++ movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift ++ .else ++ mov \_reg, \_val & (0xffff << \_shift) ++ .endif ++ .endif ++ .endm ++ ++ /* ++ * Helper macro to load arbitrary values into 32 or 64-bit registers ++ * which generates the best mov/movk combinations. Many base addresses ++ * are 64KB aligned the macro will eliminate updating bits 15:0 in ++ * that case ++ */ ++ .macro mov_imm _reg, _val ++ .if (\_val) == 0 ++ mov \_reg, #0 ++ .else ++ _mov_imm16 \_reg, (\_val), 0 ++ _mov_imm16 \_reg, (\_val), 16 ++ _mov_imm16 \_reg, (\_val), 32 ++ _mov_imm16 \_reg, (\_val), 48 ++ .endif ++ .endm ++ ++ .macro asm_read_sysreg_el1_or_el2 sysreg ++ mrs x0, CurrentEL ++ cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) ++ b.eq 1f ++ cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) ++ b.eq 2f ++ b dead ++1: ++ mrs x0, \sysreg\()_el1 ++ b 3f ++2: ++ mrs x0, \sysreg\()_el2 ++3: ++ .endm ++ ++ .macro asm_write_sysreg_el1_or_el2 sysreg scratch_reg ++ mrs \scratch_reg, CurrentEL ++ cmp \scratch_reg, #(MODE_EL1 << MODE_EL_SHIFT) ++ b.eq 1f ++ cmp \scratch_reg, #(MODE_EL2 << MODE_EL_SHIFT) ++ b.eq 2f ++ b dead ++1: ++ msr \sysreg\()_el1, x0 ++ b 3f ++2: ++ msr \sysreg\()_el2, x0 ++3: ++ .endm ++ ++ .macro asm_read_sctlr_el1_or_el2 ++ asm_read_sysreg_el1_or_el2 sctlr ++ .endm ++ ++ .macro asm_write_sctlr_el1_or_el2 scratch_reg ++ asm_write_sysreg_el1_or_el2 sctlr \scratch_reg ++ .endm ++ ++ .macro asm_write_vbar_el1_or_el2 scratch_reg ++ asm_write_sysreg_el1_or_el2 vbar \scratch_reg ++ .endm ++ ++/* ++ * Depending on the current exception level, jump to 'label_el1' or 'label_el2'. ++ * If the current exception level is neither EL1 nor EL2, jump to 'label_error' ++ * instead. ++ * The caller needs to provide the macro with a scratch 64-bit register to use. ++ * Its contents prior to calling this function will be lost. ++ */ ++ .macro JUMP_EL1_OR_EL2 scratch_reg, label_el1, label_el2, label_error ++ mrs \scratch_reg, CurrentEL ++ cmp \scratch_reg, #(MODE_EL1 << MODE_EL_SHIFT) ++ b.eq \label_el1 ++ cmp \scratch_reg, #(MODE_EL2 << MODE_EL_SHIFT) ++ b.eq \label_el2 ++ b \label_error ++ .endm ++ ++ /* ++ * Helper macro to read system register value into x0 ++ */ ++ .macro read reg:req ++#if ENABLE_BTI ++ bti j ++#endif ++ mrs x0, \reg ++ ret ++ .endm ++ ++ /* ++ * Helper macro to write value from x1 to system register ++ */ ++ .macro write reg:req ++#if ENABLE_BTI ++ bti j ++#endif ++ msr \reg, x1 ++ ret ++ .endm ++ ++#endif /* __ASM_MACROS_S__ */ +diff --git a/environments/shim/include/common/aarch64/assert_macros.S b/environments/shim/include/common/aarch64/assert_macros.S +new file mode 100644 +index 0000000..af1949d +--- /dev/null ++++ b/environments/shim/include/common/aarch64/assert_macros.S +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#ifndef __ASSERT_MACROS_S__ ++#define __ASSERT_MACROS_S__ ++ ++ /* ++ * Assembler macro to enable asm_assert. Use this macro wherever ++ * assert is required in assembly. Please note that the macro makes ++ * use of label '300' to provide the logic and the caller ++ * should make sure that this label is not used to branch prior ++ * to calling this macro. ++ */ ++#define ASM_ASSERT(_cc) \ ++.ifndef .L_assert_filename ;\ ++ .pushsection .rodata.str1.1, "aS" ;\ ++ .L_assert_filename: ;\ ++ .string __FILE__ ;\ ++ .popsection ;\ ++.endif ;\ ++ b._cc 300f ;\ ++ adr x0, .L_assert_filename ;\ ++ mov x1, __LINE__ ;\ ++ b asm_assert ;\ ++300: ++ ++#endif /* __ASSERT_MACROS_S__ */ +diff --git a/environments/shim/include/common/asm.S b/environments/shim/include/common/asm.S +new file mode 100644 +index 0000000..d3cecc3 +--- /dev/null ++++ b/environments/shim/include/common/asm.S +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ */ ++ ++ .macro FUNC name colon section=default ++ .ifc \section\(),default ++ .section .text.\name ++ .else ++ .section \section , "ax" , %progbits ++ .endif ++ .global \name ++ .type \name , %function ++ .balign 4 ++ \name \colon ++ .endm ++ ++ .macro DATA name colon ++ .global \name ++ .type \name , %object ++ \name \colon ++ .endm ++ ++ .macro LOCAL_FUNC name colon section=default ++ .ifc \section\(),default ++ .section .text.\name ++ .else ++ .section \section , "ax" , %progbits ++ .endif ++ .type \name , %function ++ .balign 4 ++ \name \colon ++ .endm ++ ++ .macro LOCAL_DATA name colon ++ .type \name , %object ++ \name \colon ++ .endm ++ ++ .macro END_DATA name ++ .size \name , .-\name ++ .endm ++ ++ .macro END_FUNC name ++ .size \name , .-\name ++ .endm +diff --git a/environments/shim/include/common/asm_macros_common.S b/environments/shim/include/common/asm_macros_common.S +new file mode 100644 +index 0000000..0047897 +--- /dev/null ++++ b/environments/shim/include/common/asm_macros_common.S +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#ifndef __ASM_MACROS_COMMON_S__ ++#define __ASM_MACROS_COMMON_S__ ++ ++#include ++ ++#if ENABLE_BTI && !ARM_ARCH_AT_LEAST(8, 5) ++#error Branch Target Identification requires ARM_ARCH_MINOR >= 5 ++#endif ++ ++ /* ++ * This macro is used to create a function label and place the ++ * code into a separate text section based on the function name ++ * to enable elimination of unused code during linking. It also adds ++ * basic debug information to enable call stack printing most of the ++ * time. ++ */ ++ .macro func _name ++ /* ++ * Add Call Frame Information entry in the .debug_frame section for ++ * debugger consumption. This enables callstack printing in debuggers. ++ * This does not use any space in the final loaded binary, only in the ++ * ELF file. ++ * Note that a function manipulating the CFA pointer location (i.e. the ++ * x29 frame pointer on AArch64) should declare it using the ++ * appropriate .cfi* directives, or be prepared to have a degraded ++ * debugging experience. ++ */ ++ .cfi_sections .debug_frame ++ .section .text.\_name, "ax" ++ .type \_name, %function ++ .func \_name ++ /* ++ * .cfi_startproc and .cfi_endproc are needed to output entries in ++ * .debug_frame ++ */ ++ .cfi_startproc ++ \_name: ++ .endm ++ ++ /* ++ * This macro is used to mark the end of a function. ++ */ ++ .macro endfunc _name ++ .endfunc ++ .cfi_endproc ++ .size \_name, . - \_name ++ .endm ++ ++ /* ++ * This macro declares an array of 1 or more stacks, properly ++ * aligned and in the requested section ++ */ ++#define STACK_ALIGN 6 ++ ++ .macro declare_stack _name, _section, _size, _count ++ .if ((\_size & ((1 << STACK_ALIGN) - 1)) <> 0) ++ .error "Stack size not correctly aligned" ++ .endif ++ .section \_section, "aw", %nobits ++ .align STACK_ALIGN ++ \_name: ++ .space ((\_count) * (\_size)), 0 ++ .endm ++ ++#endif /* __ASM_MACROS_COMMON_S__ */ +diff --git a/environments/shim/include/common/debug.h b/environments/shim/include/common/debug.h +new file mode 100644 +index 0000000..4b30175 +--- /dev/null ++++ b/environments/shim/include/common/debug.h +@@ -0,0 +1,89 @@ ++/* ++ * Copyright (c) 2014-2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __DEBUG_H__ ++#define __DEBUG_H__ ++ ++#include ++ ++#ifdef IMAGE_CACTUS_MM ++/* Remove dependency on spinlocks for Cactus-MM */ ++#define mp_printf printf ++#else ++/* ++ * Print a formatted string on the UART. ++ * ++ * Does the same thing as the standard libc's printf() function but in a MP-safe ++ * manner, i.e. it can be called from several CPUs simultaneously without ++ * getting interleaved messages. ++ */ ++__attribute__((format(printf, 1, 2))) ++void mp_printf(const char *fmt, ...); ++#endif /* IMAGE_CACTUS_MM */ ++ ++/* ++ * The log output macros print output to the console. These macros produce ++ * compiled log output only if the LOG_LEVEL defined in the makefile (or the ++ * make command line) is greater or equal than the level required for that ++ * type of log output. ++ * The format expected is similar to printf(). For example: ++ * INFO("Info %s.\n", "message") -> INFO: Info message. ++ * WARN("Warning %s.\n", "message") -> WARNING: Warning message. ++ */ ++#define LOG_LEVEL_NONE 0 ++#define LOG_LEVEL_ERROR 10 ++#define LOG_LEVEL_NOTICE 20 ++#define LOG_LEVEL_WARNING 30 ++#define LOG_LEVEL_INFO 40 ++#define LOG_LEVEL_VERBOSE 50 ++ ++#if LOG_LEVEL >= LOG_LEVEL_NOTICE ++# define NOTICE(...) mp_printf("NOTICE: " __VA_ARGS__) ++#else ++# define NOTICE(...) ++#endif ++ ++#if LOG_LEVEL >= LOG_LEVEL_ERROR ++# define ERROR(...) mp_printf("ERROR: " __VA_ARGS__) ++#else ++# define ERROR(...) ++#endif ++ ++#if LOG_LEVEL >= LOG_LEVEL_WARNING ++# define WARN(...) mp_printf("WARNING: " __VA_ARGS__) ++#else ++# define WARN(...) ++#endif ++ ++#if LOG_LEVEL >= LOG_LEVEL_INFO ++# define INFO(...) mp_printf("INFO: " __VA_ARGS__) ++#else ++# define INFO(...) ++#endif ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++# define VERBOSE(...) mp_printf("VERBOSE: " __VA_ARGS__) ++#else ++# define VERBOSE(...) ++#endif ++ ++#if ENABLE_BACKTRACE ++void backtrace(const char *cookie); ++#else ++#define backtrace(x) ++#endif ++ ++/* ++ * For the moment this panic function is very basic: report an error and ++ * spin. This can be expanded in the future to provide more information. ++ */ ++void __attribute__((__noreturn__)) do_panic(const char *file, int line); ++#define panic() do_panic(__FILE__, __LINE__) ++ ++void __attribute__((__noreturn__)) do_bug_unreachable(const char *file, int line); ++#define bug_unreachable() do_bug_unreachable(__FILE__, __LINE__) ++ ++#endif /* __DEBUG_H__ */ +diff --git a/environments/shim/include/common/trace.h b/environments/shim/include/common/trace.h +new file mode 100644 +index 0000000..aece27e +--- /dev/null ++++ b/environments/shim/include/common/trace.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __TRACE_H__ ++#define __TRACE_H__ ++ ++#include ++ ++#define EMSG(...) mp_printf("ERROR: " __VA_ARGS__) ++#define DMSG(...) mp_printf("NOTICE: " __VA_ARGS__) ++ ++#endif /* __DEBUG_H__ */ +diff --git a/environments/shim/include/drivers/arm/pl011.h b/environments/shim/include/drivers/arm/pl011.h +new file mode 100644 +index 0000000..3e19ee8 +--- /dev/null ++++ b/environments/shim/include/drivers/arm/pl011.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __PL011_H__ ++#define __PL011_H__ ++ ++/* PL011 Registers */ ++#define UARTDR 0x000 ++#define UARTRSR 0x004 ++#define UARTECR 0x004 ++#define UARTFR 0x018 ++#define UARTILPR 0x020 ++#define UARTIBRD 0x024 ++#define UARTFBRD 0x028 ++#define UARTLCR_H 0x02C ++#define UARTCR 0x030 ++#define UARTIFLS 0x034 ++#define UARTIMSC 0x038 ++#define UARTRIS 0x03C ++#define UARTMIS 0x040 ++#define UARTICR 0x044 ++#define UARTDMACR 0x048 ++ ++/* Data status bits */ ++#define UART_DATA_ERROR_MASK 0x0F00 ++ ++/* Status reg bits */ ++#define UART_STATUS_ERROR_MASK 0x0F ++ ++/* Flag reg bits */ ++#define PL011_UARTFR_RI (1 << 8) /* Ring indicator */ ++#define PL011_UARTFR_TXFE (1 << 7) /* Transmit FIFO empty */ ++#define PL011_UARTFR_RXFF (1 << 6) /* Receive FIFO full */ ++#define PL011_UARTFR_TXFF (1 << 5) /* Transmit FIFO full */ ++#define PL011_UARTFR_RXFE (1 << 4) /* Receive FIFO empty */ ++#define PL011_UARTFR_BUSY (1 << 3) /* UART busy */ ++#define PL011_UARTFR_DCD (1 << 2) /* Data carrier detect */ ++#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */ ++#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */ ++ ++#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ ++#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ ++#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */ ++ ++/* Control reg bits */ ++#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */ ++#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */ ++#define PL011_UARTCR_RTS (1 << 11) /* Request to send */ ++#define PL011_UARTCR_DTR (1 << 10) /* Data transmit ready. */ ++#define PL011_UARTCR_RXE (1 << 9) /* Receive enable */ ++#define PL011_UARTCR_TXE (1 << 8) /* Transmit enable */ ++#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */ ++#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */ ++ ++#if !defined(PL011_LINE_CONTROL) ++/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */ ++#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8) ++#endif ++ ++/* Line Control Register Bits */ ++#define PL011_UARTLCR_H_SPS (1 << 7) /* Stick parity select */ ++#define PL011_UARTLCR_H_WLEN_8 (3 << 5) ++#define PL011_UARTLCR_H_WLEN_7 (2 << 5) ++#define PL011_UARTLCR_H_WLEN_6 (1 << 5) ++#define PL011_UARTLCR_H_WLEN_5 (0 << 5) ++#define PL011_UARTLCR_H_FEN (1 << 4) /* FIFOs Enable */ ++#define PL011_UARTLCR_H_STP2 (1 << 3) /* Two stop bits select */ ++#define PL011_UARTLCR_H_EPS (1 << 2) /* Even parity select */ ++#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */ ++#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */ ++ ++/* Constants */ ++#define PL011_BAUDRATE 115200 ++ ++#ifndef __ASSEMBLER__ ++#include ++ ++/* Functions */ ++ ++int console_pl011_putc(int); ++ ++#endif /* __ASSEMBLER__ */ ++ ++#endif /* __PL011_H__ */ +diff --git a/environments/shim/include/drivers/console.h b/environments/shim/include/drivers/console.h +new file mode 100644 +index 0000000..4c22a99 +--- /dev/null ++++ b/environments/shim/include/drivers/console.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2018-2019, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __CONSOLE_H__ ++#define __CONSOLE_H__ ++ ++/* Returned by getc callbacks when receive FIFO is empty. */ ++#define ERROR_NO_PENDING_CHAR -1 ++/* Returned by console_xxx() if the registered console doesn't implement xxx. */ ++#define ERROR_NO_VALID_CONSOLE (-128) ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++ ++/* ++ * Function to initialize the console without a C Runtime to print debug ++ * information. It saves the console base to the data section. Returns 1 on ++ * success, 0 on error. ++ */ ++int console_init(uintptr_t base_addr, ++ unsigned int uart_clk, unsigned int baud_rate); ++ ++/* ++ * Function to output a character over the console. It returns the character ++ * printed on success or an error code. ++ */ ++int console_putc(int c); ++ ++/* ++ * Function to get a character from the console. It returns the character ++ * grabbed on success or an error code on error. This function is blocking, it ++ * waits until there is an available character to return. Returns a character or ++ * error code. ++ */ ++int console_getc(void); ++ ++/* ++ * Function to get a character from the console. It returns the character ++ * grabbed on success or an error code on error. This function is non-blocking, ++ * it returns immediately. ++ */ ++int console_try_getc(void); ++ ++/* ++ * Function to force a write of all buffered data that hasn't been output. It ++ * returns 0 upon successful completion, otherwise it returns an error code. ++ */ ++int console_flush(void); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* __CONSOLE_H__ */ +diff --git a/environments/shim/include/lib/aarch64/arch.h b/environments/shim/include/lib/aarch64/arch.h +new file mode 100644 +index 0000000..2d2a892 +--- /dev/null ++++ b/environments/shim/include/lib/aarch64/arch.h +@@ -0,0 +1,955 @@ ++/* ++ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef ARCH_H ++#define ARCH_H ++ ++#include ++ ++/******************************************************************************* ++ * MIDR bit definitions ++ ******************************************************************************/ ++#define MIDR_IMPL_MASK U(0xff) ++#define MIDR_IMPL_SHIFT U(0x18) ++#define MIDR_VAR_SHIFT U(20) ++#define MIDR_VAR_BITS U(4) ++#define MIDR_VAR_MASK U(0xf) ++#define MIDR_REV_SHIFT U(0) ++#define MIDR_REV_BITS U(4) ++#define MIDR_REV_MASK U(0xf) ++#define MIDR_PN_MASK U(0xfff) ++#define MIDR_PN_SHIFT U(0x4) ++ ++/******************************************************************************* ++ * MPIDR macros ++ ******************************************************************************/ ++#define MPIDR_MT_MASK (ULL(1) << 24) ++#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK ++#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) ++#define MPIDR_AFFINITY_BITS U(8) ++#define MPIDR_AFFLVL_MASK ULL(0xff) ++#define MPIDR_AFF0_SHIFT U(0) ++#define MPIDR_AFF1_SHIFT U(8) ++#define MPIDR_AFF2_SHIFT U(16) ++#define MPIDR_AFF3_SHIFT U(32) ++#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT ++#define MPIDR_AFFINITY_MASK ULL(0xff00ffffff) ++#define MPIDR_AFFLVL_SHIFT U(3) ++#define MPIDR_AFFLVL0 ULL(0x0) ++#define MPIDR_AFFLVL1 ULL(0x1) ++#define MPIDR_AFFLVL2 ULL(0x2) ++#define MPIDR_AFFLVL3 ULL(0x3) ++#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n ++#define MPIDR_AFFLVL0_VAL(mpidr) \ ++ (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) ++#define MPIDR_AFFLVL1_VAL(mpidr) \ ++ (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) ++#define MPIDR_AFFLVL2_VAL(mpidr) \ ++ (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) ++#define MPIDR_AFFLVL3_VAL(mpidr) \ ++ (((mpidr) >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK) ++/* ++ * The MPIDR_MAX_AFFLVL count starts from 0. Take care to ++ * add one while using this macro to define array sizes. ++ * TODO: Support only the first 3 affinity levels for now. ++ */ ++#define MPIDR_MAX_AFFLVL U(2) ++ ++#define MPID_MASK (MPIDR_MT_MASK | \ ++ (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT) | \ ++ (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) | \ ++ (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) | \ ++ (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) ++ ++#define MPIDR_AFF_ID(mpid, n) \ ++ (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) ++ ++/* ++ * An invalid MPID. This value can be used by functions that return an MPID to ++ * indicate an error. ++ */ ++#define INVALID_MPID U(0xFFFFFFFF) ++ ++/******************************************************************************* ++ * Definitions for CPU system register interface to GICv3 ++ ******************************************************************************/ ++#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 ++#define ICC_SGI1R S3_0_C12_C11_5 ++#define ICC_SRE_EL1 S3_0_C12_C12_5 ++#define ICC_SRE_EL2 S3_4_C12_C9_5 ++#define ICC_SRE_EL3 S3_6_C12_C12_5 ++#define ICC_CTLR_EL1 S3_0_C12_C12_4 ++#define ICC_CTLR_EL3 S3_6_C12_C12_4 ++#define ICC_PMR_EL1 S3_0_C4_C6_0 ++#define ICC_RPR_EL1 S3_0_C12_C11_3 ++#define ICC_IGRPEN1_EL3 S3_6_c12_c12_7 ++#define ICC_IGRPEN0_EL1 S3_0_c12_c12_6 ++#define ICC_HPPIR0_EL1 S3_0_c12_c8_2 ++#define ICC_HPPIR1_EL1 S3_0_c12_c12_2 ++#define ICC_IAR0_EL1 S3_0_c12_c8_0 ++#define ICC_IAR1_EL1 S3_0_c12_c12_0 ++#define ICC_EOIR0_EL1 S3_0_c12_c8_1 ++#define ICC_EOIR1_EL1 S3_0_c12_c12_1 ++#define ICC_SGI0R_EL1 S3_0_c12_c11_7 ++ ++/******************************************************************************* ++ * Generic timer memory mapped registers & offsets ++ ******************************************************************************/ ++#define CNTCR_OFF U(0x000) ++#define CNTFID_OFF U(0x020) ++ ++#define CNTCR_EN (U(1) << 0) ++#define CNTCR_HDBG (U(1) << 1) ++#define CNTCR_FCREQ(x) ((x) << 8) ++ ++/******************************************************************************* ++ * System register bit definitions ++ ******************************************************************************/ ++/* CLIDR definitions */ ++#define LOUIS_SHIFT U(21) ++#define LOC_SHIFT U(24) ++#define CLIDR_FIELD_WIDTH U(3) ++ ++/* CSSELR definitions */ ++#define LEVEL_SHIFT U(1) ++ ++/* Data cache set/way op type defines */ ++#define DCISW U(0x0) ++#define DCCISW U(0x1) ++#define DCCSW U(0x2) ++ ++/* ID_AA64PFR0_EL1 definitions */ ++#define ID_AA64PFR0_EL0_SHIFT U(0) ++#define ID_AA64PFR0_EL1_SHIFT U(4) ++#define ID_AA64PFR0_EL2_SHIFT U(8) ++#define ID_AA64PFR0_EL3_SHIFT U(12) ++#define ID_AA64PFR0_AMU_SHIFT U(44) ++#define ID_AA64PFR0_AMU_LENGTH U(4) ++#define ID_AA64PFR0_AMU_MASK ULL(0xf) ++#define ID_AA64PFR0_ELX_MASK ULL(0xf) ++#define ID_AA64PFR0_SVE_SHIFT U(32) ++#define ID_AA64PFR0_SVE_MASK ULL(0xf) ++#define ID_AA64PFR0_SVE_LENGTH U(4) ++#define ID_AA64PFR0_MPAM_SHIFT U(40) ++#define ID_AA64PFR0_MPAM_MASK ULL(0xf) ++#define ID_AA64PFR0_DIT_SHIFT U(48) ++#define ID_AA64PFR0_DIT_MASK ULL(0xf) ++#define ID_AA64PFR0_DIT_LENGTH U(4) ++#define ID_AA64PFR0_DIT_SUPPORTED U(1) ++#define ID_AA64PFR0_CSV2_SHIFT U(56) ++#define ID_AA64PFR0_CSV2_MASK ULL(0xf) ++#define ID_AA64PFR0_CSV2_LENGTH U(4) ++ ++/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ ++#define ID_AA64DFR0_PMS_SHIFT U(32) ++#define ID_AA64DFR0_PMS_LENGTH U(4) ++#define ID_AA64DFR0_PMS_MASK ULL(0xf) ++ ++/* ID_AA64DFR0_EL1.DEBUG definitions */ ++#define ID_AA64DFR0_DEBUG_SHIFT U(0) ++#define ID_AA64DFR0_DEBUG_LENGTH U(4) ++#define ID_AA64DFR0_DEBUG_MASK ULL(0xf) ++#define ID_AA64DFR0_DEBUG_BITS (ID_AA64DFR0_DEBUG_MASK << \ ++ ID_AA64DFR0_DEBUG_SHIFT) ++#define ID_AA64DFR0_V8_DEBUG_ARCH_SUPPORTED U(6) ++#define ID_AA64DFR0_V8_DEBUG_ARCH_VHE_SUPPORTED U(7) ++#define ID_AA64DFR0_V8_2_DEBUG_ARCH_SUPPORTED U(8) ++#define ID_AA64DFR0_V8_4_DEBUG_ARCH_SUPPORTED U(9) ++ ++#define EL_IMPL_NONE ULL(0) ++#define EL_IMPL_A64ONLY ULL(1) ++#define EL_IMPL_A64_A32 ULL(2) ++ ++#define ID_AA64PFR0_GIC_SHIFT U(24) ++#define ID_AA64PFR0_GIC_WIDTH U(4) ++#define ID_AA64PFR0_GIC_MASK ULL(0xf) ++ ++/* ID_AA64ISAR1_EL1 definitions */ ++#define ID_AA64ISAR1_EL1 S3_0_C0_C6_1 ++#define ID_AA64ISAR1_GPI_SHIFT U(28) ++#define ID_AA64ISAR1_GPI_WIDTH U(4) ++#define ID_AA64ISAR1_GPI_MASK ULL(0xf) ++#define ID_AA64ISAR1_GPA_SHIFT U(24) ++#define ID_AA64ISAR1_GPA_WIDTH U(4) ++#define ID_AA64ISAR1_GPA_MASK ULL(0xf) ++#define ID_AA64ISAR1_API_SHIFT U(8) ++#define ID_AA64ISAR1_API_WIDTH U(4) ++#define ID_AA64ISAR1_API_MASK ULL(0xf) ++#define ID_AA64ISAR1_APA_SHIFT U(4) ++#define ID_AA64ISAR1_APA_WIDTH U(4) ++#define ID_AA64ISAR1_APA_MASK ULL(0xf) ++ ++/* ID_AA64MMFR0_EL1 definitions */ ++#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) ++#define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf) ++ ++#define PARANGE_0000 U(32) ++#define PARANGE_0001 U(36) ++#define PARANGE_0010 U(40) ++#define PARANGE_0011 U(42) ++#define PARANGE_0100 U(44) ++#define PARANGE_0101 U(48) ++#define PARANGE_0110 U(52) ++ ++#define ID_AA64MMFR0_EL1_ECV_SHIFT U(60) ++#define ID_AA64MMFR0_EL1_ECV_MASK ULL(0xf) ++#define ID_AA64MMFR0_EL1_ECV_NOT_SUPPORTED ULL(0x0) ++#define ID_AA64MMFR0_EL1_ECV_SUPPORTED ULL(0x1) ++#define ID_AA64MMFR0_EL1_ECV_SELF_SYNCH ULL(0x2) ++ ++#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56) ++#define ID_AA64MMFR0_EL1_FGT_MASK ULL(0xf) ++#define ID_AA64MMFR0_EL1_FGT_NOT_SUPPORTED ULL(0x0) ++#define ID_AA64MMFR0_EL1_FGT_SUPPORTED ULL(0x1) ++ ++#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28) ++#define ID_AA64MMFR0_EL1_TGRAN4_MASK ULL(0xf) ++#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED ULL(0x0) ++#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED ULL(0xf) ++ ++#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT U(24) ++#define ID_AA64MMFR0_EL1_TGRAN64_MASK ULL(0xf) ++#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED ULL(0x0) ++#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED ULL(0xf) ++ ++#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20) ++#define ID_AA64MMFR0_EL1_TGRAN16_MASK ULL(0xf) ++#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED ULL(0x1) ++#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED ULL(0x0) ++ ++/* ID_AA64MMFR2_EL1 definitions */ ++#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2 ++ ++#define ID_AA64MMFR2_EL1_ST_SHIFT U(28) ++#define ID_AA64MMFR2_EL1_ST_MASK ULL(0xf) ++ ++#define ID_AA64MMFR2_EL1_CNP_SHIFT U(0) ++#define ID_AA64MMFR2_EL1_CNP_MASK ULL(0xf) ++ ++/* ID_AA64PFR1_EL1 definitions */ ++#define ID_AA64PFR1_EL1_SSBS_SHIFT U(4) ++#define ID_AA64PFR1_EL1_SSBS_MASK ULL(0xf) ++ ++#define SSBS_UNAVAILABLE ULL(0) /* No architectural SSBS support */ ++ ++#define ID_AA64PFR1_EL1_BT_SHIFT U(0) ++#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf) ++ ++#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */ ++ ++#define ID_AA64PFR1_EL1_MTE_SHIFT U(8) ++#define ID_AA64PFR1_EL1_MTE_MASK ULL(0xf) ++ ++#define MTE_UNIMPLEMENTED ULL(0) ++#define MTE_IMPLEMENTED_EL0 ULL(1) /* MTE is only implemented at EL0 */ ++#define MTE_IMPLEMENTED_ELX ULL(2) /* MTE is implemented at all ELs */ ++ ++/* ID_PFR1_EL1 definitions */ ++#define ID_PFR1_VIRTEXT_SHIFT U(12) ++#define ID_PFR1_VIRTEXT_MASK U(0xf) ++#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \ ++ & ID_PFR1_VIRTEXT_MASK) ++ ++/* SCTLR definitions */ ++#define SCTLR_EL2_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ ++ (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ ++ (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) ++ ++#define SCTLR_EL1_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ ++ (U(1) << 22) | (U(1) << 20) | (U(1) << 11)) ++#define SCTLR_AARCH32_EL1_RES1 \ ++ ((U(1) << 23) | (U(1) << 22) | (U(1) << 11) | \ ++ (U(1) << 4) | (U(1) << 3)) ++ ++#define SCTLR_EL3_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ ++ (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ ++ (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) ++ ++#define SCTLR_M_BIT (ULL(1) << 0) ++#define SCTLR_A_BIT (ULL(1) << 1) ++#define SCTLR_C_BIT (ULL(1) << 2) ++#define SCTLR_SA_BIT (ULL(1) << 3) ++#define SCTLR_SA0_BIT (ULL(1) << 4) ++#define SCTLR_CP15BEN_BIT (ULL(1) << 5) ++#define SCTLR_ITD_BIT (ULL(1) << 7) ++#define SCTLR_SED_BIT (ULL(1) << 8) ++#define SCTLR_UMA_BIT (ULL(1) << 9) ++#define SCTLR_I_BIT (ULL(1) << 12) ++#define SCTLR_EnDB_BIT (ULL(1) << 13) ++#define SCTLR_DZE_BIT (ULL(1) << 14) ++#define SCTLR_UCT_BIT (ULL(1) << 15) ++#define SCTLR_NTWI_BIT (ULL(1) << 16) ++#define SCTLR_NTWE_BIT (ULL(1) << 18) ++#define SCTLR_WXN_BIT (ULL(1) << 19) ++#define SCTLR_UWXN_BIT (ULL(1) << 20) ++#define SCTLR_IESB_BIT (ULL(1) << 21) ++#define SCTLR_E0E_BIT (ULL(1) << 24) ++#define SCTLR_EE_BIT (ULL(1) << 25) ++#define SCTLR_UCI_BIT (ULL(1) << 26) ++#define SCTLR_EnDA_BIT (ULL(1) << 27) ++#define SCTLR_EnIB_BIT (ULL(1) << 30) ++#define SCTLR_EnIA_BIT (ULL(1) << 31) ++#define SCTLR_DSSBS_BIT (ULL(1) << 44) ++#define SCTLR_RESET_VAL SCTLR_EL3_RES1 ++ ++/* CPACR_El1 definitions */ ++#define CPACR_EL1_FPEN(x) ((x) << 20) ++#define CPACR_EL1_FP_TRAP_EL0 U(0x1) ++#define CPACR_EL1_FP_TRAP_ALL U(0x2) ++#define CPACR_EL1_FP_TRAP_NONE U(0x3) ++ ++/* SCR definitions */ ++#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5)) ++#define SCR_ATA_BIT (U(1) << 26) ++#define SCR_FIEN_BIT (U(1) << 21) ++#define SCR_API_BIT (U(1) << 17) ++#define SCR_APK_BIT (U(1) << 16) ++#define SCR_TWE_BIT (U(1) << 13) ++#define SCR_TWI_BIT (U(1) << 12) ++#define SCR_ST_BIT (U(1) << 11) ++#define SCR_RW_BIT (U(1) << 10) ++#define SCR_SIF_BIT (U(1) << 9) ++#define SCR_HCE_BIT (U(1) << 8) ++#define SCR_SMD_BIT (U(1) << 7) ++#define SCR_EA_BIT (U(1) << 3) ++#define SCR_FIQ_BIT (U(1) << 2) ++#define SCR_IRQ_BIT (U(1) << 1) ++#define SCR_NS_BIT (U(1) << 0) ++#define SCR_VALID_BIT_MASK U(0x2f8f) ++#define SCR_RESET_VAL SCR_RES1_BITS ++ ++/* MDCR_EL3 definitions */ ++#define MDCR_SPD32(x) ((x) << 14) ++#define MDCR_SPD32_LEGACY ULL(0x0) ++#define MDCR_SPD32_DISABLE ULL(0x2) ++#define MDCR_SPD32_ENABLE ULL(0x3) ++#define MDCR_SDD_BIT (ULL(1) << 16) ++#define MDCR_NSPB(x) ((x) << 12) ++#define MDCR_NSPB_EL1 ULL(0x3) ++#define MDCR_TDOSA_BIT (ULL(1) << 10) ++#define MDCR_TDA_BIT (ULL(1) << 9) ++#define MDCR_TPM_BIT (ULL(1) << 6) ++#define MDCR_SCCD_BIT (ULL(1) << 23) ++#define MDCR_EL3_RESET_VAL ULL(0x0) ++ ++/* MDCR_EL2 definitions */ ++#define MDCR_EL2_TPMS (U(1) << 14) ++#define MDCR_EL2_E2PB(x) ((x) << 12) ++#define MDCR_EL2_E2PB_EL1 U(0x3) ++#define MDCR_EL2_TDRA_BIT (U(1) << 11) ++#define MDCR_EL2_TDOSA_BIT (U(1) << 10) ++#define MDCR_EL2_TDA_BIT (U(1) << 9) ++#define MDCR_EL2_TDE_BIT (U(1) << 8) ++#define MDCR_EL2_HPME_BIT (U(1) << 7) ++#define MDCR_EL2_TPM_BIT (U(1) << 6) ++#define MDCR_EL2_TPMCR_BIT (U(1) << 5) ++#define MDCR_EL2_RESET_VAL U(0x0) ++ ++/* HSTR_EL2 definitions */ ++#define HSTR_EL2_RESET_VAL U(0x0) ++#define HSTR_EL2_T_MASK U(0xff) ++ ++/* CNTHP_CTL_EL2 definitions */ ++#define CNTHP_CTL_ENABLE_BIT (U(1) << 0) ++#define CNTHP_CTL_RESET_VAL U(0x0) ++ ++/* VTTBR_EL2 definitions */ ++#define VTTBR_RESET_VAL ULL(0x0) ++#define VTTBR_VMID_MASK ULL(0xff) ++#define VTTBR_VMID_SHIFT U(48) ++#define VTTBR_BADDR_MASK ULL(0xffffffffffff) ++#define VTTBR_BADDR_SHIFT U(0) ++ ++/* HCR definitions */ ++#define HCR_API_BIT (ULL(1) << 41) ++#define HCR_APK_BIT (ULL(1) << 40) ++#define HCR_TGE_BIT (ULL(1) << 27) ++#define HCR_RW_SHIFT U(31) ++#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT) ++#define HCR_AMO_BIT (ULL(1) << 5) ++#define HCR_IMO_BIT (ULL(1) << 4) ++#define HCR_FMO_BIT (ULL(1) << 3) ++ ++/* ISR definitions */ ++#define ISR_A_SHIFT U(8) ++#define ISR_I_SHIFT U(7) ++#define ISR_F_SHIFT U(6) ++ ++/* CNTHCTL_EL2 definitions */ ++#define CNTHCTL_RESET_VAL U(0x0) ++#define EVNTEN_BIT (U(1) << 2) ++#define EL1PCEN_BIT (U(1) << 1) ++#define EL1PCTEN_BIT (U(1) << 0) ++ ++/* CNTKCTL_EL1 definitions */ ++#define EL0PTEN_BIT (U(1) << 9) ++#define EL0VTEN_BIT (U(1) << 8) ++#define EL0PCTEN_BIT (U(1) << 0) ++#define EL0VCTEN_BIT (U(1) << 1) ++#define EVNTEN_BIT (U(1) << 2) ++#define EVNTDIR_BIT (U(1) << 3) ++#define EVNTI_SHIFT U(4) ++#define EVNTI_MASK U(0xf) ++ ++/* CPTR_EL3 definitions */ ++#define TCPAC_BIT (U(1) << 31) ++#define TAM_BIT (U(1) << 30) ++#define TTA_BIT (U(1) << 20) ++#define TFP_BIT (U(1) << 10) ++#define CPTR_EZ_BIT (U(1) << 8) ++#define CPTR_EL3_RESET_VAL U(0x0) ++ ++/* CPTR_EL2 definitions */ ++#define CPTR_EL2_RES1 ((ULL(3) << 12) | (ULL(1) << 9) | (ULL(0xff))) ++#define CPTR_EL2_TCPAC_BIT (ULL(1) << 31) ++#define CPTR_EL2_TAM_BIT (ULL(1) << 30) ++#define CPTR_EL2_TTA_BIT (ULL(1) << 20) ++#define CPTR_EL2_TFP_BIT (ULL(1) << 10) ++#define CPTR_EL2_TZ_BIT (ULL(1) << 8) ++#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 ++ ++/* CPSR/SPSR definitions */ ++#define DAIF_FIQ_BIT (U(1) << 0) ++#define DAIF_IRQ_BIT (U(1) << 1) ++#define DAIF_ABT_BIT (U(1) << 2) ++#define DAIF_DBG_BIT (U(1) << 3) ++#define SPSR_DAIF_SHIFT U(6) ++#define SPSR_DAIF_MASK U(0xf) ++ ++#define SPSR_AIF_SHIFT U(6) ++#define SPSR_AIF_MASK U(0x7) ++ ++#define SPSR_E_SHIFT U(9) ++#define SPSR_E_MASK U(0x1) ++#define SPSR_E_LITTLE U(0x0) ++#define SPSR_E_BIG U(0x1) ++ ++#define SPSR_T_SHIFT U(5) ++#define SPSR_T_MASK U(0x1) ++#define SPSR_T_ARM U(0x0) ++#define SPSR_T_THUMB U(0x1) ++ ++#define SPSR_M_SHIFT U(4) ++#define SPSR_M_MASK U(0x1) ++#define SPSR_M_AARCH64 U(0x0) ++#define SPSR_M_AARCH32 U(0x1) ++ ++#define DISABLE_ALL_EXCEPTIONS \ ++ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) ++ ++#define DISABLE_INTERRUPTS (DAIF_FIQ_BIT | DAIF_IRQ_BIT) ++ ++/* ++ * RMR_EL3 definitions ++ */ ++#define RMR_EL3_RR_BIT (U(1) << 1) ++#define RMR_EL3_AA64_BIT (U(1) << 0) ++ ++/* ++ * HI-VECTOR address for AArch32 state ++ */ ++#define HI_VECTOR_BASE U(0xFFFF0000) ++ ++/* ++ * TCR defintions ++ */ ++#define TCR_EL3_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) ++#define TCR_EL2_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) ++#define TCR_EL1_IPS_SHIFT U(32) ++#define TCR_EL2_PS_SHIFT U(16) ++#define TCR_EL3_PS_SHIFT U(16) ++ ++#define TCR_TxSZ_MIN ULL(16) ++#define TCR_TxSZ_MAX ULL(39) ++#define TCR_TxSZ_MAX_TTST ULL(48) ++ ++#define TCR_T0SZ_SHIFT U(0) ++#define TCR_T1SZ_SHIFT U(16) ++ ++/* (internal) physical address size bits in EL3/EL1 */ ++#define TCR_PS_BITS_4GB ULL(0x0) ++#define TCR_PS_BITS_64GB ULL(0x1) ++#define TCR_PS_BITS_1TB ULL(0x2) ++#define TCR_PS_BITS_4TB ULL(0x3) ++#define TCR_PS_BITS_16TB ULL(0x4) ++#define TCR_PS_BITS_256TB ULL(0x5) ++ ++#define ADDR_MASK_48_TO_63 ULL(0xFFFF000000000000) ++#define ADDR_MASK_44_TO_47 ULL(0x0000F00000000000) ++#define ADDR_MASK_42_TO_43 ULL(0x00000C0000000000) ++#define ADDR_MASK_40_TO_41 ULL(0x0000030000000000) ++#define ADDR_MASK_36_TO_39 ULL(0x000000F000000000) ++#define ADDR_MASK_32_TO_35 ULL(0x0000000F00000000) ++ ++#define TCR_RGN_INNER_NC (ULL(0x0) << 8) ++#define TCR_RGN_INNER_WBA (ULL(0x1) << 8) ++#define TCR_RGN_INNER_WT (ULL(0x2) << 8) ++#define TCR_RGN_INNER_WBNA (ULL(0x3) << 8) ++ ++#define TCR_RGN_OUTER_NC (ULL(0x0) << 10) ++#define TCR_RGN_OUTER_WBA (ULL(0x1) << 10) ++#define TCR_RGN_OUTER_WT (ULL(0x2) << 10) ++#define TCR_RGN_OUTER_WBNA (ULL(0x3) << 10) ++ ++#define TCR_SH_NON_SHAREABLE (ULL(0x0) << 12) ++#define TCR_SH_OUTER_SHAREABLE (ULL(0x2) << 12) ++#define TCR_SH_INNER_SHAREABLE (ULL(0x3) << 12) ++ ++#define TCR_RGN1_INNER_NC (ULL(0x0) << 24) ++#define TCR_RGN1_INNER_WBA (ULL(0x1) << 24) ++#define TCR_RGN1_INNER_WT (ULL(0x2) << 24) ++#define TCR_RGN1_INNER_WBNA (ULL(0x3) << 24) ++ ++#define TCR_RGN1_OUTER_NC (ULL(0x0) << 26) ++#define TCR_RGN1_OUTER_WBA (ULL(0x1) << 26) ++#define TCR_RGN1_OUTER_WT (ULL(0x2) << 26) ++#define TCR_RGN1_OUTER_WBNA (ULL(0x3) << 26) ++ ++#define TCR_SH1_NON_SHAREABLE (ULL(0x0) << 28) ++#define TCR_SH1_OUTER_SHAREABLE (ULL(0x2) << 28) ++#define TCR_SH1_INNER_SHAREABLE (ULL(0x3) << 28) ++ ++#define TCR_TG0_SHIFT U(14) ++#define TCR_TG0_MASK ULL(3) ++#define TCR_TG0_4K (ULL(0) << TCR_TG0_SHIFT) ++#define TCR_TG0_64K (ULL(1) << TCR_TG0_SHIFT) ++#define TCR_TG0_16K (ULL(2) << TCR_TG0_SHIFT) ++ ++#define TCR_TG1_SHIFT U(30) ++#define TCR_TG1_MASK ULL(3) ++#define TCR_TG1_16K (ULL(1) << TCR_TG1_SHIFT) ++#define TCR_TG1_4K (ULL(2) << TCR_TG1_SHIFT) ++#define TCR_TG1_64K (ULL(3) << TCR_TG1_SHIFT) ++ ++#define TCR_EPD0_BIT (ULL(1) << 7) ++#define TCR_EPD1_BIT (ULL(1) << 23) ++ ++#define MODE_SP_SHIFT U(0x0) ++#define MODE_SP_MASK U(0x1) ++#define MODE_SP_EL0 U(0x0) ++#define MODE_SP_ELX U(0x1) ++ ++#define MODE_RW_SHIFT U(0x4) ++#define MODE_RW_MASK U(0x1) ++#define MODE_RW_64 U(0x0) ++#define MODE_RW_32 U(0x1) ++ ++#define MODE_EL_SHIFT U(0x2) ++#define MODE_EL_MASK U(0x3) ++#define MODE_EL3 U(0x3) ++#define MODE_EL2 U(0x2) ++#define MODE_EL1 U(0x1) ++#define MODE_EL0 U(0x0) ++ ++#define MODE32_SHIFT U(0) ++#define MODE32_MASK U(0xf) ++#define MODE32_usr U(0x0) ++#define MODE32_fiq U(0x1) ++#define MODE32_irq U(0x2) ++#define MODE32_svc U(0x3) ++#define MODE32_mon U(0x6) ++#define MODE32_abt U(0x7) ++#define MODE32_hyp U(0xa) ++#define MODE32_und U(0xb) ++#define MODE32_sys U(0xf) ++ ++#define GET_RW(mode) (((mode) >> MODE_RW_SHIFT) & MODE_RW_MASK) ++#define GET_EL(mode) (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK) ++#define GET_SP(mode) (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK) ++#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) ++ ++#define SPSR_64(el, sp, daif) \ ++ ((MODE_RW_64 << MODE_RW_SHIFT) | \ ++ (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ ++ (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ ++ (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) ++ ++#define SPSR_MODE32(mode, isa, endian, aif) \ ++ ((MODE_RW_32 << MODE_RW_SHIFT) | \ ++ (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ ++ (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ ++ (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ ++ (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) ++ ++/* ++ * TTBR Definitions ++ */ ++#define TTBR_CNP_BIT ULL(0x1) ++ ++/* ++ * CTR_EL0 definitions ++ */ ++#define CTR_CWG_SHIFT U(24) ++#define CTR_CWG_MASK U(0xf) ++#define CTR_ERG_SHIFT U(20) ++#define CTR_ERG_MASK U(0xf) ++#define CTR_DMINLINE_SHIFT U(16) ++#define CTR_DMINLINE_MASK U(0xf) ++#define CTR_L1IP_SHIFT U(14) ++#define CTR_L1IP_MASK U(0x3) ++#define CTR_IMINLINE_SHIFT U(0) ++#define CTR_IMINLINE_MASK U(0xf) ++ ++#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */ ++ ++/* Physical timer control register bit fields shifts and masks */ ++#define CNTP_CTL_ENABLE_SHIFT U(0) ++#define CNTP_CTL_IMASK_SHIFT U(1) ++#define CNTP_CTL_ISTATUS_SHIFT U(2) ++ ++#define CNTP_CTL_ENABLE_MASK U(1) ++#define CNTP_CTL_IMASK_MASK U(1) ++#define CNTP_CTL_ISTATUS_MASK U(1) ++ ++/* Exception Syndrome register bits and bobs */ ++#define ESR_EC_SHIFT U(26) ++#define ESR_EC_MASK U(0x3f) ++#define ESR_EC_LENGTH U(6) ++#define EC_UNKNOWN U(0x0) ++#define EC_WFE_WFI U(0x1) ++#define EC_AARCH32_CP15_MRC_MCR U(0x3) ++#define EC_AARCH32_CP15_MRRC_MCRR U(0x4) ++#define EC_AARCH32_CP14_MRC_MCR U(0x5) ++#define EC_AARCH32_CP14_LDC_STC U(0x6) ++#define EC_FP_SIMD U(0x7) ++#define EC_AARCH32_CP10_MRC U(0x8) ++#define EC_AARCH32_CP14_MRRC_MCRR U(0xc) ++#define EC_ILLEGAL U(0xe) ++#define EC_AARCH32_SVC U(0x11) ++#define EC_AARCH32_HVC U(0x12) ++#define EC_AARCH32_SMC U(0x13) ++#define EC_AARCH64_SVC U(0x15) ++#define EC_AARCH64_HVC U(0x16) ++#define EC_AARCH64_SMC U(0x17) ++#define EC_AARCH64_SYS U(0x18) ++#define EC_IABORT_LOWER_EL U(0x20) ++#define EC_IABORT_CUR_EL U(0x21) ++#define EC_PC_ALIGN U(0x22) ++#define EC_DABORT_LOWER_EL U(0x24) ++#define EC_DABORT_CUR_EL U(0x25) ++#define EC_SP_ALIGN U(0x26) ++#define EC_AARCH32_FP U(0x28) ++#define EC_AARCH64_FP U(0x2c) ++#define EC_SERROR U(0x2f) ++ ++/* ++ * External Abort bit in Instruction and Data Aborts synchronous exception ++ * syndromes. ++ */ ++#define ESR_ISS_EABORT_EA_BIT U(9) ++ ++#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK) ++ ++/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */ ++#define RMR_RESET_REQUEST_SHIFT U(0x1) ++#define RMR_WARM_RESET_CPU (U(1) << RMR_RESET_REQUEST_SHIFT) ++ ++/******************************************************************************* ++ * Definitions of register offsets, fields and macros for CPU system ++ * instructions. ++ ******************************************************************************/ ++ ++#define TLBI_ADDR_SHIFT U(12) ++#define TLBI_ADDR_MASK ULL(0x00000FFFFFFFFFFF) ++#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) ++ ++/******************************************************************************* ++ * Definitions of register offsets and fields in the CNTCTLBase Frame of the ++ * system level implementation of the Generic Timer. ++ ******************************************************************************/ ++#define CNTCTLBASE_CNTFRQ U(0x0) ++#define CNTNSAR U(0x4) ++#define CNTNSAR_NS_SHIFT(x) (x) ++ ++#define CNTACR_BASE(x) (U(0x40) + ((x) << 2)) ++#define CNTACR_RPCT_SHIFT U(0x0) ++#define CNTACR_RVCT_SHIFT U(0x1) ++#define CNTACR_RFRQ_SHIFT U(0x2) ++#define CNTACR_RVOFF_SHIFT U(0x3) ++#define CNTACR_RWVT_SHIFT U(0x4) ++#define CNTACR_RWPT_SHIFT U(0x5) ++ ++/******************************************************************************* ++ * Definitions of register offsets and fields in the CNTBaseN Frame of the ++ * system level implementation of the Generic Timer. ++ ******************************************************************************/ ++/* Physical Count register. */ ++#define CNTPCT_LO U(0x0) ++/* Counter Frequency register. */ ++#define CNTBASEN_CNTFRQ U(0x10) ++/* Physical Timer CompareValue register. */ ++#define CNTP_CVAL_LO U(0x20) ++/* Physical Timer Control register. */ ++#define CNTP_CTL U(0x2c) ++ ++/* PMCR_EL0 definitions */ ++#define PMCR_EL0_RESET_VAL U(0x0) ++#define PMCR_EL0_N_SHIFT U(11) ++#define PMCR_EL0_N_MASK U(0x1f) ++#define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) ++#define PMCR_EL0_LC_BIT (U(1) << 6) ++#define PMCR_EL0_DP_BIT (U(1) << 5) ++#define PMCR_EL0_X_BIT (U(1) << 4) ++#define PMCR_EL0_D_BIT (U(1) << 3) ++#define PMCR_EL0_E_BIT (U(1) << 0) ++ ++/* PMCNTENSET_EL0 definitions */ ++#define PMCNTENSET_EL0_C_BIT (U(1) << 31) ++#define PMCNTENSET_EL0_P_BIT(x) (U(1) << x) ++ ++/* PMEVTYPER_EL0 definitions */ ++#define PMEVTYPER_EL0_P_BIT (U(1) << 31) ++#define PMEVTYPER_EL0_NSK_BIT (U(1) << 29) ++#define PMEVTYPER_EL0_NSH_BIT (U(1) << 27) ++#define PMEVTYPER_EL0_M_BIT (U(1) << 26) ++#define PMEVTYPER_EL0_MT_BIT (U(1) << 25) ++#define PMEVTYPER_EL0_SH_BIT (U(1) << 24) ++#define PMEVTYPER_EL0_EVTCOUNT_BITS U(0x000003FF) ++ ++/* PMCCFILTR_EL0 definitions */ ++#define PMCCFILTR_EL0_P_BIT (U(1) << 31) ++#define PMCCFILTR_EL0_NSK_BIT (U(1) << 29) ++#define PMCCFILTR_EL0_NSH_BIT (U(1) << 27) ++#define PMCCFILTR_EL0_M_BIT (U(1) << 26) ++#define PMCCFILTR_EL0_MT_BIT (U(1) << 25) ++#define PMCCFILTR_EL0_SH_BIT (U(1) << 24) ++ ++/* PMU event counter ID definitions */ ++#define PMU_EV_PC_WRITE_RETIRED U(0x000C) ++ ++/******************************************************************************* ++ * Definitions for system register interface to SVE ++ ******************************************************************************/ ++#define ZCR_EL3 S3_6_C1_C2_0 ++#define ZCR_EL2 S3_4_C1_C2_0 ++ ++/* ZCR_EL3 definitions */ ++#define ZCR_EL3_LEN_MASK U(0xf) ++ ++/* ZCR_EL2 definitions */ ++#define ZCR_EL2_LEN_MASK U(0xf) ++ ++/******************************************************************************* ++ * Definitions of MAIR encodings for device and normal memory ++ ******************************************************************************/ ++/* ++ * MAIR encodings for device memory attributes. ++ */ ++#define MAIR_DEV_nGnRnE ULL(0x0) ++#define MAIR_DEV_nGnRE ULL(0x4) ++#define MAIR_DEV_nGRE ULL(0x8) ++#define MAIR_DEV_GRE ULL(0xc) ++ ++/* ++ * MAIR encodings for normal memory attributes. ++ * ++ * Cache Policy ++ * WT: Write Through ++ * WB: Write Back ++ * NC: Non-Cacheable ++ * ++ * Transient Hint ++ * NTR: Non-Transient ++ * TR: Transient ++ * ++ * Allocation Policy ++ * RA: Read Allocate ++ * WA: Write Allocate ++ * RWA: Read and Write Allocate ++ * NA: No Allocation ++ */ ++#define MAIR_NORM_WT_TR_WA ULL(0x1) ++#define MAIR_NORM_WT_TR_RA ULL(0x2) ++#define MAIR_NORM_WT_TR_RWA ULL(0x3) ++#define MAIR_NORM_NC ULL(0x4) ++#define MAIR_NORM_WB_TR_WA ULL(0x5) ++#define MAIR_NORM_WB_TR_RA ULL(0x6) ++#define MAIR_NORM_WB_TR_RWA ULL(0x7) ++#define MAIR_NORM_WT_NTR_NA ULL(0x8) ++#define MAIR_NORM_WT_NTR_WA ULL(0x9) ++#define MAIR_NORM_WT_NTR_RA ULL(0xa) ++#define MAIR_NORM_WT_NTR_RWA ULL(0xb) ++#define MAIR_NORM_WB_NTR_NA ULL(0xc) ++#define MAIR_NORM_WB_NTR_WA ULL(0xd) ++#define MAIR_NORM_WB_NTR_RA ULL(0xe) ++#define MAIR_NORM_WB_NTR_RWA ULL(0xf) ++ ++#define MAIR_NORM_OUTER_SHIFT U(4) ++ ++#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ ++ ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) ++ ++/* PAR_EL1 fields */ ++#define PAR_F_SHIFT U(0) ++#define PAR_F_MASK ULL(0x1) ++#define PAR_ADDR_SHIFT U(12) ++#define PAR_ADDR_MASK (BIT(40) - ULL(1)) /* 40-bits-wide page address */ ++ ++/******************************************************************************* ++ * Definitions for system register interface to SPE ++ ******************************************************************************/ ++#define PMBLIMITR_EL1 S3_0_C9_C10_0 ++ ++/******************************************************************************* ++ * Definitions for system register interface to MPAM ++ ******************************************************************************/ ++#define MPAMIDR_EL1 S3_0_C10_C4_4 ++#define MPAM2_EL2 S3_4_C10_C5_0 ++#define MPAMHCR_EL2 S3_4_C10_C4_0 ++#define MPAM3_EL3 S3_6_C10_C5_0 ++ ++/******************************************************************************* ++ * Definitions for system register interface to AMU for ARMv8.4 onwards ++ ******************************************************************************/ ++#define AMCR_EL0 S3_3_C13_C2_0 ++#define AMCFGR_EL0 S3_3_C13_C2_1 ++#define AMCGCR_EL0 S3_3_C13_C2_2 ++#define AMUSERENR_EL0 S3_3_C13_C2_3 ++#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 ++#define AMCNTENSET0_EL0 S3_3_C13_C2_5 ++#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 ++#define AMCNTENSET1_EL0 S3_3_C13_C3_1 ++ ++/* Activity Monitor Group 0 Event Counter Registers */ ++#define AMEVCNTR00_EL0 S3_3_C13_C4_0 ++#define AMEVCNTR01_EL0 S3_3_C13_C4_1 ++#define AMEVCNTR02_EL0 S3_3_C13_C4_2 ++#define AMEVCNTR03_EL0 S3_3_C13_C4_3 ++ ++/* Activity Monitor Group 0 Event Type Registers */ ++#define AMEVTYPER00_EL0 S3_3_C13_C6_0 ++#define AMEVTYPER01_EL0 S3_3_C13_C6_1 ++#define AMEVTYPER02_EL0 S3_3_C13_C6_2 ++#define AMEVTYPER03_EL0 S3_3_C13_C6_3 ++ ++/* Activity Monitor Group 1 Event Counter Registers */ ++#define AMEVCNTR10_EL0 S3_3_C13_C12_0 ++#define AMEVCNTR11_EL0 S3_3_C13_C12_1 ++#define AMEVCNTR12_EL0 S3_3_C13_C12_2 ++#define AMEVCNTR13_EL0 S3_3_C13_C12_3 ++#define AMEVCNTR14_EL0 S3_3_C13_C12_4 ++#define AMEVCNTR15_EL0 S3_3_C13_C12_5 ++#define AMEVCNTR16_EL0 S3_3_C13_C12_6 ++#define AMEVCNTR17_EL0 S3_3_C13_C12_7 ++#define AMEVCNTR18_EL0 S3_3_C13_C13_0 ++#define AMEVCNTR19_EL0 S3_3_C13_C13_1 ++#define AMEVCNTR1A_EL0 S3_3_C13_C13_2 ++#define AMEVCNTR1B_EL0 S3_3_C13_C13_3 ++#define AMEVCNTR1C_EL0 S3_3_C13_C13_4 ++#define AMEVCNTR1D_EL0 S3_3_C13_C13_5 ++#define AMEVCNTR1E_EL0 S3_3_C13_C13_6 ++#define AMEVCNTR1F_EL0 S3_3_C13_C13_7 ++ ++/* Activity Monitor Group 1 Event Type Registers */ ++#define AMEVTYPER10_EL0 S3_3_C13_C14_0 ++#define AMEVTYPER11_EL0 S3_3_C13_C14_1 ++#define AMEVTYPER12_EL0 S3_3_C13_C14_2 ++#define AMEVTYPER13_EL0 S3_3_C13_C14_3 ++#define AMEVTYPER14_EL0 S3_3_C13_C14_4 ++#define AMEVTYPER15_EL0 S3_3_C13_C14_5 ++#define AMEVTYPER16_EL0 S3_3_C13_C14_6 ++#define AMEVTYPER17_EL0 S3_3_C13_C14_7 ++#define AMEVTYPER18_EL0 S3_3_C13_C15_0 ++#define AMEVTYPER19_EL0 S3_3_C13_C15_1 ++#define AMEVTYPER1A_EL0 S3_3_C13_C15_2 ++#define AMEVTYPER1B_EL0 S3_3_C13_C15_3 ++#define AMEVTYPER1C_EL0 S3_3_C13_C15_4 ++#define AMEVTYPER1D_EL0 S3_3_C13_C15_5 ++#define AMEVTYPER1E_EL0 S3_3_C13_C15_6 ++#define AMEVTYPER1F_EL0 S3_3_C13_C15_7 ++ ++/* AMCGCR_EL0 definitions */ ++#define AMCGCR_EL0_CG1NC_SHIFT U(8) ++#define AMCGCR_EL0_CG1NC_LENGTH U(8) ++#define AMCGCR_EL0_CG1NC_MASK U(0xff) ++ ++/* MPAM register definitions */ ++#define MPAM3_EL3_MPAMEN_BIT (ULL(1) << 63) ++#define MPAMHCR_EL2_TRAP_MPAMIDR_EL1 (ULL(1) << 31) ++ ++#define MPAM2_EL2_TRAPMPAM0EL1 (ULL(1) << 49) ++#define MPAM2_EL2_TRAPMPAM1EL1 (ULL(1) << 48) ++ ++#define MPAMIDR_HAS_HCR_BIT (ULL(1) << 17) ++ ++/******************************************************************************* ++ * RAS system registers ++ ******************************************************************************/ ++#define DISR_EL1 S3_0_C12_C1_1 ++#define DISR_A_BIT U(31) ++ ++#define ERRIDR_EL1 S3_0_C5_C3_0 ++#define ERRIDR_MASK U(0xffff) ++ ++#define ERRSELR_EL1 S3_0_C5_C3_1 ++ ++/* System register access to Standard Error Record registers */ ++#define ERXFR_EL1 S3_0_C5_C4_0 ++#define ERXCTLR_EL1 S3_0_C5_C4_1 ++#define ERXSTATUS_EL1 S3_0_C5_C4_2 ++#define ERXADDR_EL1 S3_0_C5_C4_3 ++#define ERXPFGF_EL1 S3_0_C5_C4_4 ++#define ERXPFGCTL_EL1 S3_0_C5_C4_5 ++#define ERXPFGCDN_EL1 S3_0_C5_C4_6 ++#define ERXMISC0_EL1 S3_0_C5_C5_0 ++#define ERXMISC1_EL1 S3_0_C5_C5_1 ++ ++#define ERXCTLR_ED_BIT (U(1) << 0) ++#define ERXCTLR_UE_BIT (U(1) << 4) ++ ++#define ERXPFGCTL_UC_BIT (U(1) << 1) ++#define ERXPFGCTL_UEU_BIT (U(1) << 2) ++#define ERXPFGCTL_CDEN_BIT (U(1) << 31) ++ ++/******************************************************************************* ++ * Armv8.3 Pointer Authentication Registers ++ ******************************************************************************/ ++#define APIAKeyLo_EL1 S3_0_C2_C1_0 ++#define APIAKeyHi_EL1 S3_0_C2_C1_1 ++#define APIBKeyLo_EL1 S3_0_C2_C1_2 ++#define APIBKeyHi_EL1 S3_0_C2_C1_3 ++#define APDAKeyLo_EL1 S3_0_C2_C2_0 ++#define APDAKeyHi_EL1 S3_0_C2_C2_1 ++#define APDBKeyLo_EL1 S3_0_C2_C2_2 ++#define APDBKeyHi_EL1 S3_0_C2_C2_3 ++#define APGAKeyLo_EL1 S3_0_C2_C3_0 ++#define APGAKeyHi_EL1 S3_0_C2_C3_1 ++ ++/******************************************************************************* ++ * Armv8.4 Data Independent Timing Registers ++ ******************************************************************************/ ++#define DIT S3_3_C4_C2_5 ++#define DIT_BIT BIT(24) ++ ++/******************************************************************************* ++ * Armv8.5 - new MSR encoding to directly access PSTATE.SSBS field ++ ******************************************************************************/ ++#define SSBS S3_3_C4_C2_6 ++ ++/******************************************************************************* ++ * Armv8.5 - Memory Tagging Extension Registers ++ ******************************************************************************/ ++#define TFSRE0_EL1 S3_0_C5_C6_1 ++#define TFSR_EL1 S3_0_C5_C6_0 ++#define RGSR_EL1 S3_0_C1_C0_5 ++#define GCR_EL1 S3_0_C1_C0_6 ++ ++/******************************************************************************* ++ * Armv8.6 - Fine Grained Virtualization Traps Registers ++ ******************************************************************************/ ++#define HFGRTR_EL2 S3_4_C1_C1_4 ++#define HFGWTR_EL2 S3_4_C1_C1_5 ++#define HFGITR_EL2 S3_4_C1_C1_6 ++#define HDFGRTR_EL2 S3_4_C3_C1_4 ++#define HDFGWTR_EL2 S3_4_C3_C1_5 ++ ++/******************************************************************************* ++ * Armv8.6 - Enhanced Counter Virtualization Registers ++ ******************************************************************************/ ++#define CNTPOFF_EL2 S3_4_C14_C0_6 ++ ++ ++#endif /* ARCH_H */ +diff --git a/environments/shim/include/lib/aarch64/arch_features.h b/environments/shim/include/lib/aarch64/arch_features.h +new file mode 100644 +index 0000000..15eb784 +--- /dev/null ++++ b/environments/shim/include/lib/aarch64/arch_features.h +@@ -0,0 +1,95 @@ ++/* ++ * Copyright (c) 2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef ARCH_FEATURES_H ++#define ARCH_FEATURES_H ++ ++#include ++ ++#include ++ ++static inline bool is_armv7_gentimer_present(void) ++{ ++ /* The Generic Timer is always present in an ARMv8-A implementation */ ++ return true; ++} ++ ++static inline bool is_armv8_2_sve_present(void) ++{ ++ return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) & ++ ID_AA64PFR0_SVE_MASK) == 1U; ++} ++ ++static inline bool is_armv8_2_ttcnp_present(void) ++{ ++ return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) & ++ ID_AA64MMFR2_EL1_CNP_MASK) != 0U; ++} ++ ++static inline bool is_armv8_3_pauth_present(void) ++{ ++ uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | ++ (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) | ++ (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | ++ (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); ++ ++ /* If any of the fields is not zero, PAuth is present */ ++ return (read_id_aa64isar1_el1() & mask) != 0U; ++} ++ ++static inline bool is_armv8_3_pauth_apa_api_present(void) ++{ ++ uint64_t mask = (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | ++ (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); ++ ++ return (read_id_aa64isar1_el1() & mask) != 0U; ++} ++ ++static inline bool is_armv8_3_pauth_gpa_gpi_present(void) ++{ ++ uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | ++ (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT); ++ ++ return (read_id_aa64isar1_el1() & mask) != 0U; ++} ++ ++static inline bool is_armv8_4_ttst_present(void) ++{ ++ return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & ++ ID_AA64MMFR2_EL1_ST_MASK) == 1U; ++} ++ ++static inline bool is_armv8_5_bti_present(void) ++{ ++ return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) & ++ ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED; ++} ++ ++static inline unsigned int get_armv8_5_mte_support(void) ++{ ++ return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & ++ ID_AA64PFR1_EL1_MTE_MASK); ++} ++ ++static inline bool is_armv8_6_fgt_present(void) ++{ ++ return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) & ++ ID_AA64MMFR0_EL1_FGT_MASK) == ID_AA64MMFR0_EL1_FGT_SUPPORTED; ++} ++ ++static inline unsigned long int get_armv8_6_ecv_support(void) ++{ ++ return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) & ++ ID_AA64MMFR0_EL1_ECV_MASK); ++} ++ ++static inline uint32_t arch_get_debug_version(void) ++{ ++ return ((read_id_aa64dfr0_el1() & ID_AA64DFR0_DEBUG_BITS) >> ++ ID_AA64DFR0_DEBUG_SHIFT); ++} ++ ++#endif /* ARCH_FEATURES_H */ +diff --git a/environments/shim/include/lib/aarch64/arch_helpers.h b/environments/shim/include/lib/aarch64/arch_helpers.h +new file mode 100644 +index 0000000..9bcd0bb +--- /dev/null ++++ b/environments/shim/include/lib/aarch64/arch_helpers.h +@@ -0,0 +1,526 @@ ++/* ++ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef ARCH_HELPERS_H ++#define ARCH_HELPERS_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++/********************************************************************** ++ * Macros which create inline functions to read or write CPU system ++ * registers ++ *********************************************************************/ ++ ++#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ ++static inline u_register_t read_ ## _name(void) \ ++{ \ ++ u_register_t v; \ ++ __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ ++ return v; \ ++} ++ ++#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ ++static inline void write_ ## _name(u_register_t v) \ ++{ \ ++ __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ ++} ++ ++#define SYSREG_WRITE_CONST(reg_name, v) \ ++ __asm__ volatile ("msr " #reg_name ", %0" : : "i" (v)) ++ ++/* Define read function for system register */ ++#define DEFINE_SYSREG_READ_FUNC(_name) \ ++ _DEFINE_SYSREG_READ_FUNC(_name, _name) ++ ++/* Define read & write function for system register */ ++#define DEFINE_SYSREG_RW_FUNCS(_name) \ ++ _DEFINE_SYSREG_READ_FUNC(_name, _name) \ ++ _DEFINE_SYSREG_WRITE_FUNC(_name, _name) ++ ++/* Define read & write function for renamed system register */ ++#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \ ++ _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ ++ _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) ++ ++/* Define read function for renamed system register */ ++#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name) \ ++ _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) ++ ++/* Define write function for renamed system register */ ++#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \ ++ _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) ++ ++/********************************************************************** ++ * Macros to create inline functions for system instructions ++ *********************************************************************/ ++ ++/* Define function for simple system instruction */ ++#define DEFINE_SYSOP_FUNC(_op) \ ++static inline void _op(void) \ ++{ \ ++ __asm__ (#_op); \ ++} ++ ++/* Define function for system instruction with type specifier */ ++#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ ++static inline void _op ## _type(void) \ ++{ \ ++ __asm__ (#_op " " #_type); \ ++} ++ ++/* Define function for system instruction with register parameter */ ++#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ ++static inline void _op ## _type(uint64_t v) \ ++{ \ ++ __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ ++} ++ ++/******************************************************************************* ++ * TLB maintenance accessor prototypes ++ ******************************************************************************/ ++ ++#if ERRATA_A57_813419 ++/* ++ * Define function for TLBI instruction with type specifier that implements ++ * the workaround for errata 813419 of Cortex-A57. ++ */ ++#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(_type)\ ++static inline void tlbi ## _type(void) \ ++{ \ ++ __asm__("tlbi " #_type "\n" \ ++ "dsb ish\n" \ ++ "tlbi " #_type); \ ++} ++ ++/* ++ * Define function for TLBI instruction with register parameter that implements ++ * the workaround for errata 813419 of Cortex-A57. ++ */ ++#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(_type) \ ++static inline void tlbi ## _type(uint64_t v) \ ++{ \ ++ __asm__("tlbi " #_type ", %0\n" \ ++ "dsb ish\n" \ ++ "tlbi " #_type ", %0" : : "r" (v)); \ ++} ++#endif /* ERRATA_A57_813419 */ ++ ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) ++#if ERRATA_A57_813419 ++DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3) ++DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3is) ++#else ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3) ++DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is) ++#endif ++DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) ++ ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) ++#if ERRATA_A57_813419 ++DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vae3is) ++DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vale3is) ++#else ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is) ++#endif ++ ++/******************************************************************************* ++ * Cache maintenance accessor prototypes ++ ******************************************************************************/ ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva) ++ ++/******************************************************************************* ++ * Address translation accessor prototypes ++ ******************************************************************************/ ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e1r) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r) ++DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r) ++ ++void flush_dcache_range(uintptr_t addr, size_t size); ++void clean_dcache_range(uintptr_t addr, size_t size); ++void inv_dcache_range(uintptr_t addr, size_t size); ++ ++void dcsw_op_louis(u_register_t op_type); ++void dcsw_op_all(u_register_t op_type); ++ ++void disable_mmu(void); ++void disable_mmu_icache(void); ++ ++/******************************************************************************* ++ * Misc. accessor prototypes ++ ******************************************************************************/ ++ ++#define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val) ++#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val) ++ ++DEFINE_SYSREG_RW_FUNCS(par_el1) ++DEFINE_SYSREG_READ_FUNC(id_pfr1_el1) ++DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1) ++DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1) ++DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1) ++DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1) ++DEFINE_SYSREG_READ_FUNC(id_afr0_el1) ++DEFINE_SYSREG_READ_FUNC(CurrentEl) ++DEFINE_SYSREG_READ_FUNC(ctr_el0) ++DEFINE_SYSREG_RW_FUNCS(daif) ++DEFINE_SYSREG_RW_FUNCS(spsr_el1) ++DEFINE_SYSREG_RW_FUNCS(spsr_el2) ++DEFINE_SYSREG_RW_FUNCS(spsr_el3) ++DEFINE_SYSREG_RW_FUNCS(elr_el1) ++DEFINE_SYSREG_RW_FUNCS(elr_el2) ++DEFINE_SYSREG_RW_FUNCS(elr_el3) ++ ++DEFINE_SYSOP_FUNC(wfi) ++DEFINE_SYSOP_FUNC(wfe) ++DEFINE_SYSOP_FUNC(sev) ++DEFINE_SYSOP_TYPE_FUNC(dsb, sy) ++DEFINE_SYSOP_TYPE_FUNC(dmb, sy) ++DEFINE_SYSOP_TYPE_FUNC(dmb, st) ++DEFINE_SYSOP_TYPE_FUNC(dmb, ld) ++DEFINE_SYSOP_TYPE_FUNC(dsb, ish) ++DEFINE_SYSOP_TYPE_FUNC(dsb, nsh) ++DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) ++DEFINE_SYSOP_TYPE_FUNC(dmb, oshld) ++DEFINE_SYSOP_TYPE_FUNC(dmb, oshst) ++DEFINE_SYSOP_TYPE_FUNC(dmb, osh) ++DEFINE_SYSOP_TYPE_FUNC(dmb, nshld) ++DEFINE_SYSOP_TYPE_FUNC(dmb, nshst) ++DEFINE_SYSOP_TYPE_FUNC(dmb, nsh) ++DEFINE_SYSOP_TYPE_FUNC(dmb, ishld) ++DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) ++DEFINE_SYSOP_TYPE_FUNC(dmb, ish) ++DEFINE_SYSOP_FUNC(isb) ++ ++static inline void enable_irq(void) ++{ ++ /* ++ * The compiler memory barrier will prevent the compiler from ++ * scheduling non-volatile memory access after the write to the ++ * register. ++ * ++ * This could happen if some initialization code issues non-volatile ++ * accesses to an area used by an interrupt handler, in the assumption ++ * that it is safe as the interrupts are disabled at the time it does ++ * that (according to program order). However, non-volatile accesses ++ * are not necessarily in program order relatively with volatile inline ++ * assembly statements (and volatile accesses). ++ */ ++ COMPILER_BARRIER(); ++ write_daifclr(DAIF_IRQ_BIT); ++ isb(); ++} ++ ++static inline void enable_fiq(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifclr(DAIF_FIQ_BIT); ++ isb(); ++} ++ ++static inline void enable_serror(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifclr(DAIF_ABT_BIT); ++ isb(); ++} ++ ++static inline void enable_debug_exceptions(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifclr(DAIF_DBG_BIT); ++ isb(); ++} ++ ++static inline void disable_irq(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifset(DAIF_IRQ_BIT); ++ isb(); ++} ++ ++static inline void disable_fiq(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifset(DAIF_FIQ_BIT); ++ isb(); ++} ++ ++static inline void disable_serror(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifset(DAIF_ABT_BIT); ++ isb(); ++} ++ ++static inline void disable_debug_exceptions(void) ++{ ++ COMPILER_BARRIER(); ++ write_daifset(DAIF_DBG_BIT); ++ isb(); ++} ++ ++void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, ++ uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); ++ ++/******************************************************************************* ++ * System register accessor prototypes ++ ******************************************************************************/ ++DEFINE_SYSREG_READ_FUNC(midr_el1) ++DEFINE_SYSREG_READ_FUNC(mpidr_el1) ++DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1) ++ ++DEFINE_SYSREG_RW_FUNCS(scr_el3) ++DEFINE_SYSREG_RW_FUNCS(hcr_el2) ++ ++DEFINE_SYSREG_RW_FUNCS(vbar_el1) ++DEFINE_SYSREG_RW_FUNCS(vbar_el2) ++DEFINE_SYSREG_RW_FUNCS(vbar_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(sctlr_el1) ++DEFINE_SYSREG_RW_FUNCS(sctlr_el2) ++DEFINE_SYSREG_RW_FUNCS(sctlr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(actlr_el1) ++DEFINE_SYSREG_RW_FUNCS(actlr_el2) ++DEFINE_SYSREG_RW_FUNCS(actlr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(esr_el1) ++DEFINE_SYSREG_RW_FUNCS(esr_el2) ++DEFINE_SYSREG_RW_FUNCS(esr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(afsr0_el1) ++DEFINE_SYSREG_RW_FUNCS(afsr0_el2) ++DEFINE_SYSREG_RW_FUNCS(afsr0_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(afsr1_el1) ++DEFINE_SYSREG_RW_FUNCS(afsr1_el2) ++DEFINE_SYSREG_RW_FUNCS(afsr1_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(far_el1) ++DEFINE_SYSREG_RW_FUNCS(far_el2) ++DEFINE_SYSREG_RW_FUNCS(far_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(mair_el1) ++DEFINE_SYSREG_RW_FUNCS(mair_el2) ++DEFINE_SYSREG_RW_FUNCS(mair_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(amair_el1) ++DEFINE_SYSREG_RW_FUNCS(amair_el2) ++DEFINE_SYSREG_RW_FUNCS(amair_el3) ++ ++DEFINE_SYSREG_READ_FUNC(rvbar_el1) ++DEFINE_SYSREG_READ_FUNC(rvbar_el2) ++DEFINE_SYSREG_READ_FUNC(rvbar_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(rmr_el1) ++DEFINE_SYSREG_RW_FUNCS(rmr_el2) ++DEFINE_SYSREG_RW_FUNCS(rmr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(tcr_el1) ++DEFINE_SYSREG_RW_FUNCS(tcr_el2) ++DEFINE_SYSREG_RW_FUNCS(tcr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(ttbr0_el1) ++DEFINE_SYSREG_RW_FUNCS(ttbr0_el2) ++DEFINE_SYSREG_RW_FUNCS(ttbr0_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(ttbr1_el1) ++ ++DEFINE_SYSREG_RW_FUNCS(vttbr_el2) ++ ++DEFINE_SYSREG_RW_FUNCS(cptr_el2) ++DEFINE_SYSREG_RW_FUNCS(cptr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(cpacr_el1) ++DEFINE_SYSREG_RW_FUNCS(cntfrq_el0) ++DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) ++DEFINE_SYSREG_RW_FUNCS(cnthp_tval_el2) ++DEFINE_SYSREG_RW_FUNCS(cnthp_cval_el2) ++DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1) ++DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1) ++DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1) ++DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0) ++DEFINE_SYSREG_RW_FUNCS(cntp_tval_el0) ++DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0) ++DEFINE_SYSREG_READ_FUNC(cntpct_el0) ++DEFINE_SYSREG_RW_FUNCS(cnthctl_el2) ++ ++#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \ ++ CNTP_CTL_ENABLE_MASK) ++#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \ ++ CNTP_CTL_IMASK_MASK) ++#define get_cntp_ctl_istatus(x) (((x) >> CNTP_CTL_ISTATUS_SHIFT) & \ ++ CNTP_CTL_ISTATUS_MASK) ++ ++#define set_cntp_ctl_enable(x) ((x) |= (U(1) << CNTP_CTL_ENABLE_SHIFT)) ++#define set_cntp_ctl_imask(x) ((x) |= (U(1) << CNTP_CTL_IMASK_SHIFT)) ++ ++#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT)) ++#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT)) ++ ++DEFINE_SYSREG_RW_FUNCS(tpidr_el3) ++ ++DEFINE_SYSREG_RW_FUNCS(cntvoff_el2) ++ ++DEFINE_SYSREG_RW_FUNCS(vpidr_el2) ++DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) ++ ++DEFINE_SYSREG_READ_FUNC(isr_el1) ++ ++DEFINE_SYSREG_RW_FUNCS(mdcr_el2) ++DEFINE_SYSREG_RW_FUNCS(mdcr_el3) ++DEFINE_SYSREG_RW_FUNCS(hstr_el2) ++DEFINE_SYSREG_RW_FUNCS(pmcr_el0) ++DEFINE_SYSREG_RW_FUNCS(pmcntenset_el0) ++DEFINE_SYSREG_READ_FUNC(pmccntr_el0) ++DEFINE_SYSREG_RW_FUNCS(pmccfiltr_el0) ++ ++DEFINE_SYSREG_RW_FUNCS(pmevtyper0_el0) ++DEFINE_SYSREG_READ_FUNC(pmevcntr0_el0) ++ ++/* GICv3 System Registers */ ++ ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1) ++DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) ++DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) ++DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R) ++ ++DEFINE_RENAME_SYSREG_RW_FUNCS(amcgcr_el0, AMCGCR_EL0) ++DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) ++DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) ++DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) ++DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) ++ ++DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3) ++DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2) ++ ++DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) ++ ++DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3) ++DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2) ++ ++DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1) ++DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1) ++ ++DEFINE_RENAME_SYSREG_READ_FUNC(erxfr_el1, ERXFR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(erxctlr_el1, ERXCTLR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(erxstatus_el1, ERXSTATUS_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(erxaddr_el1, ERXADDR_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1) ++DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) ++ ++/* Armv8.2 Registers */ ++DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) ++ ++/* Armv8.3 Pointer Authentication Registers */ ++/* Instruction keys A and B */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1) ++ ++DEFINE_RENAME_SYSREG_RW_FUNCS(apibkeyhi_el1, APIBKeyHi_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(apibkeylo_el1, APIBKeyLo_EL1) ++ ++/* Data keys A and B */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(apdakeyhi_el1, APDAKeyHi_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(apdakeylo_el1, APDAKeyLo_EL1) ++ ++DEFINE_RENAME_SYSREG_RW_FUNCS(apdbkeyhi_el1, APDBKeyHi_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(apdbkeylo_el1, APDBKeyLo_EL1) ++ ++/* Generic key */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(apgakeyhi_el1, APGAKeyHi_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(apgakeylo_el1, APGAKeyLo_EL1) ++ ++/* MTE registers */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1) ++DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1) ++ ++/* Armv8.6 Fine Grained Virtualization Traps Registers */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(hfgrtr_el2, HFGRTR_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(hfgwtr_el2, HFGWTR_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(hfgitr_el2, HFGITR_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgrtr_el2, HDFGRTR_EL2) ++DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgwtr_el2, HDFGWTR_EL2) ++ ++/* Armv8.6 Enhanced Counter Virtualization Register */ ++DEFINE_RENAME_SYSREG_RW_FUNCS(cntpoff_el2, CNTPOFF_EL2) ++ ++#define IS_IN_EL(x) \ ++ (GET_EL(read_CurrentEl()) == MODE_EL##x) ++ ++#define IS_IN_EL1() IS_IN_EL(1) ++#define IS_IN_EL2() IS_IN_EL(2) ++#define IS_IN_EL3() IS_IN_EL(3) ++ ++static inline unsigned int get_current_el(void) ++{ ++ return GET_EL(read_CurrentEl()); ++} ++ ++/* ++ * Check if an EL is implemented from AA64PFR0 register fields. ++ */ ++static inline uint64_t el_implemented(unsigned int el) ++{ ++ if (el > 3U) { ++ return EL_IMPL_NONE; ++ } else { ++ unsigned int shift = ID_AA64PFR0_EL1_SHIFT * el; ++ ++ return (read_id_aa64pfr0_el1() >> shift) & ID_AA64PFR0_ELX_MASK; ++ } ++} ++ ++/* Read the count value of the system counter. */ ++static inline uint64_t syscounter_read(void) ++{ ++ /* ++ * The instruction barrier is needed to guarantee that we read an ++ * accurate value. Otherwise, the CPU might speculatively read it and ++ * return a stale value. ++ */ ++ isb(); ++ return read_cntpct_el0(); ++} ++ ++#endif /* ARCH_HELPERS_H */ +diff --git a/environments/shim/include/lib/cassert.h b/environments/shim/include/lib/cassert.h +new file mode 100644 +index 0000000..8844e8b +--- /dev/null ++++ b/environments/shim/include/lib/cassert.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __CASSERT_H__ ++#define __CASSERT_H__ ++ ++/******************************************************************************* ++ * Macro to flag a compile time assertion. It uses the preprocessor to generate ++ * an invalid C construct if 'cond' evaluates to false. ++ * The following compilation error is triggered if the assertion fails: ++ * "error: size of array 'msg' is negative" ++ ******************************************************************************/ ++#define CASSERT(cond, msg) typedef char msg[(cond) ? 1 : -1] ++ ++#endif /* __CASSERT_H__ */ +diff --git a/environments/shim/include/lib/libc/aarch64/endian_.h b/environments/shim/include/lib/libc/aarch64/endian_.h +new file mode 100644 +index 0000000..7c79fd4 +--- /dev/null ++++ b/environments/shim/include/lib/libc/aarch64/endian_.h +@@ -0,0 +1,128 @@ ++/*- ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * Copyright (c) 2001 David E. O'Brien ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)endian.h 8.1 (Berkeley) 6/10/93 ++ * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ ++ * $FreeBSD$ ++ */ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef ENDIAN__H ++#define ENDIAN__H ++ ++#include ++ ++/* ++ * Definitions for byte order, according to byte significance from low ++ * address to high. ++ */ ++#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ ++#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ ++#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ ++ ++#define _BYTE_ORDER _LITTLE_ENDIAN ++ ++#if __BSD_VISIBLE ++#define LITTLE_ENDIAN _LITTLE_ENDIAN ++#define BIG_ENDIAN _BIG_ENDIAN ++#define PDP_ENDIAN _PDP_ENDIAN ++#define BYTE_ORDER _BYTE_ORDER ++#endif ++ ++#define _QUAD_HIGHWORD 1 ++#define _QUAD_LOWWORD 0 ++#define __ntohl(x) (__bswap32(x)) ++#define __ntohs(x) (__bswap16(x)) ++#define __htonl(x) (__bswap32(x)) ++#define __htons(x) (__bswap16(x)) ++ ++static __inline uint64_t ++__bswap64(uint64_t x) ++{ ++ uint64_t ret; ++ ++ __asm __volatile("rev %0, %1\n" ++ : "=&r" (ret), "+r" (x)); ++ ++ return (ret); ++} ++ ++static __inline uint32_t ++__bswap32_var(uint32_t v) ++{ ++ uint32_t ret; ++ ++ __asm __volatile("rev32 %x0, %x1\n" ++ : "=&r" (ret), "+r" (v)); ++ ++ return (ret); ++} ++ ++static __inline uint16_t ++__bswap16_var(uint16_t v) ++{ ++ uint32_t ret; ++ ++ __asm __volatile("rev16 %w0, %w1\n" ++ : "=&r" (ret), "+r" (v)); ++ ++ return ((uint16_t)ret); ++} ++ ++#ifdef __OPTIMIZE__ ++ ++#define __bswap32_constant(x) \ ++ ((((x) & 0xff000000U) >> 24) | \ ++ (((x) & 0x00ff0000U) >> 8) | \ ++ (((x) & 0x0000ff00U) << 8) | \ ++ (((x) & 0x000000ffU) << 24)) ++ ++#define __bswap16_constant(x) \ ++ ((((x) & 0xff00) >> 8) | \ ++ (((x) & 0x00ff) << 8)) ++ ++#define __bswap16(x) \ ++ ((uint16_t)(__builtin_constant_p(x) ? \ ++ __bswap16_constant((uint16_t)(x)) : \ ++ __bswap16_var(x))) ++ ++#define __bswap32(x) \ ++ ((uint32_t)(__builtin_constant_p(x) ? \ ++ __bswap32_constant((uint32_t)(x)) : \ ++ __bswap32_var(x))) ++ ++#else ++#define __bswap16(x) __bswap16_var(x) ++#define __bswap32(x) __bswap32_var(x) ++ ++#endif /* __OPTIMIZE__ */ ++#endif /* ENDIAN__H */ +diff --git a/environments/shim/include/lib/libc/aarch64/limits_.h b/environments/shim/include/lib/libc/aarch64/limits_.h +new file mode 100644 +index 0000000..e36cfe7 +--- /dev/null ++++ b/environments/shim/include/lib/libc/aarch64/limits_.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define SCHAR_MAX 0x7F ++#define SCHAR_MIN (-SCHAR_MIN - 1) ++#define CHAR_MAX 0x7F ++#define CHAR_MIN (-CHAR_MAX - 1) ++#define UCHAR_MAX 0xFFU ++#define SHRT_MAX 0x7FFF ++#define SHRT_MIN (-SHRT_MAX - 1) ++#define USHRT_MAX 0xFFFFU ++#define INT_MAX 0x7FFFFFFF ++#define INT_MIN (-INT_MAX - 1) ++#define UINT_MAX 0xFFFFFFFFU ++#define LONG_MAX 0x7FFFFFFFFFFFFFFFL ++#define LONG_MIN (-LONG_MAX - 1L) ++#define ULONG_MAX 0xFFFFFFFFFFFFFFFFUL ++#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL ++#define LLONG_MIN (-LLONG_MAX - 1LL) ++#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL ++ ++#define __LONG_BIT 64 ++#define __WORD_BIT 32 +diff --git a/environments/shim/include/lib/libc/aarch64/setjmp_.h b/environments/shim/include/lib/libc/aarch64/setjmp_.h +new file mode 100644 +index 0000000..174b3eb +--- /dev/null ++++ b/environments/shim/include/lib/libc/aarch64/setjmp_.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SETJMP__H ++#define SETJMP__H ++ ++#define JMP_CTX_X19 0x0 ++#define JMP_CTX_X21 0x10 ++#define JMP_CTX_X23 0x20 ++#define JMP_CTX_X25 0x30 ++#define JMP_CTX_X27 0x40 ++#define JMP_CTX_X29 0x50 ++#define JMP_CTX_SP 0x60 ++#define JMP_CTX_END 0x70 /* Aligned to 16 bytes */ ++ ++#define JMP_SIZE (JMP_CTX_END >> 3) ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++ ++/* Jump buffer hosting x18 - x30 and sp_el0 registers */ ++typedef uint64_t jmp_buf[JMP_SIZE] __aligned(16); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* SETJMP__H */ +diff --git a/environments/shim/include/lib/libc/aarch64/stddef_.h b/environments/shim/include/lib/libc/aarch64/stddef_.h +new file mode 100644 +index 0000000..6ecc606 +--- /dev/null ++++ b/environments/shim/include/lib/libc/aarch64/stddef_.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STDDEF__H ++#define STDDEF__H ++ ++#ifndef SIZET_ ++typedef unsigned long size_t; ++#define SIZET_ ++#endif ++ ++#endif /* STDDEF__H */ +diff --git a/environments/shim/include/lib/libc/aarch64/stdio_.h b/environments/shim/include/lib/libc/aarch64/stdio_.h +new file mode 100644 +index 0000000..afaeadc +--- /dev/null ++++ b/environments/shim/include/lib/libc/aarch64/stdio_.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STDIO__H ++#define STDIO__H ++ ++#ifndef SSIZET_ ++typedef long ssize_t; ++#define SSIZET_ ++#endif ++ ++#endif /* STDIO__H */ +diff --git a/environments/shim/include/lib/libc/assert.h b/environments/shim/include/lib/libc/assert.h +new file mode 100644 +index 0000000..ec28c26 +--- /dev/null ++++ b/environments/shim/include/lib/libc/assert.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef ASSERT_H ++#define ASSERT_H ++ ++#include ++ ++#include ++ ++#if ENABLE_ASSERTIONS ++#define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) ++#else ++#define assert(e) ((void)0) ++#endif /* ENABLE_ASSERTIONS */ ++ ++__dead2 void __assert(const char *file, unsigned int line, ++ const char *assertion); ++ ++#define COMPILE_TIME_ASSERT(x) \ ++ do { \ ++ switch (0) { case 0: case ((x) ? 1: 0): default : break; } \ ++ } while (0) ++ ++#endif /* ASSERT_H */ +diff --git a/environments/shim/include/lib/libc/cdefs.h b/environments/shim/include/lib/libc/cdefs.h +new file mode 100644 +index 0000000..c3dd6f1 +--- /dev/null ++++ b/environments/shim/include/lib/libc/cdefs.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef CDEFS_H ++#define CDEFS_H ++ ++#define __dead2 __attribute__((__noreturn__)) ++#define __deprecated __attribute__((__deprecated__)) ++#define __packed __attribute__((__packed__)) ++#define __used __attribute__((__used__)) ++#define __unused __attribute__((__unused__)) ++#define __aligned(x) __attribute__((__aligned__(x))) ++#define __section(x) __attribute__((__section__(x))) ++/* ++ * For compatibility with TF-A codebase. ++ */ ++#define __init ++ ++ ++#define __printflike(fmtarg, firstvararg) \ ++ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) ++ ++#define __weak_reference(sym, alias) \ ++ __asm__(".weak alias"); \ ++ __asm__(".equ alias, sym") ++ ++#define __STRING(x) #x ++#define __XSTRING(x) __STRING(x) ++ ++#endif /* CDEFS_H */ +diff --git a/environments/shim/include/lib/libc/compiler.h b/environments/shim/include/lib/libc/compiler.h +new file mode 100644 +index 0000000..b9474cf +--- /dev/null ++++ b/environments/shim/include/lib/libc/compiler.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ * Copyright (c) 2021, Arm Limited. ++ */ ++ ++#ifndef COMPILER_H ++#define COMPILER_H ++ ++#define __packed __attribute__((__packed__)) ++#define __noreturn __attribute__((__noreturn__)) ++#define __maybe_unused __attribute__((__unused__)) ++ ++#define __GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + \ ++ __GNUC_PATCHLEVEL__) ++ ++#if __GCC_VERSION >= 50100 && !defined(__CHECKER__) ++#define __HAVE_BUILTIN_OVERFLOW 1 ++#endif ++ ++#ifdef __HAVE_BUILTIN_OVERFLOW ++#define __compiler_add_overflow(a, b, res) \ ++ __builtin_add_overflow((a), (b), (res)) ++ ++#define __compiler_sub_overflow(a, b, res) \ ++ __builtin_sub_overflow((a), (b), (res)) ++ ++#define __compiler_mul_overflow(a, b, res) \ ++ __builtin_mul_overflow((a), (b), (res)) ++#endif /*!__HAVE_BUILTIN_OVERFLOW*/ ++ ++#endif /* CDEFS_H */ +diff --git a/environments/shim/include/lib/libc/endian.h b/environments/shim/include/lib/libc/endian.h +new file mode 100644 +index 0000000..4100f57 +--- /dev/null ++++ b/environments/shim/include/lib/libc/endian.h +@@ -0,0 +1,191 @@ ++/*- ++ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD ++ * ++ * Copyright (c) 2002 Thomas Moestl ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * $FreeBSD$ ++ */ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef ENDIAN_H ++#define ENDIAN_H ++ ++#include ++#include ++#include ++ ++/* ++ * General byte order swapping functions. ++ */ ++#define bswap16(x) __bswap16(x) ++#define bswap32(x) __bswap32(x) ++#define bswap64(x) __bswap64(x) ++ ++/* ++ * Host to big endian, host to little endian, big endian to host, and little ++ * endian to host byte order functions as detailed in byteorder(9). ++ */ ++#if _BYTE_ORDER == _LITTLE_ENDIAN ++#define htobe16(x) bswap16((x)) ++#define htobe32(x) bswap32((x)) ++#define htobe64(x) bswap64((x)) ++#define htole16(x) ((uint16_t)(x)) ++#define htole32(x) ((uint32_t)(x)) ++#define htole64(x) ((uint64_t)(x)) ++ ++#define be16toh(x) bswap16((x)) ++#define be32toh(x) bswap32((x)) ++#define be64toh(x) bswap64((x)) ++#define le16toh(x) ((uint16_t)(x)) ++#define le32toh(x) ((uint32_t)(x)) ++#define le64toh(x) ((uint64_t)(x)) ++#else /* _BYTE_ORDER != _LITTLE_ENDIAN */ ++#define htobe16(x) ((uint16_t)(x)) ++#define htobe32(x) ((uint32_t)(x)) ++#define htobe64(x) ((uint64_t)(x)) ++#define htole16(x) bswap16((x)) ++#define htole32(x) bswap32((x)) ++#define htole64(x) bswap64((x)) ++ ++#define be16toh(x) ((uint16_t)(x)) ++#define be32toh(x) ((uint32_t)(x)) ++#define be64toh(x) ((uint64_t)(x)) ++#define le16toh(x) bswap16((x)) ++#define le32toh(x) bswap32((x)) ++#define le64toh(x) bswap64((x)) ++#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ ++ ++/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ ++ ++static __inline uint16_t ++be16dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return ((p[0] << 8) | p[1]); ++} ++ ++static __inline uint32_t ++be32dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); ++} ++ ++static __inline uint64_t ++be64dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); ++} ++ ++static __inline uint16_t ++le16dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return ((p[1] << 8) | p[0]); ++} ++ ++static __inline uint32_t ++le32dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); ++} ++ ++static __inline uint64_t ++le64dec(const void *pp) ++{ ++ uint8_t const *p = (uint8_t const *)pp; ++ ++ return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); ++} ++ ++static __inline void ++be16enc(void *pp, uint16_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ p[0] = (u >> 8) & 0xff; ++ p[1] = u & 0xff; ++} ++ ++static __inline void ++be32enc(void *pp, uint32_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ p[0] = (u >> 24) & 0xff; ++ p[1] = (u >> 16) & 0xff; ++ p[2] = (u >> 8) & 0xff; ++ p[3] = u & 0xff; ++} ++ ++static __inline void ++be64enc(void *pp, uint64_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ be32enc(p, (uint32_t)(u >> 32)); ++ be32enc(p + 4, (uint32_t)(u & 0xffffffffU)); ++} ++ ++static __inline void ++le16enc(void *pp, uint16_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ p[0] = u & 0xff; ++ p[1] = (u >> 8) & 0xff; ++} ++ ++static __inline void ++le32enc(void *pp, uint32_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ p[0] = u & 0xff; ++ p[1] = (u >> 8) & 0xff; ++ p[2] = (u >> 16) & 0xff; ++ p[3] = (u >> 24) & 0xff; ++} ++ ++static __inline void ++le64enc(void *pp, uint64_t u) ++{ ++ uint8_t *p = (uint8_t *)pp; ++ ++ le32enc(p, (uint32_t)(u & 0xffffffffU)); ++ le32enc(p + 4, (uint32_t)(u >> 32)); ++} ++ ++#endif /* ENDIAN_H */ +diff --git a/environments/shim/include/lib/libc/errno.h b/environments/shim/include/lib/libc/errno.h +new file mode 100644 +index 0000000..029912f +--- /dev/null ++++ b/environments/shim/include/lib/libc/errno.h +@@ -0,0 +1,169 @@ ++/*- ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * Copyright (c) 1982, 1986, 1989, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * (c) UNIX System Laboratories, Inc. ++ * All or some portions of this file are derived from material licensed ++ * to the University of California by American Telephone and Telegraph ++ * Co. or Unix System Laboratories, Inc. and are reproduced herein with ++ * the permission of UNIX System Laboratories, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)errno.h 8.5 (Berkeley) 1/21/94 ++ * $FreeBSD$ ++ */ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef ERRNO_H ++#define ERRNO_H ++ ++#define EPERM 1 /* Operation not permitted */ ++#define ENOENT 2 /* No such file or directory */ ++#define ESRCH 3 /* No such process */ ++#define EINTR 4 /* Interrupted system call */ ++#define EIO 5 /* Input/output error */ ++#define ENXIO 6 /* Device not configured */ ++#define E2BIG 7 /* Argument list too long */ ++#define ENOEXEC 8 /* Exec format error */ ++#define EBADF 9 /* Bad file descriptor */ ++#define ECHILD 10 /* No child processes */ ++#define EDEADLK 11 /* Resource deadlock avoided */ ++ /* 11 was EAGAIN */ ++#define ENOMEM 12 /* Cannot allocate memory */ ++#define EACCES 13 /* Permission denied */ ++#define EFAULT 14 /* Bad address */ ++#define ENOTBLK 15 /* Block device required */ ++#define EBUSY 16 /* Device busy */ ++#define EEXIST 17 /* File exists */ ++#define EXDEV 18 /* Cross-device link */ ++#define ENODEV 19 /* Operation not supported by device */ ++#define ENOTDIR 20 /* Not a directory */ ++#define EISDIR 21 /* Is a directory */ ++#define EINVAL 22 /* Invalid argument */ ++#define ENFILE 23 /* Too many open files in system */ ++#define EMFILE 24 /* Too many open files */ ++#define ENOTTY 25 /* Inappropriate ioctl for device */ ++#define ETXTBSY 26 /* Text file busy */ ++#define EFBIG 27 /* File too large */ ++#define ENOSPC 28 /* No space left on device */ ++#define ESPIPE 29 /* Illegal seek */ ++#define EROFS 30 /* Read-only filesystem */ ++#define EMLINK 31 /* Too many links */ ++#define EPIPE 32 /* Broken pipe */ ++ ++/* math software */ ++#define EDOM 33 /* Numerical argument out of domain */ ++#define ERANGE 34 /* Result too large */ ++ ++/* non-blocking and interrupt i/o */ ++#define EAGAIN 35 /* Resource temporarily unavailable */ ++#define EWOULDBLOCK EAGAIN /* Operation would block */ ++#define EINPROGRESS 36 /* Operation now in progress */ ++#define EALREADY 37 /* Operation already in progress */ ++ ++/* ipc/network software -- argument errors */ ++#define ENOTSOCK 38 /* Socket operation on non-socket */ ++#define EDESTADDRREQ 39 /* Destination address required */ ++#define EMSGSIZE 40 /* Message too long */ ++#define EPROTOTYPE 41 /* Protocol wrong type for socket */ ++#define ENOPROTOOPT 42 /* Protocol not available */ ++#define EPROTONOSUPPORT 43 /* Protocol not supported */ ++#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ ++#define EOPNOTSUPP 45 /* Operation not supported */ ++#define ENOTSUP EOPNOTSUPP /* Operation not supported */ ++#define EPFNOSUPPORT 46 /* Protocol family not supported */ ++#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ ++#define EADDRINUSE 48 /* Address already in use */ ++#define EADDRNOTAVAIL 49 /* Can't assign requested address */ ++ ++/* ipc/network software -- operational errors */ ++#define ENETDOWN 50 /* Network is down */ ++#define ENETUNREACH 51 /* Network is unreachable */ ++#define ENETRESET 52 /* Network dropped connection on reset */ ++#define ECONNABORTED 53 /* Software caused connection abort */ ++#define ECONNRESET 54 /* Connection reset by peer */ ++#define ENOBUFS 55 /* No buffer space available */ ++#define EISCONN 56 /* Socket is already connected */ ++#define ENOTCONN 57 /* Socket is not connected */ ++#define ESHUTDOWN 58 /* Can't send after socket shutdown */ ++#define ETOOMANYREFS 59 /* Too many references: can't splice */ ++#define ETIMEDOUT 60 /* Operation timed out */ ++#define ECONNREFUSED 61 /* Connection refused */ ++ ++#define ELOOP 62 /* Too many levels of symbolic links */ ++#define ENAMETOOLONG 63 /* File name too long */ ++ ++/* should be rearranged */ ++#define EHOSTDOWN 64 /* Host is down */ ++#define EHOSTUNREACH 65 /* No route to host */ ++#define ENOTEMPTY 66 /* Directory not empty */ ++ ++/* quotas & mush */ ++#define EPROCLIM 67 /* Too many processes */ ++#define EUSERS 68 /* Too many users */ ++#define EDQUOT 69 /* Disc quota exceeded */ ++ ++/* Network File System */ ++#define ESTALE 70 /* Stale NFS file handle */ ++#define EREMOTE 71 /* Too many levels of remote in path */ ++#define EBADRPC 72 /* RPC struct is bad */ ++#define ERPCMISMATCH 73 /* RPC version wrong */ ++#define EPROGUNAVAIL 74 /* RPC prog. not avail */ ++#define EPROGMISMATCH 75 /* Program version wrong */ ++#define EPROCUNAVAIL 76 /* Bad procedure for program */ ++ ++#define ENOLCK 77 /* No locks available */ ++#define ENOSYS 78 /* Function not implemented */ ++ ++#define EFTYPE 79 /* Inappropriate file type or format */ ++#define EAUTH 80 /* Authentication error */ ++#define ENEEDAUTH 81 /* Need authenticator */ ++#define EIDRM 82 /* Identifier removed */ ++#define ENOMSG 83 /* No message of desired type */ ++#define EOVERFLOW 84 /* Value too large to be stored in data type */ ++#define ECANCELED 85 /* Operation canceled */ ++#define EILSEQ 86 /* Illegal byte sequence */ ++#define ENOATTR 87 /* Attribute not found */ ++ ++#define EDOOFUS 88 /* Programming error */ ++ ++#define EBADMSG 89 /* Bad message */ ++#define EMULTIHOP 90 /* Multihop attempted */ ++#define ENOLINK 91 /* Link has been severed */ ++#define EPROTO 92 /* Protocol error */ ++ ++#define ENOTCAPABLE 93 /* Capabilities insufficient */ ++#define ECAPMODE 94 /* Not permitted in capability mode */ ++#define ENOTRECOVERABLE 95 /* State not recoverable */ ++#define EOWNERDEAD 96 /* Previous owner died */ ++ ++#define ELAST 96 /* Must be equal largest errno */ ++ ++#endif /* ERRNO_H */ +diff --git a/environments/shim/include/lib/libc/inttypes.h b/environments/shim/include/lib/libc/inttypes.h +new file mode 100644 +index 0000000..3563870 +--- /dev/null ++++ b/environments/shim/include/lib/libc/inttypes.h +@@ -0,0 +1,54 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ */ ++#ifndef INTTYPES_H ++#define INTTYPES_H ++ ++#include ++ ++#ifdef __ILP32__ ++#define __PRI64_PREFIX "ll" ++#endif ++#ifdef __LP64__ ++#define __PRI64_PREFIX "l" ++#endif ++#define __PRIPTR_PREFIX "l" ++ ++#define PRId8 "d" ++#define PRId16 "d" ++#define PRId32 "d" ++#define PRId64 __PRI64_PREFIX "d" ++#define PRIdPTR __PRIPTR_PREFIX "d" ++ ++#define PRIi8 "i" ++#define PRIi16 "i" ++#define PRIi32 "i" ++#define PRIi64 __PRI64_PREFIX "i" ++#define PRIiPTR __PRIPTR_PREFIX "i" ++ ++#define PRIo8 "o" ++#define PRIo16 "o" ++#define PRIo32 "o" ++#define PRIo64 __PRI64_PREFIX "o" ++#define PRIoPTR __PRIPTR_PREFIX "o" ++ ++#define PRIu8 "u" ++#define PRIu16 "u" ++#define PRIu32 "u" ++#define PRIu64 __PRI64_PREFIX "u" ++#define PRIuPTR __PRIPTR_PREFIX "u" ++ ++#define PRIx8 "x" ++#define PRIx16 "x" ++#define PRIx32 "x" ++#define PRIx64 __PRI64_PREFIX "x" ++#define PRIxPTR __PRIPTR_PREFIX "x" ++ ++#define PRIX8 "X" ++#define PRIX16 "X" ++#define PRIX32 "X" ++#define PRIX64 __PRI64_PREFIX "X" ++#define PRIXPTR __PRIPTR_PREFIX "X" ++ ++#endif /*INTTYPES_H*/ +diff --git a/environments/shim/include/lib/libc/limits.h b/environments/shim/include/lib/libc/limits.h +new file mode 100644 +index 0000000..41bb658 +--- /dev/null ++++ b/environments/shim/include/lib/libc/limits.h +@@ -0,0 +1,19 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef LIMITS_H ++#define LIMITS_H ++ ++#include ++ ++#define CHAR_BIT 8 ++#define MB_LEN_MAX 1 ++ ++#endif /* LIMITS_H */ +diff --git a/environments/shim/include/lib/libc/malloc.h b/environments/shim/include/lib/libc/malloc.h +new file mode 100644 +index 0000000..7c21108 +--- /dev/null ++++ b/environments/shim/include/lib/libc/malloc.h +@@ -0,0 +1,131 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ * Copyright (c) 2021, Arm Limited. ++ */ ++#ifndef MALLOC_H ++#define MALLOC_H ++ ++#include ++#include ++ ++void free(void *ptr); ++ ++#ifdef ENABLE_MDBG ++ ++void *mdbg_malloc(const char *fname, int lineno, size_t size); ++void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); ++void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); ++ ++void mdbg_check(int bufdump); ++ ++#define malloc(size) mdbg_malloc(__FILE__, __LINE__, (size)) ++#define calloc(nmemb, size) \ ++ mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) ++#define realloc(ptr, size) \ ++ mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) ++ ++#else ++ ++void *malloc(size_t size); ++void *calloc(size_t nmemb, size_t size); ++void *realloc(void *ptr, size_t size); ++ ++#define mdbg_check(x) do { } while (0) ++ ++#endif ++ ++ ++/* ++ * Returns true if the supplied memory area is within a buffer ++ * previously allocated (and not freed yet). ++ * ++ * Used internally by TAs ++ */ ++bool malloc_buffer_is_within_alloced(void *buf, size_t len); ++ ++/* ++ * Returns true if the supplied memory area is overlapping the area used ++ * for heap. ++ * ++ * Used internally by TAs ++ */ ++bool malloc_buffer_overlaps_heap(void *buf, size_t len); ++ ++/* ++ * Adds a pool of memory to allocate from. ++ */ ++void malloc_add_pool(void *buf, size_t len); ++ ++#ifdef CFG_WITH_STATS ++/* ++ * Get/reset allocation statistics ++ */ ++ ++#define TEE_ALLOCATOR_DESC_LENGTH 32 ++struct malloc_stats { ++ char desc[TEE_ALLOCATOR_DESC_LENGTH]; ++ uint32_t allocated; /* Bytes currently allocated */ ++ uint32_t max_allocated; /* Tracks max value of allocated */ ++ uint32_t size; /* Total size for this allocator */ ++ uint32_t num_alloc_fail; /* Number of failed alloc requests */ ++ uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ ++ uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ ++}; ++ ++void malloc_get_stats(struct malloc_stats *stats); ++void malloc_reset_stats(void); ++#endif /* CFG_WITH_STATS */ ++ ++ ++#ifdef CFG_VIRTUALIZATION ++ ++void nex_free(void *ptr); ++ ++#ifdef ENABLE_MDBG ++ ++void *nex_mdbg_malloc(const char *fname, int lineno, size_t size); ++void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); ++void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); ++ ++void nex_mdbg_check(int bufdump); ++ ++#define nex_malloc(size) nex_mdbg_malloc(__FILE__, __LINE__, (size)) ++#define nex_calloc(nmemb, size) \ ++ nex_mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) ++#define nex_realloc(ptr, size) \ ++ nex_mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) ++ ++#else /* ENABLE_MDBG */ ++ ++void *nex_malloc(size_t size); ++void *nex_calloc(size_t nmemb, size_t size); ++void *nex_realloc(void *ptr, size_t size); ++ ++#define nex_mdbg_check(x) do { } while (0) ++ ++#endif /* ENABLE_MDBG */ ++ ++bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len); ++bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len); ++void nex_malloc_add_pool(void *buf, size_t len); ++ ++#ifdef CFG_WITH_STATS ++/* ++ * Get/reset allocation statistics ++ */ ++ ++void nex_malloc_get_stats(struct malloc_stats *stats); ++void nex_malloc_reset_stats(void); ++ ++#endif /* CFG_WITH_STATS */ ++#else /* CFG_VIRTUALIZATION */ ++ ++#define nex_free(ptr) free(ptr) ++#define nex_malloc(size) malloc(size) ++#define nex_calloc(nmemb, size) calloc(nmemb, size) ++#define nex_realloc(ptr, size) realloc(ptr, size) ++ ++#endif /* CFG_VIRTUALIZATION */ ++ ++#endif /* MALLOC_H */ +diff --git a/environments/shim/include/lib/libc/setjmp.h b/environments/shim/include/lib/libc/setjmp.h +new file mode 100644 +index 0000000..5661201 +--- /dev/null ++++ b/environments/shim/include/lib/libc/setjmp.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SETJMP_H ++#define SETJMP_H ++ ++#include ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++ ++int setjmp(jmp_buf env); ++__dead2 void longjmp(jmp_buf env, int val); ++ ++#endif /* __ASSEMBLY__ */ ++#endif /* SETJMP_H */ +diff --git a/environments/shim/include/lib/libc/stdarg.h b/environments/shim/include/lib/libc/stdarg.h +new file mode 100644 +index 0000000..e260b9b +--- /dev/null ++++ b/environments/shim/include/lib/libc/stdarg.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STDARG_H ++#define STDARG_H ++ ++#define va_list __builtin_va_list ++#define va_start(ap, last) __builtin_va_start(ap, last) ++#define va_end(ap) __builtin_va_end(ap) ++#define va_copy(to, from) __builtin_va_copy(to, from) ++#define va_arg(to, type) __builtin_va_arg(to, type) ++ ++#endif /* STDARG_H */ +diff --git a/environments/shim/include/lib/libc/stdbool.h b/environments/shim/include/lib/libc/stdbool.h +new file mode 100644 +index 0000000..e39aef7 +--- /dev/null ++++ b/environments/shim/include/lib/libc/stdbool.h +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef STDBOOL_H ++#define STDBOOL_H ++ ++#define bool _Bool ++ ++#define true 1 ++#define false 0 ++ ++#define __bool_true_false_are_defined 1 ++ ++#endif /* STDBOOL_H */ +diff --git a/environments/shim/include/lib/libc/stddef.h b/environments/shim/include/lib/libc/stddef.h +new file mode 100644 +index 0000000..58a519e +--- /dev/null ++++ b/environments/shim/include/lib/libc/stddef.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2019, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STDDEF_H ++#define STDDEF_H ++ ++#include ++ ++#ifndef _PTRDIFF_T ++typedef long ptrdiff_t; ++#define _PTRDIFF_T ++#endif ++ ++#ifndef NULL ++#define NULL ((void *) 0) ++#endif ++ ++#define offsetof(st, m) __builtin_offsetof(st, m) ++ ++#endif /* STDDEF_H */ +diff --git a/environments/shim/include/lib/libc/stdint.h b/environments/shim/include/lib/libc/stdint.h +new file mode 100644 +index 0000000..d5dbfc4 +--- /dev/null ++++ b/environments/shim/include/lib/libc/stdint.h +@@ -0,0 +1,148 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2021, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STDINT_H ++#define STDINT_H ++ ++#include ++ ++#define INT8_MAX CHAR_MAX ++#define INT8_MIN CHAR_MIN ++#define UINT8_MAX UCHAR_MAX ++ ++#define INT16_MAX SHRT_MAX ++#define INT16_MIN SHRT_MIN ++#define UINT16_MAX USHRT_MAX ++ ++#define INT32_MAX INT_MAX ++#define INT32_MIN INT_MIN ++#define UINT32_MAX UINT_MAX ++ ++#define INT64_MAX LLONG_MAX ++#define INT64_MIN LLONG_MIN ++#define UINT64_MAX ULLONG_MAX ++ ++#define INT_LEAST8_MIN INT8_MIN ++#define INT_LEAST8_MAX INT8_MAX ++#define UINT_LEAST8_MAX UINT8_MAX ++ ++#define INT_LEAST16_MIN INT16_MIN ++#define INT_LEAST16_MAX INT16_MAX ++#define UINT_LEAST16_MAX UINT16_MAX ++ ++#define INT_LEAST32_MIN INT32_MIN ++#define INT_LEAST32_MAX INT32_MAX ++#define UINT_LEAST32_MAX UINT32_MAX ++ ++#define INT_LEAST64_MIN INT64_MIN ++#define INT_LEAST64_MAX INT64_MAX ++#define UINT_LEAST64_MAX UINT64_MAX ++ ++#define INT_FAST8_MIN INT32_MIN ++#define INT_FAST8_MAX INT32_MAX ++#define UINT_FAST8_MAX UINT32_MAX ++ ++#define INT_FAST16_MIN INT32_MIN ++#define INT_FAST16_MAX INT32_MAX ++#define UINT_FAST16_MAX UINT32_MAX ++ ++#define INT_FAST32_MIN INT32_MIN ++#define INT_FAST32_MAX INT32_MAX ++#define UINT_FAST32_MAX UINT32_MAX ++ ++#define INT_FAST64_MIN INT64_MIN ++#define INT_FAST64_MAX INT64_MAX ++#define UINT_FAST64_MAX UINT64_MAX ++ ++#define INTPTR_MIN LONG_MIN ++#define INTPTR_MAX LONG_MAX ++#define UINTPTR_MAX ULONG_MAX ++ ++#define INTMAX_MIN LLONG_MIN ++#define INTMAX_MAX LLONG_MAX ++#define UINTMAX_MAX ULLONG_MAX ++ ++#define PTRDIFF_MIN LONG_MIN ++#define PTRDIFF_MAX LONG_MAX ++ ++#define SIZE_MAX ULONG_MAX ++ ++#define INT8_C(x) x ++#define INT16_C(x) x ++#define INT32_C(x) x ++#define INT64_C(x) x ## LL ++ ++#define UINT8_C(x) x ++#define UINT16_C(x) x ++#define UINT32_C(x) x ## U ++#define UINT64_C(x) x ## ULL ++ ++#define INTMAX_C(x) x ## LL ++#define UINTMAX_C(x) x ## ULL ++ ++typedef signed char int8_t; ++typedef short int16_t; ++typedef int int32_t; ++typedef long long int64_t; ++ ++typedef unsigned char uint8_t; ++typedef unsigned short uint16_t; ++typedef unsigned int uint32_t; ++typedef unsigned long long uint64_t; ++ ++typedef signed char int8_least_t; ++typedef short int16_least_t; ++typedef int int32_least_t; ++typedef long long int64_least_t; ++ ++typedef unsigned char uint8_least_t; ++typedef unsigned short uint16_least_t; ++typedef unsigned int uint32_least_t; ++typedef unsigned long long uint64_least_t; ++ ++typedef int int8_fast_t; ++typedef int int16_fast_t; ++typedef int int32_fast_t; ++typedef long long int64_fast_t; ++ ++typedef unsigned int uint8_fast_t; ++typedef unsigned int uint16_fast_t; ++typedef unsigned int uint32_fast_t; ++typedef unsigned long long uint64_fast_t; ++ ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++ ++/* 7.18.1.2 Minimum-width integer types */ ++typedef int8_t int_least8_t; ++typedef int16_t int_least16_t; ++typedef int32_t int_least32_t; ++typedef int64_t int_least64_t; ++typedef uint8_t uint_least8_t; ++typedef uint16_t uint_least16_t; ++typedef uint32_t uint_least32_t; ++typedef uint64_t uint_least64_t; ++ ++/* ++* Conceptually, these are supposed to be the largest integers representable in C, ++* but GCC and Clang define them as long long for compatibility. ++*/ ++typedef long long intmax_t; ++typedef unsigned long long uintmax_t; ++ ++typedef long register_t; ++typedef unsigned long u_register_t; ++ ++#ifdef __aarch64__ ++typedef __int128 int128_t; ++typedef unsigned __int128 uint128_t; ++#endif /* __aarch64__ */ ++ ++#endif /* STDINT_H */ +diff --git a/environments/shim/include/lib/libc/stdio.h b/environments/shim/include/lib/libc/stdio.h +new file mode 100644 +index 0000000..88d4d73 +--- /dev/null ++++ b/environments/shim/include/lib/libc/stdio.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2021, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STDIO_H ++#define STDIO_H ++ ++#include ++#include ++#include ++ ++#define EOF -1 ++ ++int printf(const char *fmt, ...) __printflike(1, 2); ++int snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4); ++ ++#ifdef STDARG_H ++int vprintf(const char *fmt, va_list args) __printflike(1, 0); ++int vsnprintf(char *str, size_t size, const char *format, va_list ap) __printflike(3, 0); ++#endif ++ ++int putchar(int c); ++int puts(const char *s); ++ ++typedef struct _FILE FILE; ++ ++#endif /* STDIO_H */ +diff --git a/environments/shim/include/lib/libc/stdlib.h b/environments/shim/include/lib/libc/stdlib.h +new file mode 100644 +index 0000000..bbd6889 +--- /dev/null ++++ b/environments/shim/include/lib/libc/stdlib.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2021, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STDLIB_H ++#define STDLIB_H ++ ++#include ++ ++#define EXIT_FAILURE 1 ++#define EXIT_SUCCESS 0 ++ ++#define _ATEXIT_MAX 1 ++ ++#define RAND_MAX 0x7ffffffd ++ ++extern void abort(void); ++extern int atexit(void (*func)(void)); ++extern void exit(int status); ++ ++int rand(void); ++void srand(unsigned int seed); ++ ++void malloc_add_pool(void *buf, size_t len); ++void *malloc(size_t size); ++void free(void *ptr); ++ ++#endif /* STDLIB_H */ +diff --git a/environments/shim/include/lib/libc/string.h b/environments/shim/include/lib/libc/string.h +new file mode 100644 +index 0000000..8df8cf9 +--- /dev/null ++++ b/environments/shim/include/lib/libc/string.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2019, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef STRING_H ++#define STRING_H ++ ++#include ++ ++void *memcpy(void *dst, const void *src, size_t len); ++void *memmove(void *dst, const void *src, size_t len); ++int memcmp(const void *s1, const void *s2, size_t len); ++int strcmp(const char *s1, const char *s2); ++int strncmp(const char *s1, const char *s2, size_t n); ++void *memchr(const void *src, int c, size_t len); ++char *strchr(const char *s, int c); ++void *memset(void *dst, int val, size_t count); ++size_t strlen(const char *s); ++size_t strnlen(const char *s, size_t maxlen); ++char *strrchr(const char *p, int ch); ++size_t strlcpy(char * dst, const char * src, size_t dsize); ++char *strncpy(char *dst, const char *src, size_t n); ++ ++#endif /* STRING_H */ +diff --git a/environments/shim/include/lib/libc/time.h b/environments/shim/include/lib/libc/time.h +new file mode 100644 +index 0000000..c1c95e5 +--- /dev/null ++++ b/environments/shim/include/lib/libc/time.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2012-2017 Roberto E. Vargas Caballero ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++/* ++ * Portions copyright (c) 2018-2019, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef TIME_H ++#define TIME_H ++ ++#include ++ ++typedef long int time_t; ++ ++#endif /* TIME_H */ +diff --git a/environments/shim/include/lib/libc/util.h b/environments/shim/include/lib/libc/util.h +new file mode 100644 +index 0000000..03ab476 +--- /dev/null ++++ b/environments/shim/include/lib/libc/util.h +@@ -0,0 +1,165 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ */ ++#ifndef UTIL_H ++#define UTIL_H ++ ++#include ++#include ++ ++#define SIZE_4K UINTPTR_C(0x1000) ++#define SIZE_1M UINTPTR_C(0x100000) ++#define SIZE_2M UINTPTR_C(0x200000) ++#define SIZE_4M UINTPTR_C(0x400000) ++#define SIZE_8M UINTPTR_C(0x800000) ++#define SIZE_2G UINTPTR_C(0x80000000) ++ ++#ifndef MAX ++#ifndef __ASSEMBLER__ ++#define MAX(a, b) \ ++ (__extension__({ __typeof__(a) _a = (a); \ ++ __typeof__(b) _b = (b); \ ++ _a > _b ? _a : _b; })) ++ ++#define MIN(a, b) \ ++ (__extension__({ __typeof__(a) _a = (a); \ ++ __typeof__(b) _b = (b); \ ++ _a < _b ? _a : _b; })) ++#else ++#define MAX(a, b) (((a) > (b)) ? (a) : (b)) ++#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ++#endif ++#endif ++ ++/* ++ * In some particular conditions MAX and MIN macros fail to ++ * build from C source file implmentation. In such case one ++ * need to use MAX_UNSAFE/MIN_UNSAFE instead. ++ */ ++#define MAX_UNSAFE(a, b) (((a) > (b)) ? (a) : (b)) ++#define MIN_UNSAFE(a, b) (((a) < (b)) ? (a) : (b)) ++ ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++#ifndef __ASSEMBLER__ ++/* Round up the even multiple of size, size has to be a multiple of 2 */ ++#define ROUNDUP(v, size) (((v) + ((__typeof__(v))(size) - 1)) & \ ++ ~((__typeof__(v))(size) - 1)) ++ ++#define ROUNDUP_OVERFLOW(v, size, res) (__extension__({ \ ++ typeof(*(res)) __roundup_tmp = 0; \ ++ typeof(v) __roundup_mask = (typeof(v))(size) - 1; \ ++ \ ++ ADD_OVERFLOW((v), __roundup_mask, &__roundup_tmp) ? 1 : \ ++ (void)(*(res) = __roundup_tmp & ~__roundup_mask), 0; \ ++})) ++ ++/* ++ * Rounds up to the nearest multiple of y and then divides by y. Safe ++ * against overflow, y has to be a multiple of 2. ++ * ++ * This macro is intended to be used to convert from "number of bytes" to ++ * "number of pages" or similar units. Example: ++ * num_pages = ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE); ++ */ ++#define ROUNDUP_DIV(x, y) (__extension__({ \ ++ typeof(x) __roundup_x = (x); \ ++ typeof(y) __roundup_mask = (typeof(x))(y) - 1; \ ++ \ ++ (__roundup_x / (y)) + (__roundup_x & __roundup_mask ? 1 : 0); \ ++})) ++ ++/* Round down the even multiple of size, size has to be a multiple of 2 */ ++#define ROUNDDOWN(v, size) ((v) & ~((__typeof__(v))(size) - 1)) ++ ++/* Unsigned integer division with nearest rounding variant */ ++#define UDIV_ROUND_NEAREST(x, y) \ ++ (__extension__ ({ __typeof__(x) _x = (x); \ ++ __typeof__(y) _y = (y); \ ++ (_x + (_y / 2)) / _y; })) ++#else ++#define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) ++#define ROUNDDOWN(x, y) (((x) / (y)) * (y)) ++#define UDIV_ROUND_NEAREST(x, y) (((x) + ((y) / 2)) / (y)) ++#endif ++ ++/* x has to be of an unsigned type */ ++#define IS_POWER_OF_TWO(x) (((x) != 0) && (((x) & (~(x) + 1)) == (x))) ++ ++#define ALIGNMENT_IS_OK(p, type) \ ++ (((uintptr_t)(p) & (__alignof__(type) - 1)) == 0) ++ ++#define TO_STR(x) _TO_STR(x) ++#define _TO_STR(x) #x ++ ++#define CONCAT(x, y) _CONCAT(x, y) ++#define _CONCAT(x, y) x##y ++ ++#define container_of(ptr, type, member) \ ++ (__extension__({ \ ++ const typeof(((type *)0)->member) *__ptr = (ptr); \ ++ (type *)((unsigned long)(__ptr) - offsetof(type, member)); \ ++ })) ++ ++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) ++ ++#ifdef __ASSEMBLER__ ++#define BIT32(nr) (1 << (nr)) ++#define BIT64(nr) (1 << (nr)) ++#define SHIFT_U32(v, shift) ((v) << (shift)) ++#define SHIFT_U64(v, shift) ((v) << (shift)) ++#else ++#define BIT32(nr) (UINT32_C(1) << (nr)) ++#define BIT64(nr) (UINT64_C(1) << (nr)) ++#define SHIFT_U32(v, shift) ((uint32_t)(v) << (shift)) ++#define SHIFT_U64(v, shift) ((uint64_t)(v) << (shift)) ++#endif ++#define BIT(nr) BIT32(nr) ++ ++/* ++ * Create a contiguous bitmask starting at bit position @l and ending at ++ * position @h. For example ++ * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. ++ */ ++#define GENMASK_32(h, l) \ ++ (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) ++ ++#define GENMASK_64(h, l) \ ++ (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) ++ ++/* ++ * Checking overflow for addition, subtraction and multiplication. Result ++ * of operation is stored in res which is a pointer to some kind of ++ * integer. ++ * ++ * The macros return true if an overflow occurred and *res is undefined. ++ */ ++#define ADD_OVERFLOW(a, b, res) __compiler_add_overflow((a), (b), (res)) ++#define SUB_OVERFLOW(a, b, res) __compiler_sub_overflow((a), (b), (res)) ++#define MUL_OVERFLOW(a, b, res) __compiler_mul_overflow((a), (b), (res)) ++ ++/* Return a signed +1, 0 or -1 value based on data comparison */ ++#define CMP_TRILEAN(a, b) \ ++ (__extension__({ \ ++ __typeof__(a) _a = (a); \ ++ __typeof__(b) _b = (b); \ ++ \ ++ _a > _b ? 1 : _a < _b ? -1 : 0; \ ++ })) ++ ++#ifndef __ASSEMBLER__ ++static inline uint64_t reg_pair_to_64(uint32_t reg0, uint32_t reg1) ++{ ++ return (uint64_t)reg0 << 32 | reg1; ++} ++ ++static inline void reg_pair_from_64(uint64_t val, uint32_t *reg0, ++ uint32_t *reg1) ++{ ++ *reg0 = val >> 32; ++ *reg1 = val; ++} ++#endif ++ ++#endif /*UTIL_H*/ +diff --git a/environments/shim/include/lib/libc/uuid.h b/environments/shim/include/lib/libc/uuid.h +new file mode 100644 +index 0000000..3a1699b +--- /dev/null ++++ b/environments/shim/include/lib/libc/uuid.h +@@ -0,0 +1,56 @@ ++/*- ++ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD ++ * ++ * Copyright (c) 2002 Marcel Moolenaar ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * $FreeBSD$ ++ */ ++ ++/* ++ * Portions copyright (c) 2014-2020, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#ifndef _SYS_UUID_H_ ++#define _SYS_UUID_H_ ++ ++#include ++#include ++ ++/* Length of a node address (an IEEE 802 address). */ ++#define _UUID_NODE_LEN 6 ++ ++struct uuid { ++ uint8_t time_low[4]; ++ uint8_t time_mid[2]; ++ uint8_t time_hi_and_version[2]; ++ uint8_t clock_seq_hi_and_reserved; ++ uint8_t clock_seq_low; ++ uint8_t node[_UUID_NODE_LEN]; ++}; ++ ++typedef struct uuid uuid_t; ++ ++#endif /* _SYS_UUID_H_ */ +diff --git a/environments/shim/include/lib/mmio.h b/environments/shim/include/lib/mmio.h +new file mode 100644 +index 0000000..e8a7df0 +--- /dev/null ++++ b/environments/shim/include/lib/mmio.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __MMIO_H__ ++#define __MMIO_H__ ++ ++#include ++ ++static inline void mmio_write_8(uintptr_t addr, uint8_t value) ++{ ++ *(volatile uint8_t*)addr = value; ++} ++ ++static inline uint8_t mmio_read_8(uintptr_t addr) ++{ ++ return *(volatile uint8_t*)addr; ++} ++ ++static inline void mmio_write_32(uintptr_t addr, uint32_t value) ++{ ++ *(volatile uint32_t*)addr = value; ++} ++ ++static inline uint32_t mmio_read_32(uintptr_t addr) ++{ ++ return *(volatile uint32_t*)addr; ++} ++ ++static inline void mmio_write_64(uintptr_t addr, uint64_t value) ++{ ++ *(volatile uint64_t*)addr = value; ++} ++ ++static inline uint64_t mmio_read_64(uintptr_t addr) ++{ ++ return *(volatile uint64_t*)addr; ++} ++ ++#endif /* __MMIO_H__ */ +diff --git a/environments/shim/include/lib/spinlock.h b/environments/shim/include/lib/spinlock.h +new file mode 100644 +index 0000000..27ea730 +--- /dev/null ++++ b/environments/shim/include/lib/spinlock.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __SPINLOCK_H__ ++#define __SPINLOCK_H__ ++ ++typedef struct spinlock { ++ volatile unsigned int lock; ++} spinlock_t; ++ ++void init_spinlock(spinlock_t *lock); ++void spin_lock(spinlock_t *lock); ++void spin_unlock(spinlock_t *lock); ++ ++#endif /* __SPINLOCK_H__ */ +diff --git a/environments/shim/include/lib/status.h b/environments/shim/include/lib/status.h +new file mode 100644 +index 0000000..8cb6145 +--- /dev/null ++++ b/environments/shim/include/lib/status.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __STATUS_H__ ++#define __STATUS_H__ ++ ++/* Status Code definitions */ ++#define STATUS_SUCCESS 0x00 ++#define STATUS_INVALID_PARAMETER 0x01 ++#define STATUS_UNSUPPORTED 0x02 ++#define STATUS_OUT_OF_RESOURCES 0x03 ++#define STATUS_NOT_FOUND 0x04 ++#define STATUS_ABORTED 0x05 ++#define STATUS_LOAD_ERROR 0x06 ++#define STATUS_NEVER_RETURN 0x07 ++#define STATUS_BUSY 0x08 ++#define STATUS_NOT_INIT 0x09 ++#define STATUS_BUFFER_TOO_SMALL 0x0A ++#define STATUS_COMPROMISED_DATA 0x0B ++#define STATUS_ALREADY_LOADED 0x0C ++#define STATUS_FAIL 0x0D ++ ++typedef unsigned int STATUS; ++ ++#endif /* __STATUS_H__ */ +diff --git a/environments/shim/include/lib/tftf_lib.h b/environments/shim/include/lib/tftf_lib.h +new file mode 100644 +index 0000000..f9d1a6e +--- /dev/null ++++ b/environments/shim/include/lib/tftf_lib.h +@@ -0,0 +1,236 @@ ++/* ++ * Copyright (c) 2018-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __TFTF_LIB_H__ ++#define __TFTF_LIB_H__ ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * Possible error codes for signaling the result of a test ++ * TEST_RESULT_MIN and TEST_RESULT_MAX are only used as bounds in the enum. ++ */ ++typedef enum { ++ /* ++ * NA = Not applicable. ++ * Initial value for a test result. ++ * Used for CPUs that don't participate in the test. ++ */ ++ TEST_RESULT_NA = -1, ++ ++ TEST_RESULT_MIN = 0, ++ TEST_RESULT_SKIPPED = TEST_RESULT_MIN, ++ TEST_RESULT_SUCCESS, ++ TEST_RESULT_FAIL, ++ TEST_RESULT_CRASHED, ++ ++ TEST_RESULT_MAX ++} test_result_t; ++ ++#define TEST_RESULT_IS_VALID(result) \ ++ ((result >= TEST_RESULT_MIN) && (result < TEST_RESULT_MAX)) ++ ++/* ++ * PSCI Function Wrappers ++ * ++ * SMC calls to PSCI functions ++ */ ++int32_t tftf_psci_cpu_on(u_register_t target_cpu, ++ uintptr_t entry_point_address, ++ u_register_t context_id); ++int32_t tftf_psci_cpu_off(void); ++int32_t tftf_psci_affinity_info(u_register_t target_affinity, ++ uint32_t lowest_affinity_level); ++int32_t tftf_psci_node_hw_state(u_register_t target_cpu, uint32_t power_level); ++int32_t tftf_get_psci_feature_info(uint32_t psci_func_id); ++u_register_t tftf_psci_stat_count(u_register_t target_cpu, ++ uint32_t power_state); ++u_register_t tftf_psci_stat_residency(u_register_t target_cpu, ++ uint32_t power_state); ++ ++/* ++ * PSCI Helper functions ++ */ ++ ++/* ++ * Gets the context ID used when calling tftf_psci_cpu_on(). ++ */ ++u_register_t tftf_get_cpu_on_ctx_id(unsigned int core_pos); ++ ++/* ++ * Sets the context ID used when calling tftf_psci_cpu_on(). ++ */ ++void tftf_set_cpu_on_ctx_id(unsigned int core_pos, u_register_t context_id); ++ ++/* ++ * Gets the PSCI version of Trusted Firmware-A. The version number returned ++ * is a 32-bit unsigned integer, with the upper 16 bits denoting the major ++ * revision, and the lower 16 bits denoting the minor revision. ++ */ ++unsigned int tftf_get_psci_version(void); ++ ++/* ++ * Returns 0 if version is not a valid PSCI version supported by TFTF. ++ * Otherwise it returns a value different of 0. ++ */ ++int tftf_is_valid_psci_version(unsigned int version); ++ ++ ++/* ++ * The function constructs a composite state_id up-to the specified ++ * affinity level querying the relevant state property from the platform. ++ * It chooses the first matching state property from the array returned ++ * by platform. In case the requested affinity level is not supported by ++ * the platform, then this function uses DUMMY_STATE_ID as the local state ++ * for that level. This allows the tests to construct composite state-id ++ * for invalid affinity levels as well. It returns the expected return ++ * value from CPU SUSPEND call. ++ */ ++int tftf_psci_make_composite_state_id(uint32_t affinity_level, ++ uint32_t state_type, uint32_t *state_id); ++ ++/* ++ * This function composes the power state parameter in the right format ++ * needed by PSCI. The detection of the power state format is done during ++ * cold boot by tftf_detect_psci_pstate_format() function. ++ */ ++uint32_t tftf_make_psci_pstate(uint32_t affinity_level, ++ uint32_t state_type, ++ uint32_t state_id); ++ ++/* ++ * Returns 1, if the EL3 software supports PSCI's original format state ID as ++ * NULL else returns zero ++ */ ++unsigned int tftf_is_psci_state_id_null(void); ++ ++/* ++ * Returns 1, if the EL3 software supports PSCI's original state format else ++ * returns zero ++ */ ++unsigned int tftf_is_psci_pstate_format_original(void); ++ ++/* Functions to wait for a specified number of ms or us */ ++void waitms(uint64_t ms); ++void waitus(uint64_t us); ++ ++/* ++ * SMC calls take a function identifier and up to 7 arguments. ++ * Additionally, few SMC calls that originate from EL2 leverage the seventh ++ * argument explicitly. Given that TFTF runs in EL2, we need to be able to ++ * specify it. ++ */ ++typedef struct { ++ /* Function identifier. Identifies which function is being invoked. */ ++ uint32_t fid; ++ ++ u_register_t arg1; ++ u_register_t arg2; ++ u_register_t arg3; ++ u_register_t arg4; ++ u_register_t arg5; ++ u_register_t arg6; ++ u_register_t arg7; ++} smc_args; ++ ++/* SMC calls can return up to 8 register values */ ++typedef struct { ++ u_register_t ret0; ++ u_register_t ret1; ++ u_register_t ret2; ++ u_register_t ret3; ++ u_register_t ret4; ++ u_register_t ret5; ++ u_register_t ret6; ++ u_register_t ret7; ++} smc_ret_values; ++ ++/* ++ * Trigger an SMC call. ++ */ ++smc_ret_values tftf_smc(const smc_args *args); ++ ++/* ++ * Trigger an HVC call. ++ */ ++typedef smc_args hvc_args; ++ ++typedef smc_ret_values hvc_ret_values; ++ ++hvc_ret_values tftf_hvc(const hvc_args *args); ++ ++/* ++ * Write a formatted string in the test output buffer. ++ * Just like the standard libc's printf() function, the string produced is under ++ * the control of a format string that specifies how subsequent arguments are ++ * converted. ++ * ++ * The string will appear in the test report. ++ * Use mp_printf() instead for volatile debug messages that are not meant to be ++ * stored into the test report. ++ * Note: The test output buffer referred here is a temporary buffer stored in ++ * RAM. This function doesn't write anything into NVM. ++ * ++ * Upon successful return, return the number of characters printed (not ++ * including the final '\0' character). If an output error is encountered, ++ * a negative value is returned. If the function is not able to print any ++ * character at all, this is considered as an output error. Note that a partial ++ * write (i.e. when the string is truncated) is not considered as an output ++ * error. ++ */ ++__attribute__((format(printf, 1, 2))) ++int tftf_testcase_printf(const char *format, ...); ++ ++/* ++ * This function is meant to be used by tests. ++ * It tells the framework that the test is going to reset the platform. ++ * ++ * It the test omits to call this function before resetting, the framework will ++ * consider the test has crashed upon resumption. ++ */ ++void tftf_notify_reboot(void); ++ ++/* ++ * Returns 0 if the test function is executed for the first time, ++ * or 1 if the test rebooted the platform and the test function is being ++ * executed again. ++ * This function is used for tests that reboot the platform, so that they can ++ * execute different code paths on 1st execution and subsequent executions. ++ */ ++unsigned int tftf_is_rebooted(void); ++ ++static inline unsigned int make_mpid(unsigned int clusterid, ++#if PLAT_MAX_PE_PER_CPU > 1 ++ unsigned int coreid, ++ unsigned int threadid) ++#else ++ unsigned int coreid) ++#endif ++{ ++ /* ++ * If MT bit is set then need to shift the affinities and also set the ++ * MT bit. ++ */ ++ if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0) ++ return MPIDR_MT_MASK | ++#if PLAT_MAX_PE_PER_CPU > 1 ++ ((threadid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT) | ++#endif ++ ((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT) | ++ ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF2_SHIFT); ++ else ++ return ((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT) | ++ ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT); ++ ++} ++ ++#endif /* __ASSEMBLY__ */ ++#endif /* __TFTF_LIB_H__ */ +diff --git a/environments/shim/include/lib/utils_def.h b/environments/shim/include/lib/utils_def.h +new file mode 100644 +index 0000000..78d4131 +--- /dev/null ++++ b/environments/shim/include/lib/utils_def.h +@@ -0,0 +1,165 @@ ++/* ++ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef UTILS_DEF_H ++#define UTILS_DEF_H ++ ++/* Compute the number of elements in the given array */ ++#define ARRAY_SIZE(a) \ ++ (sizeof(a) / sizeof((a)[0])) ++ ++#define IS_POWER_OF_TWO(x) \ ++ (((x) & ((x) - 1)) == 0) ++ ++#define SIZE_FROM_LOG2_WORDS(n) (4 << (n)) ++ ++#define BIT_32(nr) (U(1) << (nr)) ++#define BIT_64(nr) (ULL(1) << (nr)) ++ ++#ifndef __aarch64__ ++#define BIT BIT_32 ++#else ++#define BIT BIT_64 ++#endif ++ ++/* ++ * Create a contiguous bitmask starting at bit position @l and ending at ++ * position @h. For example ++ * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. ++ */ ++#if defined(__LINKER__) || defined(__ASSEMBLY__) ++#define GENMASK_32(h, l) \ ++ (((0xFFFFFFFF) << (l)) & (0xFFFFFFFF >> (32 - 1 - (h)))) ++ ++#define GENMASK_64(h, l) \ ++ ((~0 << (l)) & (~0 >> (64 - 1 - (h)))) ++#else ++#define GENMASK_32(h, l) \ ++ (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) ++ ++#define GENMASK_64(h, l) \ ++ (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) ++#endif ++ ++#ifndef __aarch64__ ++#define GENMASK GENMASK_32 ++#else ++#define GENMASK GENMASK_64 ++#endif ++ ++/* ++ * This variant of div_round_up can be used in macro definition but should not ++ * be used in C code as the `div` parameter is evaluated twice. ++ */ ++#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d)) ++ ++#define div_round_up(val, div) __extension__ ({ \ ++ __typeof__(div) _div = (div); \ ++ ((val) + _div - (__typeof__(div)) 1) / _div; \ ++}) ++ ++#define MIN(x, y) __extension__ ({ \ ++ __typeof__(x) _x = (x); \ ++ __typeof__(y) _y = (y); \ ++ (void)(&_x == &_y); \ ++ _x < _y ? _x : _y; \ ++}) ++ ++#define MAX(x, y) __extension__ ({ \ ++ __typeof__(x) _x = (x); \ ++ __typeof__(y) _y = (y); \ ++ (void)(&_x == &_y); \ ++ _x > _y ? _x : _y; \ ++}) ++ ++/* ++ * The round_up() macro rounds up a value to the given boundary in a ++ * type-agnostic yet type-safe manner. The boundary must be a power of two. ++ * In other words, it computes the smallest multiple of boundary which is ++ * greater than or equal to value. ++ * ++ * round_down() is similar but rounds the value down instead. ++ */ ++#define round_boundary(value, boundary) \ ++ ((__typeof__(value))((boundary) - 1)) ++ ++#define round_up(value, boundary) \ ++ ((((value) - 1) | round_boundary(value, boundary)) + 1) ++ ++#define round_down(value, boundary) \ ++ ((value) & ~round_boundary(value, boundary)) ++ ++/* ++ * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. ++ * Both arguments must be unsigned pointer values (i.e. uintptr_t). ++ */ ++#define check_uptr_overflow(_ptr, _inc) \ ++ ((_ptr) > (UINTPTR_MAX - (_inc))) ++ ++/* ++ * Evaluates to 1 if (u32 + inc) overflows, 0 otherwise. ++ * Both arguments must be 32-bit unsigned integers (i.e. effectively uint32_t). ++ */ ++#define check_u32_overflow(_u32, _inc) \ ++ ((_u32) > (UINT32_MAX - (_inc))) ++ ++/* ++ * For those constants to be shared between C and other sources, apply a 'U', ++ * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid ++ * undefined or unintended behaviour. ++ * ++ * The GNU assembler and linker do not support these suffixes (it causes the ++ * build process to fail) therefore the suffix is omitted when used in linker ++ * scripts and assembler files. ++*/ ++#if defined(__LINKER__) || defined(__ASSEMBLY__) ++# define U(_x) (_x) ++# define UL(_x) (_x) ++# define ULL(_x) (_x) ++# define L(_x) (_x) ++# define LL(_x) (_x) ++#else ++# define U(_x) (_x##U) ++# define UL(_x) (_x##UL) ++# define ULL(_x) (_x##ULL) ++# define L(_x) (_x##L) ++# define LL(_x) (_x##LL) ++#endif ++ ++/* Register size of the current architecture. */ ++#ifndef __aarch64__ ++#define REGSZ U(4) ++#else ++#define REGSZ U(8) ++#endif ++ ++/* ++ * Test for the current architecture version to be at least the version ++ * expected. ++ */ ++#define ARM_ARCH_AT_LEAST(_maj, _min) \ ++ ((ARM_ARCH_MAJOR > (_maj)) || \ ++ ((ARM_ARCH_MAJOR == (_maj)) && (ARM_ARCH_MINOR >= (_min)))) ++ ++/* ++ * Import an assembly or linker symbol as a C expression with the specified ++ * type ++ */ ++#define IMPORT_SYM(type, sym, name) \ ++ extern char sym[];\ ++ static const __attribute__((unused)) type name = (type) sym; ++ ++/* ++ * When the symbol is used to hold a pointer, its alignment can be asserted ++ * with this macro. For example, if there is a linker symbol that is going to ++ * be used as a 64-bit pointer, the value of the linker symbol must also be ++ * aligned to 64 bit. This macro makes sure this is the case. ++ */ ++#define ASSERT_SYM_PTR_ALIGN(sym) assert(((size_t)(sym) % __alignof__(*(sym))) == 0) ++ ++#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory") ++ ++#endif /* UTILS_DEF_H */ +diff --git a/environments/shim/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/environments/shim/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h +new file mode 100644 +index 0000000..8c29d00 +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_TABLES_AARCH64_H ++#define XLAT_TABLES_AARCH64_H ++ ++#include ++#include ++#include ++ ++#if !defined(PAGE_SIZE) ++#error "PAGE_SIZE is not defined." ++#endif ++ ++/* ++ * Encode a Physical Address Space size for its use in TCR_ELx. ++ */ ++unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr); ++ ++/* ++ * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page ++ * granularity. For 4KB granularity, a level 0 table descriptor doesn't support ++ * block translation. For 16KB, the same thing happens to levels 0 and 1. For ++ * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture ++ * Reference Manual (DDI 0487A.k) for more information. ++ * ++ * The define below specifies the first table level that allows block ++ * descriptors. ++ */ ++#if PAGE_SIZE == PAGE_SIZE_4KB ++# define MIN_LVL_BLOCK_DESC U(1) ++#elif (PAGE_SIZE == PAGE_SIZE_16KB) || (PAGE_SIZE == PAGE_SIZE_64KB) ++# define MIN_LVL_BLOCK_DESC U(2) ++#endif ++ ++#define XLAT_TABLE_LEVEL_MIN U(0) ++ ++/* ++ * Define the architectural limits of the virtual address space in AArch64 ++ * state. ++ * ++ * TCR.TxSZ is calculated as 64 minus the width of said address space. ++ * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2], ++ * depending on Small Translation Table Support which means that ++ * the virtual address space width must be in the range 48 to 25 or 16 bits. ++ * ++ * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more ++ * information: ++ * Page 1730: 'Input address size', 'For all translation stages'. ++ * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual ++ * (DDI 0487D.a) ++ */ ++/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */ ++#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MAX)) ++ ++/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */ ++#define MIN_VIRT_ADDR_SPACE_SIZE_TTST \ ++ (ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST)) ++#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MIN)) ++ ++/* ++ * Here we calculate the initial lookup level from the value of the given ++ * virtual address space size. For a 4 KB page size, ++ * - level 0 supports virtual address spaces of widths 48 to 40 bits; ++ * - level 1 from 39 to 31; ++ * - level 2 from 30 to 22. ++ * - level 3 from 21 to 16. ++ * ++ * Small Translation Table (Armv8.4-TTST) support allows the starting level ++ * of the translation table from 3 for 4KB granularity. See section 12.2.55 in ++ * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below ++ * wider or narrower address spaces are not supported. As a result, level 3 ++ * cannot be used as initial lookup level with 4 KB granularity. See section ++ * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more ++ * information. ++ * ++ * For example, for a 35-bit address space (i.e. virt_addr_space_size == ++ * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table ++ * D4-11 in the ARM ARM, the initial lookup level for an address space like that ++ * is 1. ++ * ++ * Note that this macro assumes that the given virtual address space size is ++ * valid. ++ */ ++#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ ++ (((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT)) \ ++ ? 0U \ ++ : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \ ++ ? 1U \ ++ : (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT)) \ ++ ? 2U : 3U))) ++ ++#endif /* XLAT_TABLES_AARCH64_H */ +diff --git a/environments/shim/include/lib/xlat_tables/xlat_mmu_helpers.h b/environments/shim/include/lib/xlat_tables/xlat_mmu_helpers.h +new file mode 100644 +index 0000000..15ab2ef +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/xlat_mmu_helpers.h +@@ -0,0 +1,91 @@ ++/* ++ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_MMU_HELPERS_H ++#define XLAT_MMU_HELPERS_H ++ ++/* ++ * The following flags are passed to enable_mmu_xxx() to override the default ++ * values used to program system registers while enabling the MMU. ++ */ ++ ++/* ++ * When this flag is used, all data access to Normal memory from this EL and all ++ * Normal memory accesses to the translation tables of this EL are non-cacheable ++ * for all levels of data and unified cache until the caches are enabled by ++ * setting the bit SCTLR_ELx.C. ++ */ ++#define DISABLE_DCACHE (U(1) << 0) ++ ++/* ++ * Mark the translation tables as non-cacheable for the MMU table walker, which ++ * is a different observer from the PE/CPU. If the flag is not specified, the ++ * tables are cacheable for the MMU table walker. ++ * ++ * Note that, as far as the PE/CPU observer is concerned, the attributes used ++ * are the ones specified in the translation tables themselves. The MAIR ++ * register specifies the cacheability through the field AttrIndx of the lower ++ * attributes of the translation tables. The shareability is specified in the SH ++ * field of the lower attributes. ++ * ++ * The MMU table walker uses the attributes specified in the fields ORGNn, IRGNn ++ * and SHn of the TCR register to access the translation tables. ++ * ++ * The attributes specified in the TCR register and the tables can be different ++ * as there are no checks to prevent that. Special care must be taken to ensure ++ * that there aren't mismatches. The behaviour in that case is described in the ++ * sections 'Mismatched memory attributes' in the ARMv8 ARM. ++ */ ++#define XLAT_TABLE_NC (U(1) << 1) ++ ++/* ++ * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All ++ * parameters are 64 bits wide. ++ */ ++#define MMU_CFG_MAIR 0 ++#define MMU_CFG_TCR 1 ++#define MMU_CFG_TTBR0 2 ++#define MMU_CFG_PARAM_MAX 3 ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++#include ++#include ++ ++/* ++ * Return the values that the MMU configuration registers must contain for the ++ * specified translation context. `params` must be a pointer to array of size ++ * MMU_CFG_PARAM_MAX. ++ */ ++void setup_mmu_cfg(uint64_t *params, unsigned int flags, ++ const uint64_t *base_table, unsigned long long max_pa, ++ uintptr_t max_va, int xlat_regime); ++ ++#ifndef __aarch64__ ++/* AArch32 specific translation table API */ ++void enable_mmu_svc_mon(unsigned int flags); ++void enable_mmu_hyp(unsigned int flags); ++ ++void enable_mmu_direct_svc_mon(unsigned int flags); ++void enable_mmu_direct_hyp(unsigned int flags); ++#else ++/* AArch64 specific translation table APIs */ ++void enable_mmu_el1(unsigned int flags); ++void enable_mmu_el2(unsigned int flags); ++void enable_mmu_el3(unsigned int flags); ++ ++void enable_mmu_direct_el1(unsigned int flags); ++void enable_mmu_direct_el2(unsigned int flags); ++void enable_mmu_direct_el3(unsigned int flags); ++#endif /* !__aarch64__ */ ++ ++bool xlat_arch_is_granule_size_supported(size_t size); ++size_t xlat_arch_get_max_supported_granule_size(void); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* XLAT_MMU_HELPERS_H */ +diff --git a/environments/shim/include/lib/xlat_tables/xlat_tables_arch.h b/environments/shim/include/lib/xlat_tables/xlat_tables_arch.h +new file mode 100644 +index 0000000..c8f29e4 +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/xlat_tables_arch.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_TABLES_ARCH_H ++#define XLAT_TABLES_ARCH_H ++ ++#ifndef __aarch64__ ++#include "aarch32/xlat_tables_aarch32.h" ++#else ++#include "aarch64/xlat_tables_aarch64.h" ++#endif ++ ++/* ++ * Evaluates to 1 if the given physical address space size is a power of 2, ++ * or 0 if it's not. ++ */ ++#define CHECK_PHY_ADDR_SPACE_SIZE(size) \ ++ (IS_POWER_OF_TWO(size)) ++ ++/* ++ * Compute the number of entries required at the initial lookup level to address ++ * the whole virtual address space. ++ */ ++#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size) \ ++ ((addr_space_size) >> \ ++ XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size))) ++ ++#endif /* XLAT_TABLES_ARCH_H */ +diff --git a/environments/shim/include/lib/xlat_tables/xlat_tables_defs.h b/environments/shim/include/lib/xlat_tables/xlat_tables_defs.h +new file mode 100644 +index 0000000..1fd3c83 +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/xlat_tables_defs.h +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_TABLES_DEFS_H ++#define XLAT_TABLES_DEFS_H ++ ++#include ++#include ++#include ++ ++/* Miscellaneous MMU related constants */ ++#define NUM_2MB_IN_GB (U(1) << 9) ++#define NUM_4K_IN_2MB (U(1) << 9) ++#define NUM_GB_IN_4GB (U(1) << 2) ++ ++#define TWO_MB_SHIFT U(21) ++#define ONE_GB_SHIFT U(30) ++#define FOUR_KB_SHIFT U(12) ++ ++#define ONE_GB_INDEX(x) ((x) >> ONE_GB_SHIFT) ++#define TWO_MB_INDEX(x) ((x) >> TWO_MB_SHIFT) ++#define FOUR_KB_INDEX(x) ((x) >> FOUR_KB_SHIFT) ++ ++#define PAGE_SIZE_4KB U(4096) ++#define PAGE_SIZE_16KB U(16384) ++#define PAGE_SIZE_64KB U(65536) ++ ++#define INVALID_DESC U(0x0) ++/* ++ * A block descriptor points to a region of memory bigger than the granule size ++ * (e.g. a 2MB region when the granule size is 4KB). ++ */ ++#define BLOCK_DESC U(0x1) /* Table levels 0-2 */ ++/* A table descriptor points to the next level of translation table. */ ++#define TABLE_DESC U(0x3) /* Table levels 0-2 */ ++/* ++ * A page descriptor points to a page, i.e. a memory region whose size is the ++ * translation granule size (e.g. 4KB). ++ */ ++#define PAGE_DESC U(0x3) /* Table level 3 */ ++ ++#define DESC_MASK U(0x3) ++ ++#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT ++#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT ++#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT ++ ++/* XN: Translation regimes that support one VA range (EL2 and EL3). */ ++#define XN (ULL(1) << 2) ++/* UXN, PXN: Translation regimes that support two VA ranges (EL1&0). */ ++#define UXN (ULL(1) << 2) ++#define PXN (ULL(1) << 1) ++#define CONT_HINT (ULL(1) << 0) ++#define UPPER_ATTRS(x) (((x) & ULL(0x7)) << 52) ++ ++#define NON_GLOBAL (U(1) << 9) ++#define ACCESS_FLAG (U(1) << 8) ++#define NSH (U(0x0) << 6) ++#define OSH (U(0x2) << 6) ++#define ISH (U(0x3) << 6) ++ ++#ifdef __aarch64__ ++/* Guarded Page bit */ ++#define GP (ULL(1) << 50) ++#endif ++ ++#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000) ++ ++/* ++ * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or ++ * 64KB. However, only 4KB are supported at the moment. ++ */ ++#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT ++#define PAGE_SIZE (U(1) << PAGE_SIZE_SHIFT) ++#define PAGE_SIZE_MASK (PAGE_SIZE - U(1)) ++#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == U(0)) ++ ++#if (ARM_ARCH_MAJOR == 7) && !ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING ++#define XLAT_ENTRY_SIZE_SHIFT U(2) /* Each MMU table entry is 4 bytes */ ++#else ++#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes */ ++#endif ++#define XLAT_ENTRY_SIZE (U(1) << XLAT_ENTRY_SIZE_SHIFT) ++ ++#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT /* Size of one complete table */ ++#define XLAT_TABLE_SIZE (U(1) << XLAT_TABLE_SIZE_SHIFT) ++ ++#define XLAT_TABLE_LEVEL_MAX U(3) ++ ++/* Values for number of entries in each MMU translation table */ ++#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) ++#define XLAT_TABLE_ENTRIES (U(1) << XLAT_TABLE_ENTRIES_SHIFT) ++#define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - U(1)) ++ ++/* Values to convert a memory address to an index into a translation table */ ++#define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT ++#define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) ++#define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) ++#define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) ++#define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ ++ ((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT)) ++ ++#define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) ++/* Mask to get the bits used to index inside a block of a certain level */ ++#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - UL(1)) ++/* Mask to get the address bits common to a block of a certain table level*/ ++#define XLAT_ADDR_MASK(level) (~XLAT_BLOCK_MASK(level)) ++/* ++ * Extract from the given virtual address the index into the given lookup level. ++ * This macro assumes the system is using the 4KB translation granule. ++ */ ++#define XLAT_TABLE_IDX(virtual_addr, level) \ ++ (((virtual_addr) >> XLAT_ADDR_SHIFT(level)) & ULL(0x1FF)) ++ ++/* ++ * The ARMv8 translation table descriptor format defines AP[2:1] as the Access ++ * Permissions bits, and does not define an AP[0] bit. ++ * ++ * AP[1] is valid only for a stage 1 translation that supports two VA ranges ++ * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime). It is RES1 ++ * when stage 1 translations can only support one VA range. ++ */ ++#define AP2_SHIFT U(0x7) ++#define AP2_RO ULL(0x1) ++#define AP2_RW ULL(0x0) ++ ++#define AP1_SHIFT U(0x6) ++#define AP1_ACCESS_UNPRIVILEGED ULL(0x1) ++#define AP1_NO_ACCESS_UNPRIVILEGED ULL(0x0) ++#define AP1_RES1 ULL(0x1) ++ ++/* ++ * The following definitions must all be passed to the LOWER_ATTRS() macro to ++ * get the right bitmask. ++ */ ++#define AP_RO (AP2_RO << 5) ++#define AP_RW (AP2_RW << 5) ++#define AP_ACCESS_UNPRIVILEGED (AP1_ACCESS_UNPRIVILEGED << 4) ++#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4) ++#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4) ++#define NS (U(0x1) << 3) ++#define ATTR_NON_CACHEABLE_INDEX ULL(0x2) ++#define ATTR_DEVICE_INDEX ULL(0x1) ++#define ATTR_IWBWA_OWBWA_NTR_INDEX ULL(0x0) ++#define LOWER_ATTRS(x) (((x) & U(0xfff)) << 2) ++ ++/* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */ ++#define ATTR_NON_CACHEABLE MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC) ++/* Device-nGnRE */ ++#define ATTR_DEVICE MAIR_DEV_nGnRE ++/* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */ ++#define ATTR_IWBWA_OWBWA_NTR MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA) ++#define MAIR_ATTR_SET(attr, index) ((attr) << ((index) << 3)) ++#define ATTR_INDEX_MASK U(0x3) ++#define ATTR_INDEX_GET(attr) (((attr) >> 2) & ATTR_INDEX_MASK) ++ ++/* ++ * Shift values for the attributes fields in a block or page descriptor. ++ * See section D4.3.3 in the ARMv8-A ARM (issue B.a). ++ */ ++ ++/* Memory attributes index field, AttrIndx[2:0]. */ ++#define ATTR_INDEX_SHIFT 2 ++/* Non-secure bit, NS. */ ++#define NS_SHIFT 5 ++/* Shareability field, SH[1:0] */ ++#define SHAREABILITY_SHIFT 8 ++/* The Access Flag, AF. */ ++#define ACCESS_FLAG_SHIFT 10 ++/* The not global bit, nG. */ ++#define NOT_GLOBAL_SHIFT 11 ++/* Contiguous hint bit. */ ++#define CONT_HINT_SHIFT 52 ++/* Execute-never bits, XN. */ ++#define PXN_SHIFT 53 ++#define XN_SHIFT 54 ++#define UXN_SHIFT XN_SHIFT ++ ++#endif /* XLAT_TABLES_DEFS_H */ +diff --git a/environments/shim/include/lib/xlat_tables/xlat_tables_v2.h b/environments/shim/include/lib/xlat_tables/xlat_tables_v2.h +new file mode 100644 +index 0000000..0fe388b +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/xlat_tables_v2.h +@@ -0,0 +1,367 @@ ++/* ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_TABLES_V2_H ++#define XLAT_TABLES_V2_H ++ ++#include ++#include ++ ++#ifndef __ASSEMBLY__ ++#include ++#include ++#include ++ ++/* ++ * Default granularity size for an mmap_region_t. ++ * Useful when no specific granularity is required. ++ * ++ * By default, choose the biggest possible block size allowed by the ++ * architectural state and granule size in order to minimize the number of page ++ * tables required for the mapping. ++ */ ++#define REGION_DEFAULT_GRANULARITY XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC) ++ ++/* Helper macro to define an mmap_region_t. */ ++#define MAP_REGION(_pa, _va, _sz, _attr) \ ++ MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY) ++ ++/* Helper macro to define an mmap_region_t with an identity mapping. */ ++#define MAP_REGION_FLAT(_adr, _sz, _attr) \ ++ MAP_REGION(_adr, _adr, _sz, _attr) ++ ++/* ++ * Helper macro to define entries for mmap_region_t. It allows to define 'pa' ++ * and sets 'va' to 0 for each region. To be used with mmap_add_alloc_va(). ++ */ ++#define MAP_REGION_ALLOC_VA(pa, sz, attr) MAP_REGION(pa, 0, sz, attr) ++ ++/* ++ * Helper macro to define an mmap_region_t to map with the desired granularity ++ * of translation tables. ++ * ++ * The granularity value passed to this macro must be a valid block or page ++ * size. When using a 4KB translation granule, this might be 4KB, 2MB or 1GB. ++ * Passing REGION_DEFAULT_GRANULARITY is also allowed and means that the library ++ * is free to choose the granularity for this region. In this case, it is ++ * equivalent to the MAP_REGION() macro. ++ */ ++#define MAP_REGION2(_pa, _va, _sz, _attr, _gr) \ ++ MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) ++ ++/* ++ * Shifts and masks to access fields of an mmap attribute ++ */ ++#define MT_TYPE_MASK U(0x7) ++#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) ++/* Access permissions (RO/RW) */ ++#define MT_PERM_SHIFT U(3) ++/* Security state (SECURE/NS) */ ++#define MT_SEC_SHIFT U(4) ++/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ ++#define MT_EXECUTE_SHIFT U(5) ++/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */ ++#define MT_USER_SHIFT U(6) ++/* All other bits are reserved */ ++ ++/* ++ * Memory mapping attributes ++ */ ++ ++/* ++ * Memory types supported. ++ * These are organised so that, going down the list, the memory types are ++ * getting weaker; conversely going up the list the memory types are getting ++ * stronger. ++ */ ++#define MT_DEVICE U(0) ++#define MT_NON_CACHEABLE U(1) ++#define MT_MEMORY U(2) ++/* Values up to 7 are reserved to add new memory types in the future */ ++ ++#define MT_RO (U(0) << MT_PERM_SHIFT) ++#define MT_RW (U(1) << MT_PERM_SHIFT) ++ ++#define MT_SECURE (U(0) << MT_SEC_SHIFT) ++#define MT_NS (U(1) << MT_SEC_SHIFT) ++ ++/* ++ * Access permissions for instruction execution are only relevant for normal ++ * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially ++ * overridden) otherwise: ++ * - Device memory is always marked as execute-never. ++ * - Read-write normal memory is always marked as execute-never. ++ */ ++#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) ++#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) ++ ++/* ++ * When mapping a region at EL0 or EL1, this attribute will be used to determine ++ * if a User mapping (EL0) will be created or a Privileged mapping (EL1). ++ */ ++#define MT_USER (U(1) << MT_USER_SHIFT) ++#define MT_PRIVILEGED (U(0) << MT_USER_SHIFT) ++ ++/* Compound attributes for most common usages */ ++#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) ++#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) ++#define MT_RW_DATA (MT_MEMORY | MT_RW | MT_EXECUTE_NEVER) ++ ++/* ++ * Structure for specifying a single region of memory. ++ */ ++typedef struct mmap_region { ++ unsigned long long base_pa; ++ uintptr_t base_va; ++ size_t size; ++ unsigned int attr; ++ /* Desired granularity. See the MAP_REGION2() macro for more details. */ ++ size_t granularity; ++} mmap_region_t; ++ ++/* ++ * Translation regimes supported by this library. EL_REGIME_INVALID tells the ++ * library to detect it at runtime. ++ */ ++#define EL1_EL0_REGIME 1 ++#define EL2_REGIME 2 ++#define EL3_REGIME 3 ++#define EL_REGIME_INVALID -1 ++ ++/* ++ * Declare the translation context type. ++ * Its definition is private. ++ */ ++typedef struct xlat_ctx xlat_ctx_t; ++ ++/* ++ * Statically allocate a translation context and associated structures. Also ++ * initialize them. ++ * ++ * _ctx_name: ++ * Prefix for the translation context variable. ++ * E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'. ++ * Useful to distinguish multiple contexts from one another. ++ * ++ * _mmap_count: ++ * Number of mmap_region_t to allocate. ++ * Would typically be MAX_MMAP_REGIONS for the translation context describing ++ * the software image currently executing. ++ * ++ * _xlat_tables_count: ++ * Number of sub-translation tables to allocate. ++ * Would typically be MAX_XLAT_TABLES for the translation context describing ++ * the software image currently executing. ++ * Note that this is only for sub-tables ; at the initial lookup level, there ++ * is always a single table. ++ * ++ * _virt_addr_space_size, _phy_addr_space_size: ++ * Size (in bytes) of the virtual (resp. physical) address space. ++ * Would typically be PLAT_VIRT_ADDR_SPACE_SIZE ++ * (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the ++ * software image currently executing. ++ */ ++#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \ ++ _virt_addr_space_size, _phy_addr_space_size) \ ++ REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ ++ (_xlat_tables_count), \ ++ (_virt_addr_space_size), \ ++ (_phy_addr_space_size), \ ++ EL_REGIME_INVALID, "xlat_table") ++ ++/* ++ * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: ++ * ++ * _xlat_regime: ++ * Specify the translation regime managed by this xlat_ctx_t instance. The ++ * values are the one from the EL*_REGIME definitions. ++ * ++ * _section_name: ++ * Specify the name of the section where the translation tables have to be ++ * placed by the linker. ++ */ ++#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ ++ _virt_addr_space_size, _phy_addr_space_size, \ ++ _xlat_regime, _section_name) \ ++ REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ ++ (_xlat_tables_count), \ ++ (_virt_addr_space_size), \ ++ (_phy_addr_space_size), \ ++ (_xlat_regime), (_section_name)) ++ ++/****************************************************************************** ++ * Generic translation table APIs. ++ * Each API comes in 2 variants: ++ * - one that acts on the current translation context for this software image ++ * - another that acts on the given translation context instead. This variant ++ * is named after the 1st version, with an additional '_ctx' suffix. ++ *****************************************************************************/ ++ ++/* ++ * Initialize translation tables from the current list of mmap regions. Calling ++ * this function marks the transition point after which static regions can no ++ * longer be added. ++ */ ++void init_xlat_tables(void); ++void init_xlat_tables_ctx(xlat_ctx_t *ctx); ++ ++/* ++ * Fill all fields of a dynamic translation tables context. It must be done ++ * either statically with REGISTER_XLAT_CONTEXT() or at runtime with this ++ * function. ++ */ ++void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, ++ uintptr_t va_max, struct mmap_region *mmap, ++ unsigned int mmap_num, uint64_t **tables, ++ unsigned int tables_num, uint64_t *base_table, ++ int xlat_regime, int *mapped_regions); ++ ++/* ++ * Add a static region with defined base PA and base VA. This function can only ++ * be used before initializing the translation tables. The region cannot be ++ * removed afterwards. ++ */ ++void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, ++ size_t size, unsigned int attr); ++void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); ++ ++/* ++ * Add an array of static regions with defined base PA and base VA. This ++ * function can only be used before initializing the translation tables. The ++ * regions cannot be removed afterwards. ++ */ ++void mmap_add(const mmap_region_t *mm); ++void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); ++ ++/* ++ * Add a region with defined base PA. Returns base VA calculated using the ++ * highest existing region in the mmap array even if it fails to allocate the ++ * region. ++ */ ++void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, ++ size_t size, unsigned int attr); ++void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); ++ ++/* ++ * Add an array of static regions with defined base PA, and fill the base VA ++ * field on the array of structs. This function can only be used before ++ * initializing the translation tables. The regions cannot be removed afterwards. ++ */ ++void mmap_add_alloc_va(mmap_region_t *mm); ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++/* ++ * Add a dynamic region with defined base PA and base VA. This type of region ++ * can be added and removed even after the translation tables are initialized. ++ * ++ * Returns: ++ * 0: Success. ++ * EINVAL: Invalid values were used as arguments. ++ * ERANGE: Memory limits were surpassed. ++ * ENOMEM: Not enough space in the mmap array or not enough free xlat tables. ++ * EPERM: It overlaps another region in an invalid way. ++ */ ++int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, ++ size_t size, unsigned int attr); ++int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); ++ ++/* ++ * Add a dynamic region with defined base PA. Returns base VA calculated using ++ * the highest existing region in the mmap array even if it fails to allocate ++ * the region. ++ * ++ * mmap_add_dynamic_region_alloc_va() returns the allocated VA in 'base_va'. ++ * mmap_add_dynamic_region_alloc_va_ctx() returns it in 'mm->base_va'. ++ * ++ * It returns the same error values as mmap_add_dynamic_region(). ++ */ ++int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, ++ uintptr_t *base_va, ++ size_t size, unsigned int attr); ++int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); ++ ++/* ++ * Remove a region with the specified base VA and size. Only dynamic regions can ++ * be removed, and they can be removed even if the translation tables are ++ * initialized. ++ * ++ * Returns: ++ * 0: Success. ++ * EINVAL: The specified region wasn't found. ++ * EPERM: Trying to remove a static region. ++ */ ++int mmap_remove_dynamic_region(uintptr_t base_va, size_t size); ++int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, ++ uintptr_t base_va, ++ size_t size); ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++/* ++ * Change the memory attributes of the memory region starting from a given ++ * virtual address in a set of translation tables. ++ * ++ * This function can only be used after the translation tables have been ++ * initialized. ++ * ++ * The base address of the memory region must be aligned on a page boundary. ++ * The size of this memory region must be a multiple of a page size. ++ * The memory region must be already mapped by the given translation tables ++ * and it must be mapped at the granularity of a page. ++ * ++ * Return 0 on success, a negative value on error. ++ * ++ * In case of error, the memory attributes remain unchanged and this function ++ * has no effect. ++ * ++ * ctx ++ * Translation context to work on. ++ * base_va: ++ * Virtual address of the 1st page to change the attributes of. ++ * size: ++ * Size in bytes of the memory region. ++ * attr: ++ * New attributes of the page tables. The attributes that can be changed are ++ * data access (MT_RO/MT_RW), instruction access (MT_EXECUTE_NEVER/MT_EXECUTE) ++ * and user/privileged access (MT_USER/MT_PRIVILEGED) in the case of contexts ++ * that are used in the EL1&0 translation regime. Also, note that this ++ * function doesn't allow to remap a region as RW and executable, or to remap ++ * device memory as executable. ++ * ++ * NOTE: The caller of this function must be able to write to the translation ++ * tables, i.e. the memory where they are stored must be mapped with read-write ++ * access permissions. This function assumes it is the case. If this is not ++ * the case then this function might trigger a data abort exception. ++ * ++ * NOTE2: The caller is responsible for making sure that the targeted ++ * translation tables are not modified by any other code while this function is ++ * executing. ++ */ ++int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, ++ size_t size, uint32_t attr); ++int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr); ++ ++/* ++ * Query the memory attributes of a memory page in a set of translation tables. ++ * ++ * Return 0 on success, a negative error code on error. ++ * On success, the attributes are stored into *attr. ++ * ++ * ctx ++ * Translation context to work on. ++ * base_va ++ * Virtual address of the page to get the attributes of. ++ * There are no alignment restrictions on this address. The attributes of the ++ * memory page it lies within are returned. ++ * attr ++ * Output parameter where to store the attributes of the targeted memory page. ++ */ ++int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, ++ uint32_t *attr); ++int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr); ++ ++#endif /*__ASSEMBLY__*/ ++#endif /* XLAT_TABLES_V2_H */ +diff --git a/environments/shim/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/environments/shim/include/lib/xlat_tables/xlat_tables_v2_helpers.h +new file mode 100644 +index 0000000..aa2bd66 +--- /dev/null ++++ b/environments/shim/include/lib/xlat_tables/xlat_tables_v2_helpers.h +@@ -0,0 +1,163 @@ ++/* ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * This header file contains internal definitions that are not supposed to be ++ * used outside of this library code. ++ */ ++ ++#ifndef XLAT_TABLES_V2_HELPERS_H ++#define XLAT_TABLES_V2_HELPERS_H ++ ++#ifndef XLAT_TABLES_V2_H ++#error "Do not include this header file directly. Include xlat_tables_v2.h instead." ++#endif ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Forward declaration */ ++struct mmap_region; ++ ++/* ++ * Helper macro to define an mmap_region_t. This macro allows to specify all ++ * the fields of the structure but its parameter list is not guaranteed to ++ * remain stable as we add members to mmap_region_t. ++ */ ++#define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \ ++ { \ ++ .base_pa = (_pa), \ ++ .base_va = (_va), \ ++ .size = (_sz), \ ++ .attr = (_attr), \ ++ .granularity = (_gr), \ ++ } ++ ++/* Struct that holds all information about the translation tables. */ ++struct xlat_ctx { ++ /* ++ * Max allowed Virtual and Physical Addresses. ++ */ ++ unsigned long long pa_max_address; ++ uintptr_t va_max_address; ++ ++ /* ++ * Array of all memory regions stored in order of ascending end address ++ * and ascending size to simplify the code that allows overlapping ++ * regions. The list is terminated by the first entry with size == 0. ++ * The max size of the list is stored in `mmap_num`. `mmap` points to an ++ * array of mmap_num + 1 elements, so that there is space for the final ++ * null entry. ++ */ ++ struct mmap_region *mmap; ++ int mmap_num; ++ ++ /* ++ * Array of finer-grain translation tables. ++ * For example, if the initial lookup level is 1 then this array would ++ * contain both level-2 and level-3 entries. ++ */ ++ uint64_t (*tables)[XLAT_TABLE_ENTRIES]; ++ int tables_num; ++ /* ++ * Keep track of how many regions are mapped in each table. The base ++ * table can't be unmapped so it isn't needed to keep track of it. ++ */ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ int *tables_mapped_regions; ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++ int next_table; ++ ++ /* ++ * Base translation table. It doesn't need to have the same amount of ++ * entries as the ones used for other levels. ++ */ ++ uint64_t *base_table; ++ unsigned int base_table_entries; ++ ++ /* ++ * Max Physical and Virtual addresses currently in use by the ++ * translation tables. These might get updated as we map/unmap memory ++ * regions but they will never go beyond pa/va_max_address. ++ */ ++ unsigned long long max_pa; ++ uintptr_t max_va; ++ ++ /* Level of the base translation table. */ ++ unsigned int base_level; ++ ++ /* Set to true when the translation tables are initialized. */ ++ bool initialized; ++ ++ /* ++ * Translation regime managed by this xlat_ctx_t. It should be one of ++ * the EL*_REGIME defines. ++ */ ++ int xlat_regime; ++}; ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ ++ static int _ctx_name##_mapped_regions[_xlat_tables_count]; ++ ++#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ ++ .tables_mapped_regions = _ctx_name##_mapped_regions, ++#else ++#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ ++ /* do nothing */ ++ ++#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ ++ /* do nothing */ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ ++ _xlat_tables_count, _virt_addr_space_size, \ ++ _phy_addr_space_size, _xlat_regime, _section_name)\ ++ CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \ ++ assert_invalid_physical_addr_space_sizefor_##_ctx_name);\ ++ \ ++ static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ ++ \ ++ static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ ++ [XLAT_TABLE_ENTRIES] \ ++ __aligned(XLAT_TABLE_SIZE) __section(_section_name); \ ++ \ ++ static uint64_t _ctx_name##_base_xlat_table \ ++ [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ ++ __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\ ++ * sizeof(uint64_t)); \ ++ \ ++ XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ ++ \ ++ static xlat_ctx_t _ctx_name##_xlat_ctx = { \ ++ .va_max_address = (_virt_addr_space_size) - 1UL, \ ++ .pa_max_address = (_phy_addr_space_size) - 1ULL, \ ++ .mmap = _ctx_name##_mmap, \ ++ .mmap_num = (_mmap_count), \ ++ .base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\ ++ .base_table = _ctx_name##_base_xlat_table, \ ++ .base_table_entries = \ ++ GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\ ++ .tables = _ctx_name##_xlat_tables, \ ++ .tables_num = _xlat_tables_count, \ ++ XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ ++ .xlat_regime = (_xlat_regime), \ ++ .max_pa = 0U, \ ++ .max_va = 0U, \ ++ .next_table = 0, \ ++ .initialized = false, \ ++ } ++ ++#endif /*__ASSEMBLY__*/ ++ ++#endif /* XLAT_TABLES_V2_HELPERS_H */ +diff --git a/environments/shim/include/platform_def.h b/environments/shim/include/platform_def.h +new file mode 100644 +index 0000000..a1f09d6 +--- /dev/null ++++ b/environments/shim/include/platform_def.h +@@ -0,0 +1,150 @@ ++/* ++ * Copyright (c) 2020-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++#include ++ ++#ifndef PLATFORM_DEF_H ++#define PLATFORM_DEF_H ++ ++/* Platform binary types for linking */ ++#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" ++#define PLATFORM_LINKER_ARCH aarch64 ++ ++#ifdef SECURE_STORAGE ++#define SP_IMAGE_BASE 0xFEE01000 ++#define SP_IMAGE_SIZE 0x200000 ++#endif ++ ++#ifdef CRYPTO ++#define SP_IMAGE_BASE 0xFEC01000 ++#define SP_IMAGE_SIZE 0x200000 ++#endif ++ ++#define TC0_CLUSTER_COUNT 1 ++#define TC0_MAX_CPUS_PER_CLUSTER 4 ++#define TC0_MAX_PE_PER_CPU 1 ++ ++/******************************************************************************* ++ * Run-time address of the TFTF image. ++ * It has to match the location where the Trusted Firmware-A loads the BL33 ++ * image. ++ ******************************************************************************/ ++#define TFTF_BASE 0xE0000000 ++ ++#define TC0_DRAM1_BASE 0x80000000 ++#define TC0_DRAM1_SIZE 0x80000000 ++#define DRAM_BASE TC0_DRAM1_BASE ++ ++/* ++ * TF-A reserves DRAM space 0xFD000000 - 0xFEFFFFFF for Trusted DRAM ++ * TF-A reserves DRAM space 0xFF000000 - 0xFFFFFFFF for TZC ++ */ ++#define ARM_TZC_DRAM1_SIZE 0x01000000 ++#define ARM_TRUSTED_DRAM1_SIZE 0x02000000 ++ ++#define DRAM_SIZE (TC0_DRAM1_SIZE - \ ++ ARM_TRUSTED_DRAM1_SIZE - \ ++ ARM_TZC_DRAM1_SIZE) ++ ++/* REFCLK CNTControl, Generic Timer. Secure Access only. */ ++#define SYS_CNT_CONTROL_BASE 0x2a430000 ++/* REFCLK CNTRead, Generic Timer. */ ++#define SYS_CNT_READ_BASE 0x2a800000 ++/* AP_REFCLK CNTBase1, Generic Timer. */ ++#define SYS_CNT_BASE1 0x2A830000 ++ ++/* Base address of non-trusted watchdog (SP805) */ ++#define SP805_WDOG_BASE 0x1C0F0000 ++ ++/* Base address and size of external NVM flash */ ++#define FLASH_BASE 0x08000000 ++ ++#define NOR_FLASH_BLOCK_SIZE 0x40000 /* 256KB */ ++#define FLASH_SIZE 0x4000000 /* 64MB */ ++ ++/* ++ * If you want to use DRAM for non-volatile memory then the first 128MB ++ * can be used. However for tests that involve power resets this is not ++ * suitable since the state will be lost. ++ */ ++#define TFTF_NVM_OFFSET 0x0 ++#define TFTF_NVM_SIZE 0x8000000 /* 128 MB */ ++ ++/* Sub-system Peripherals */ ++#define TC0_DEVICE0_BASE 0x21000000 ++#define TC0_DEVICE0_SIZE 0x5f000000 ++ ++/* Following covers Peripherals and PCIe expansion area */ ++#define TC0_DEVICE1_BASE 0x60000000 ++#define TC0_DEVICE1_SIZE 0x20000000 ++ ++/* GIC-600 & interrupt handling related constants */ ++#define TC0_GICD_BASE 0x30000000 ++#define TC0_GICR_BASE 0x30140000 ++#define TC0_GICC_BASE 0x2C000000 ++ ++/* SoC's PL011 UART0 related constants */ ++#define PL011_UART0_BASE 0x7FF70000 ++#define PL011_UART0_CLK_IN_HZ 7372800 ++ ++/* SoC's PL011 UART1 related constants */ ++#define PL011_UART1_BASE 0x7FF80000 ++#define PL011_UART1_CLK_IN_HZ 7372800 ++ ++#define PLAT_ARM_UART_BASE PL011_UART0_BASE ++#define PLAT_ARM_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ ++ ++/* Size of cacheable stacks */ ++#define PLATFORM_STACK_SIZE 0x1400 ++ ++/* Size of coherent stacks */ ++#define PCPU_DV_MEM_STACK_SIZE 0x600 ++ ++#define PLATFORM_CORE_COUNT (TC0_CLUSTER_COUNT * TC0_MAX_CPUS_PER_CLUSTER) ++#define PLATFORM_NUM_AFFS (TC0_CLUSTER_COUNT + PLATFORM_CORE_COUNT) ++#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1 ++ ++#define PLAT_MAX_PWR_LEVEL PLATFORM_MAX_AFFLVL ++#define PLAT_MAX_PWR_STATES_PER_LVL 2 ++ ++/* I/O Storage NOR flash device */ ++#define MAX_IO_DEVICES 1 ++#define MAX_IO_HANDLES 1 ++ ++/* Local state bit width for each level in the state-ID field of power state */ ++#define PLAT_LOCAL_PSTATE_WIDTH 4 ++ ++/* Platform specific page table and MMU setup constants */ ++#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36) ++#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36) ++#define MAX_XLAT_TABLES 5 ++#define MAX_MMAP_REGIONS 16 ++ ++/******************************************************************************* ++ * Used to align variables on the biggest cache line size in the platform. ++ * This is known only to the platform as it might have a combination of ++ * integrated and external caches. ++ ******************************************************************************/ ++#define CACHE_WRITEBACK_SHIFT 6 ++#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) ++ ++/* Non-Secure Software Generated Interupts IDs */ ++#define IRQ_NS_SGI_0 0 ++#define IRQ_NS_SGI_7 7 ++ ++/* AP UART1 interrupt is considered as the maximum SPI */ ++#define PLAT_MAX_SPI_OFFSET_ID 64 ++ ++/* AP_REFCLK Generic Timer, Non-secure. */ ++#define IRQ_CNTPSIRQ1 92 ++ ++/* Per-CPU Hypervisor Timer Interrupt ID */ ++#define IRQ_PCPU_HP_TIMER 26 ++ ++/* Times(in ms) used by test code for completion of different events */ ++#define PLAT_SUSPEND_ENTRY_TIME 15 ++#define PLAT_SUSPEND_ENTRY_EXIT_TIME 30 ++ ++#endif /* PLATFORM_DEF_H */ +diff --git a/environments/shim/include/runtime_services/ffa_helpers.h b/environments/shim/include/runtime_services/ffa_helpers.h +new file mode 100644 +index 0000000..c68a014 +--- /dev/null ++++ b/environments/shim/include/runtime_services/ffa_helpers.h +@@ -0,0 +1,399 @@ ++/* ++ * Copyright (c) 2018-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef FFA_HELPERS_H ++#define FFA_HELPERS_H ++ ++#include ++#include ++#include ++ ++/* This error code must be different to the ones used by FFA */ ++#define FFA_TFTF_ERROR -42 ++ ++/* Hypervisor ID at physical FFA instance */ ++#define HYP_ID (0) ++ ++/* By convention, SP IDs (as opposed to VM IDs) have bit 15 set */ ++#define SP_ID(x) ((x) | (1 << 15)) ++ ++typedef unsigned short ffa_vm_id_t; ++typedef unsigned short ffa_vm_count_t; ++typedef unsigned short ffa_vcpu_count_t; ++typedef uint32_t ffa_int_id_t; ++typedef uint64_t ffa_memory_handle_t; ++/** Flags to indicate properties of receivers during memory region retrieval. */ ++typedef uint8_t ffa_memory_receiver_flags_t; ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++ ++struct mailbox_buffers { ++ const void *recv; ++ void *send; ++}; ++ ++struct ffa_partition_info { ++ /** The ID of the VM the information is about */ ++ ffa_vm_id_t id; ++ /** The number of execution contexts implemented by the partition */ ++ uint16_t exec_context; ++ /** The Partition's properties, e.g. supported messaging methods */ ++ uint32_t properties; ++}; ++ ++enum ffa_data_access { ++ FFA_DATA_ACCESS_NOT_SPECIFIED, ++ FFA_DATA_ACCESS_RO, ++ FFA_DATA_ACCESS_RW, ++ FFA_DATA_ACCESS_RESERVED, ++}; ++ ++enum ffa_instruction_access { ++ FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, ++ FFA_INSTRUCTION_ACCESS_NX, ++ FFA_INSTRUCTION_ACCESS_X, ++ FFA_INSTRUCTION_ACCESS_RESERVED, ++}; ++ ++enum ffa_memory_type { ++ FFA_MEMORY_NOT_SPECIFIED_MEM, ++ FFA_MEMORY_DEVICE_MEM, ++ FFA_MEMORY_NORMAL_MEM, ++}; ++ ++enum ffa_memory_cacheability { ++ FFA_MEMORY_CACHE_RESERVED = 0x0, ++ FFA_MEMORY_CACHE_NON_CACHEABLE = 0x1, ++ FFA_MEMORY_CACHE_RESERVED_1 = 0x2, ++ FFA_MEMORY_CACHE_WRITE_BACK = 0x3, ++ FFA_MEMORY_DEV_NGNRNE = 0x0, ++ FFA_MEMORY_DEV_NGNRE = 0x1, ++ FFA_MEMORY_DEV_NGRE = 0x2, ++ FFA_MEMORY_DEV_GRE = 0x3, ++}; ++ ++enum ffa_memory_shareability { ++ FFA_MEMORY_SHARE_NON_SHAREABLE, ++ FFA_MEMORY_SHARE_RESERVED, ++ FFA_MEMORY_OUTER_SHAREABLE, ++ FFA_MEMORY_INNER_SHAREABLE, ++}; ++ ++typedef uint8_t ffa_memory_access_permissions_t; ++ ++/** ++ * This corresponds to table "Memory region attributes descriptor" of the FF-A ++ * 1.0 specification. ++ */ ++typedef uint8_t ffa_memory_attributes_t; ++ ++#define FFA_DATA_ACCESS_OFFSET (0x0U) ++#define FFA_DATA_ACCESS_MASK ((0x3U) << FFA_DATA_ACCESS_OFFSET) ++ ++#define FFA_INSTRUCTION_ACCESS_OFFSET (0x2U) ++#define FFA_INSTRUCTION_ACCESS_MASK ((0x3U) << FFA_INSTRUCTION_ACCESS_OFFSET) ++ ++#define FFA_MEMORY_TYPE_OFFSET (0x4U) ++#define FFA_MEMORY_TYPE_MASK ((0x3U) << FFA_MEMORY_TYPE_OFFSET) ++ ++#define FFA_MEMORY_CACHEABILITY_OFFSET (0x2U) ++#define FFA_MEMORY_CACHEABILITY_MASK ((0x3U) << FFA_MEMORY_CACHEABILITY_OFFSET) ++ ++#define FFA_MEMORY_SHAREABILITY_OFFSET (0x0U) ++#define FFA_MEMORY_SHAREABILITY_MASK ((0x3U) << FFA_MEMORY_SHAREABILITY_OFFSET) ++ ++#define ATTR_FUNCTION_SET(name, container_type, offset, mask) \ ++ static inline void ffa_set_##name##_attr(container_type *attr, \ ++ const enum ffa_##name perm) \ ++ { \ ++ *attr = (*attr & ~(mask)) | ((perm << offset) & mask); \ ++ } ++ ++#define ATTR_FUNCTION_GET(name, container_type, offset, mask) \ ++ static inline enum ffa_##name ffa_get_##name##_attr( \ ++ container_type attr) \ ++ { \ ++ return (enum ffa_##name)((attr & mask) >> offset); \ ++ } ++ ++ATTR_FUNCTION_SET(data_access, ffa_memory_access_permissions_t, ++ FFA_DATA_ACCESS_OFFSET, FFA_DATA_ACCESS_MASK) ++ATTR_FUNCTION_GET(data_access, ffa_memory_access_permissions_t, ++ FFA_DATA_ACCESS_OFFSET, FFA_DATA_ACCESS_MASK) ++ ++ATTR_FUNCTION_SET(instruction_access, ffa_memory_access_permissions_t, ++ FFA_INSTRUCTION_ACCESS_OFFSET, FFA_INSTRUCTION_ACCESS_MASK) ++ATTR_FUNCTION_GET(instruction_access, ffa_memory_access_permissions_t, ++ FFA_INSTRUCTION_ACCESS_OFFSET, FFA_INSTRUCTION_ACCESS_MASK) ++ ++ATTR_FUNCTION_SET(memory_type, ffa_memory_attributes_t, FFA_MEMORY_TYPE_OFFSET, ++ FFA_MEMORY_TYPE_MASK) ++ATTR_FUNCTION_GET(memory_type, ffa_memory_attributes_t, FFA_MEMORY_TYPE_OFFSET, ++ FFA_MEMORY_TYPE_MASK) ++ ++ATTR_FUNCTION_SET(memory_cacheability, ffa_memory_attributes_t, ++ FFA_MEMORY_CACHEABILITY_OFFSET, FFA_MEMORY_CACHEABILITY_MASK) ++ATTR_FUNCTION_GET(memory_cacheability, ffa_memory_attributes_t, ++ FFA_MEMORY_CACHEABILITY_OFFSET, FFA_MEMORY_CACHEABILITY_MASK) ++ ++ATTR_FUNCTION_SET(memory_shareability, ffa_memory_attributes_t, ++ FFA_MEMORY_SHAREABILITY_OFFSET, FFA_MEMORY_SHAREABILITY_MASK) ++ATTR_FUNCTION_GET(memory_shareability, ffa_memory_attributes_t, ++ FFA_MEMORY_SHAREABILITY_OFFSET, FFA_MEMORY_SHAREABILITY_MASK) ++ ++#define FFA_MEMORY_HANDLE_ALLOCATOR_MASK \ ++ ((ffa_memory_handle_t)(UINT64_C(1) << 63)) ++#define FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR \ ++ ((ffa_memory_handle_t)(UINT64_C(1) << 63)) ++#define FFA_MEMORY_HANDLE_INVALID (~UINT64_C(0)) ++ ++/** ++ * A set of contiguous pages which is part of a memory region. This corresponds ++ * to table "Constituent memory region descriptor" of the FFA 1.0 specification. ++ */ ++struct ffa_memory_region_constituent { ++ /** ++ * The base IPA of the constituent memory region, aligned to 4 kiB page ++ * size granularity. ++ */ ++ void *address; ++ /** The number of 4 kiB pages in the constituent memory region. */ ++ uint32_t page_count; ++ /** Reserved field, must be 0. */ ++ uint32_t reserved; ++}; ++ ++/** ++ * A set of pages comprising a memory region. This corresponds to table ++ * "Composite memory region descriptor" of the FFA 1.0 specification. ++ */ ++struct ffa_composite_memory_region { ++ /** ++ * The total number of 4 kiB pages included in this memory region. This ++ * must be equal to the sum of page counts specified in each ++ * `ffa_memory_region_constituent`. ++ */ ++ uint32_t page_count; ++ /** ++ * The number of constituents (`ffa_memory_region_constituent`) ++ * included in this memory region range. ++ */ ++ uint32_t constituent_count; ++ /** Reserved field, must be 0. */ ++ uint64_t reserved_0; ++ /** An array of `constituent_count` memory region constituents. */ ++ struct ffa_memory_region_constituent constituents[]; ++}; ++ ++/** ++ * This corresponds to table "Memory access permissions descriptor" of the FFA ++ * 1.0 specification. ++ */ ++struct ffa_memory_region_attributes { ++ /** The ID of the VM to which the memory is being given or shared. */ ++ ffa_vm_id_t receiver; ++ /** ++ * The permissions with which the memory region should be mapped in the ++ * receiver's page table. ++ */ ++ ffa_memory_access_permissions_t permissions; ++ /** ++ * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP ++ * for memory regions with multiple borrowers. ++ */ ++ ffa_memory_receiver_flags_t flags; ++}; ++ ++/** Flags to control the behaviour of a memory sharing transaction. */ ++typedef uint32_t ffa_memory_region_flags_t; ++ ++/** ++ * Clear memory region contents after unmapping it from the sender and before ++ * mapping it for any receiver. ++ */ ++#define FFA_MEMORY_REGION_FLAG_CLEAR 0x1U ++ ++/** ++ * Whether the hypervisor may time slice the memory sharing or retrieval ++ * operation. ++ */ ++#define FFA_MEMORY_REGION_FLAG_TIME_SLICE 0x2U ++ ++/** ++ * Whether the hypervisor should clear the memory region after the receiver ++ * relinquishes it or is aborted. ++ */ ++#define FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH 0x4U ++ ++#define FFA_MEMORY_REGION_TRANSACTION_TYPE_MASK ((0x3U) << 3) ++#define FFA_MEMORY_REGION_TRANSACTION_TYPE_UNSPECIFIED ((0x0U) << 3) ++#define FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE ((0x1U) << 3) ++#define FFA_MEMORY_REGION_TRANSACTION_TYPE_LEND ((0x2U) << 3) ++#define FFA_MEMORY_REGION_TRANSACTION_TYPE_DONATE ((0x3U) << 3) ++ ++/** The maximum number of recipients a memory region may be sent to. */ ++#define MAX_MEM_SHARE_RECIPIENTS 1U ++ ++/** ++ * This corresponds to table "Endpoint memory access descriptor" of the FFA 1.0 ++ * specification. ++ */ ++struct ffa_memory_access { ++ struct ffa_memory_region_attributes receiver_permissions; ++ /** ++ * Offset in bytes from the start of the outer `ffa_memory_region` to ++ * an `ffa_composite_memory_region` struct. ++ */ ++ uint32_t composite_memory_region_offset; ++ uint64_t reserved_0; ++}; ++ ++/** ++ * Information about a set of pages which are being shared. This corresponds to ++ * table "Lend, donate or share memory transaction descriptor" of the FFA ++ * 1.0 specification. Note that it is also used for retrieve requests and ++ * responses. ++ */ ++struct ffa_memory_region { ++ /** ++ * The ID of the VM which originally sent the memory region, i.e. the ++ * owner. ++ */ ++ ffa_vm_id_t sender; ++ ffa_memory_attributes_t attributes; ++ /** Reserved field, must be 0. */ ++ uint8_t reserved_0; ++ /** Flags to control behaviour of the transaction. */ ++ ffa_memory_region_flags_t flags; ++ ffa_memory_handle_t handle; ++ /** ++ * An implementation defined value associated with the receiver and the ++ * memory region. ++ */ ++ uint64_t tag; ++ /** Reserved field, must be 0. */ ++ uint32_t reserved_1; ++ /** ++ * The number of `ffa_memory_access` entries included in this ++ * transaction. ++ */ ++ uint32_t receiver_count; ++ /** ++ * An array of `attribute_count` endpoint memory access descriptors. ++ * Each one specifies a memory region offset, an endpoint and the ++ * attributes with which this memory region should be mapped in that ++ * endpoint's page table. ++ */ ++ struct ffa_memory_access receivers[]; ++}; ++ ++/** ++ * Descriptor used for FFA_MEM_RELINQUISH requests. This corresponds to table ++ * "Descriptor to relinquish a memory region" of the FFA 1.0 specification. ++ */ ++struct ffa_mem_relinquish { ++ ffa_memory_handle_t handle; ++ ffa_memory_region_flags_t flags; ++ uint32_t endpoint_count; ++ ffa_vm_id_t endpoints[]; ++}; ++ ++static inline ffa_memory_handle_t ffa_assemble_handle(uint32_t h1, uint32_t h2) ++{ ++ return (uint64_t)h1 | (uint64_t)h2 << 32; ++} ++ ++static inline ffa_memory_handle_t ffa_mem_success_handle(smc_ret_values r) ++{ ++ return ffa_assemble_handle(r.ret2, r.ret3); ++} ++ ++/** ++ * Gets the `ffa_composite_memory_region` for the given receiver from an ++ * `ffa_memory_region`, or NULL if it is not valid. ++ */ ++static inline struct ffa_composite_memory_region * ++ffa_memory_region_get_composite(struct ffa_memory_region *memory_region, ++ uint32_t receiver_index) ++{ ++ uint32_t offset = memory_region->receivers[receiver_index] ++ .composite_memory_region_offset; ++ ++ if (offset == 0) { ++ return NULL; ++ } ++ ++ return (struct ffa_composite_memory_region *)((uint8_t *)memory_region + ++ offset); ++} ++ ++static inline uint32_t ffa_mem_relinquish_init( ++ struct ffa_mem_relinquish *relinquish_request, ++ ffa_memory_handle_t handle, ffa_memory_region_flags_t flags, ++ ffa_vm_id_t sender) ++{ ++ relinquish_request->handle = handle; ++ relinquish_request->flags = flags; ++ relinquish_request->endpoint_count = 1; ++ relinquish_request->endpoints[0] = sender; ++ return sizeof(struct ffa_mem_relinquish) + sizeof(ffa_vm_id_t); ++} ++ ++uint32_t ffa_memory_retrieve_request_init( ++ struct ffa_memory_region *memory_region, ffa_memory_handle_t handle, ++ ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag, ++ ffa_memory_region_flags_t flags, enum ffa_data_access data_access, ++ enum ffa_instruction_access instruction_access, ++ enum ffa_memory_type type, enum ffa_memory_cacheability cacheability, ++ enum ffa_memory_shareability shareability); ++ ++uint32_t ffa_memory_region_init( ++ struct ffa_memory_region *memory_region, size_t memory_region_max_size, ++ ffa_vm_id_t sender, ffa_vm_id_t receiver, ++ const struct ffa_memory_region_constituent constituents[], ++ uint32_t constituent_count, uint32_t tag, ++ ffa_memory_region_flags_t flags, enum ffa_data_access data_access, ++ enum ffa_instruction_access instruction_access, ++ enum ffa_memory_type type, enum ffa_memory_cacheability cacheability, ++ enum ffa_memory_shareability shareability, uint32_t *total_length, ++ uint32_t *fragment_length); ++ ++bool check_spmc_execution_level(void); ++smc_ret_values ffa_msg_send_direct_req(uint32_t source_id, uint32_t dest_id, uint32_t message); ++smc_ret_values ffa_msg_send_direct_req64(uint32_t source_id, uint32_t dest_id, uint64_t message); ++smc_ret_values ffa_msg_send_direct_req64_5args(uint32_t source_id, uint32_t dest_id, ++ uint64_t arg0, uint64_t arg1, ++ uint64_t arg2, uint64_t arg3, ++ uint64_t arg4); ++ ++smc_ret_values ffa_run(uint32_t dest_id, uint32_t vcpu_id); ++smc_ret_values ffa_version(uint32_t input_version); ++smc_ret_values ffa_id_get(void); ++smc_ret_values ffa_msg_wait(void); ++smc_ret_values ffa_msg_send_direct_resp(ffa_vm_id_t source_id, ++ ffa_vm_id_t dest_id, uint32_t message); ++smc_ret_values ffa_error(int32_t error_code); ++smc_ret_values ffa_features(uint32_t feature); ++smc_ret_values ffa_partition_info_get(const uint32_t uuid[4]); ++smc_ret_values ffa_rx_release(void); ++smc_ret_values ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages); ++ ++smc_ret_values ffa_mem_donate(uint32_t descriptor_length, ++ uint32_t fragment_length); ++smc_ret_values ffa_mem_lend(uint32_t descriptor_length, ++ uint32_t fragment_length); ++smc_ret_values ffa_mem_share(uint32_t descriptor_length, ++ uint32_t fragment_length); ++smc_ret_values ffa_mem_retrieve_req(uint32_t descriptor_length, ++ uint32_t fragment_length); ++smc_ret_values ffa_mem_relinquish(void); ++smc_ret_values ffa_mem_reclaim(uint64_t handle, uint32_t flags); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* FFA_HELPERS_H */ +diff --git a/environments/shim/include/runtime_services/ffa_svc.h b/environments/shim/include/runtime_services/ffa_svc.h +new file mode 100644 +index 0000000..f08e803 +--- /dev/null ++++ b/environments/shim/include/runtime_services/ffa_svc.h +@@ -0,0 +1,140 @@ ++/* ++ * Copyright (c) 2018-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef FFA_SVC_H ++#define FFA_SVC_H ++ ++#include ++#include ++#include ++ ++/* FFA error codes. */ ++#define FFA_ERROR_NOT_SUPPORTED -1 ++#define FFA_ERROR_INVALID_PARAMETER -2 ++#define FFA_ERROR_NO_MEMORY -3 ++#define FFA_ERROR_BUSY -4 ++#define FFA_ERROR_INTERRUPTED -5 ++#define FFA_ERROR_DENIED -6 ++#define FFA_ERROR_RETRY -7 ++ ++/* The macros below are used to identify FFA calls from the SMC function ID */ ++#define FFA_FNUM_MIN_VALUE U(0x60) ++#define FFA_FNUM_MAX_VALUE U(0x7f) ++#define is_ffa_fid(fid) __extension__ ({ \ ++ __typeof__(fid) _fid = (fid); \ ++ ((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \ ++ (GET_SMC_NUM(_fid) <= FFA_FNUM_MAX_VALUE)); }) ++ ++/* FFA_VERSION helpers */ ++#define FFA_VERSION_MAJOR U(1) ++#define FFA_VERSION_MAJOR_SHIFT 16 ++#define FFA_VERSION_MAJOR_MASK U(0x7FFF) ++#define FFA_VERSION_MINOR U(0) ++#define FFA_VERSION_MINOR_SHIFT 0 ++#define FFA_VERSION_MINOR_MASK U(0xFFFF) ++#define FFA_VERSION_BIT31_MASK U(1 << 31) ++ ++#define MAKE_FFA_VERSION(major, minor) \ ++ ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ ++ (((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT)) ++#define FFA_VERSION_COMPILED MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \ ++ FFA_VERSION_MINOR) ++ ++/* FFA_MSG_SEND helpers */ ++#define FFA_MSG_SEND_ATTRS_BLK_SHIFT U(0) ++#define FFA_MSG_SEND_ATTRS_BLK_MASK U(0x1) ++#define FFA_MSG_SEND_ATTRS_BLK U(0) ++#define FFA_MSG_SEND_ATTRS_BLK_NOT U(1) ++#define FFA_MSG_SEND_ATTRS(blk) \ ++ (((blk) & FFA_MSG_SEND_ATTRS_BLK_MASK) \ ++ << FFA_MSG_SEND_ATTRS_BLK_SHIFT) ++ ++/* Get FFA fastcall std FID from function number */ ++#define FFA_FID(smc_cc, func_num) \ ++ ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ ++ ((smc_cc) << FUNCID_CC_SHIFT) | \ ++ (OEN_STD_START << FUNCID_OEN_SHIFT) | \ ++ ((func_num) << FUNCID_NUM_SHIFT)) ++ ++/* FFA function numbers */ ++#define FFA_FNUM_ERROR U(0x60) ++#define FFA_FNUM_SUCCESS U(0x61) ++#define FFA_FNUM_INTERRUPT U(0x62) ++#define FFA_FNUM_VERSION U(0x63) ++#define FFA_FNUM_FEATURES U(0x64) ++#define FFA_FNUM_RX_RELEASE U(0x65) ++#define FFA_FNUM_RXTX_MAP U(0x66) ++#define FFA_FNUM_RXTX_UNMAP U(0x67) ++#define FFA_FNUM_PARTITION_INFO_GET U(0x68) ++#define FFA_FNUM_ID_GET U(0x69) ++#define FFA_FNUM_MSG_POLL U(0x6A) ++#define FFA_FNUM_MSG_WAIT U(0x6B) ++#define FFA_FNUM_MSG_YIELD U(0x6C) ++#define FFA_FNUM_MSG_RUN U(0x6D) ++#define FFA_FNUM_MSG_SEND U(0x6E) ++#define FFA_FNUM_MSG_SEND_DIRECT_REQ U(0x6F) ++#define FFA_FNUM_MSG_SEND_DIRECT_RESP U(0x70) ++#define FFA_FNUM_MEM_DONATE U(0x71) ++#define FFA_FNUM_MEM_LEND U(0x72) ++#define FFA_FNUM_MEM_SHARE U(0x73) ++#define FFA_FNUM_MEM_RETRIEVE_REQ U(0x74) ++#define FFA_FNUM_MEM_RETRIEVE_RESP U(0x75) ++#define FFA_FNUM_MEM_RELINQUISH U(0x76) ++#define FFA_FNUM_MEM_RECLAIM U(0x77) ++ ++/* FFA SMC32 FIDs */ ++#define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR) ++#define FFA_SUCCESS_SMC32 FFA_FID(SMC_32, FFA_FNUM_SUCCESS) ++#define FFA_INTERRUPT FFA_FID(SMC_32, FFA_FNUM_INTERRUPT) ++#define FFA_VERSION FFA_FID(SMC_32, FFA_FNUM_VERSION) ++#define FFA_FEATURES FFA_FID(SMC_32, FFA_FNUM_FEATURES) ++#define FFA_RX_RELEASE FFA_FID(SMC_32, FFA_FNUM_RX_RELEASE) ++#define FFA_RXTX_MAP_SMC32 FFA_FID(SMC_32, FFA_FNUM_RXTX_MAP) ++#define FFA_RXTX_UNMAP FFA_FID(SMC_32, FFA_FNUM_RXTX_UNMAP) ++#define FFA_PARTITION_INFO_GET FFA_FID(SMC_32, FFA_FNUM_PARTITION_INFO_GET) ++#define FFA_ID_GET FFA_FID(SMC_32, FFA_FNUM_ID_GET) ++#define FFA_MSG_POLL FFA_FID(SMC_32, FFA_FNUM_MSG_POLL) ++#define FFA_MSG_WAIT FFA_FID(SMC_32, FFA_FNUM_MSG_WAIT) ++#define FFA_MSG_YIELD FFA_FID(SMC_32, FFA_FNUM_MSG_YIELD) ++#define FFA_MSG_RUN FFA_FID(SMC_32, FFA_FNUM_MSG_RUN) ++#define FFA_MSG_SEND FFA_FID(SMC_32, FFA_FNUM_MSG_SEND) ++#define FFA_MSG_SEND_DIRECT_REQ_SMC32 \ ++ FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_REQ) ++#define FFA_MSG_SEND_DIRECT_RESP_SMC32 \ ++ FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_RESP) ++#define FFA_MEM_DONATE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_DONATE) ++#define FFA_MEM_LEND_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_LEND) ++#define FFA_MEM_SHARE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_SHARE) ++#define FFA_MEM_RETRIEVE_REQ_SMC32 \ ++ FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_REQ) ++#define FFA_MEM_RETRIEVE_RESP FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP) ++#define FFA_MEM_RELINQUISH FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH) ++#define FFA_MEM_RECLAIM FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM) ++ ++/* FFA SMC64 FIDs */ ++#define FFA_SUCCESS_SMC64 FFA_FID(SMC_64, FFA_FNUM_SUCCESS) ++#define FFA_RXTX_MAP_SMC64 FFA_FID(SMC_64, FFA_FNUM_RXTX_MAP) ++#define FFA_MSG_SEND_DIRECT_REQ_SMC64 \ ++ FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ) ++#define FFA_MSG_SEND_DIRECT_RESP_SMC64 \ ++ FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP) ++#define FFA_MEM_DONATE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_DONATE) ++#define FFA_MEM_LEND_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_LEND) ++#define FFA_MEM_SHARE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_SHARE) ++#define FFA_MEM_RETRIEVE_REQ_SMC64 \ ++ FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ) ++ ++/* ++ * Reserve a special value for traffic targeted to the Hypervisor or SPM. ++ */ ++#define FFA_TARGET_INFO_MBZ U(0x0) ++ ++/* ++ * Reserve a special value for MBZ parameters. ++ */ ++#define FFA_PARAM_MBZ U(0x0) ++ ++#endif /* FFA_SVC_H */ +diff --git a/environments/shim/include/runtime_services/smccc.h b/environments/shim/include/runtime_services/smccc.h +new file mode 100644 +index 0000000..283b463 +--- /dev/null ++++ b/environments/shim/include/runtime_services/smccc.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2018-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __SMCCC_H__ ++#define __SMCCC_H__ ++ ++#include ++ ++#define SMCCC_VERSION_MAJOR_SHIFT U(16) ++#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF) ++#define SMCCC_VERSION_MINOR_SHIFT U(0) ++#define SMCCC_VERSION_MINOR_MASK U(0xFFFF) ++#define MAKE_SMCCC_VERSION(_major, _minor) \ ++ ((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \ ++ SMCCC_VERSION_MAJOR_SHIFT) \ ++ | (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \ ++ SMCCC_VERSION_MINOR_SHIFT)) ++ ++#define SMC_UNKNOWN -1 ++#define SMC_OK 0 ++ ++/* Return codes for Arm Architecture Service SMC calls */ ++#define SMC_ARCH_CALL_SUCCESS 0 ++#define SMC_ARCH_CALL_NOT_SUPPORTED -1 ++#define SMC_ARCH_CALL_NOT_REQUIRED -2 ++#define SMC_ARCH_CALL_INVAL_PARAM -3 ++ ++/******************************************************************************* ++ * Bit definitions inside the function id as per the SMC calling convention ++ ******************************************************************************/ ++#define FUNCID_TYPE_SHIFT 31 ++#define FUNCID_CC_SHIFT 30 ++#define FUNCID_OEN_SHIFT 24 ++#define FUNCID_NUM_SHIFT 0 ++ ++#define FUNCID_TYPE_MASK 0x1 ++#define FUNCID_CC_MASK 0x1 ++#define FUNCID_OEN_MASK 0x3f ++#define FUNCID_NUM_MASK 0xffff ++ ++#define FUNCID_TYPE_WIDTH 1 ++#define FUNCID_CC_WIDTH 1 ++#define FUNCID_OEN_WIDTH 6 ++#define FUNCID_NUM_WIDTH 16 ++ ++#define SMC_64 1 ++#define SMC_32 0 ++#define SMC_TYPE_FAST 1 ++#define SMC_TYPE_STD 0 ++ ++/******************************************************************************* ++ * Owning entity number definitions inside the function id as per the SMC ++ * calling convention ++ ******************************************************************************/ ++#define OEN_ARM_START 0 ++#define OEN_ARM_END 0 ++#define OEN_CPU_START 1 ++#define OEN_CPU_END 1 ++#define OEN_SIP_START 2 ++#define OEN_SIP_END 2 ++#define OEN_OEM_START 3 ++#define OEN_OEM_END 3 ++#define OEN_STD_START 4 /* Standard Calls */ ++#define OEN_STD_END 4 ++#define OEN_TAP_START 48 /* Trusted Applications */ ++#define OEN_TAP_END 49 ++#define OEN_TOS_START 50 /* Trusted OS */ ++#define OEN_TOS_END 63 ++#define OEN_LIMIT 64 ++ ++/******************************************************************************* ++ * Argument definitions passed to SMC call ++ ******************************************************************************/ ++#define SMC_GET_SOC_VERSION 0 ++#define SMC_GET_SOC_REVISION 1 ++ ++#endif /* __SMCCC_H__ */ +diff --git a/environments/shim/include/shim_sp.h b/environments/shim/include/shim_sp.h +new file mode 100644 +index 0000000..53b8e06 +--- /dev/null ++++ b/environments/shim/include/shim_sp.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SP_H ++#define SP_H ++ ++#include ++ ++/* Linker symbols used to figure out the memory layout of the S-EL1 shim. */ ++extern uintptr_t __SHIM_TEXT_START__, __SHIM_TEXT_END__; ++#define SHIM_TEXT_START ((uintptr_t)&__SHIM_TEXT_START__) ++#define SHIM_TEXT_END ((uintptr_t)&__SHIM_TEXT_END__) ++ ++extern uintptr_t __SHIM_RODATA_START__, __SHIM_RODATA_END__; ++#define SHIM_RODATA_START ((uintptr_t)&__SHIM_RODATA_START__) ++#define SHIM_RODATA_END ((uintptr_t)&__SHIM_RODATA_END__) ++ ++extern uintptr_t __SHIM_DATA_START__, __SHIM_DATA_END__; ++#define SHIM_DATA_START ((uintptr_t)&__SHIM_DATA_START__) ++#define SHIM_DATA_END ((uintptr_t)&__SHIM_DATA_END__) ++ ++extern uintptr_t __SHIM_BSS_START__, __SHIM_BSS_END__; ++#define SHIM_BSS_START ((uintptr_t)&__SHIM_BSS_START__) ++#define SHIM_BSS_END ((uintptr_t)&__SHIM_BSS_END__) ++ ++/* Linker symbols used to figure out the memory layout of TS (S-EL0). */ ++extern uintptr_t __TEXT_START__, __TEXT_END__; ++#define SP_TEXT_START ((uintptr_t)&__TEXT_START__) ++#define SP_TEXT_END ((uintptr_t)&__TEXT_END__) ++ ++extern uintptr_t __RODATA_START__, __RODATA_END__; ++#define SP_RODATA_START ((uintptr_t)&__RODATA_START__) ++#define SP_RODATA_END ((uintptr_t)&__RODATA_END__) ++ ++extern uintptr_t __DATA_START__, __DATA_END__; ++#define SP_DATA_START ((uintptr_t)&__DATA_START__) ++#define SP_DATA_END ((uintptr_t)&__DATA_END__) ++ ++extern uintptr_t __BSS_START__, __BSS_END__; ++#define SP_BSS_START ((uintptr_t)&__BSS_START__) ++#define SP_BSS_END ((uintptr_t)&__BSS_END__) ++ ++ ++#endif /* __SP_H__ */ +diff --git a/environments/shim/include/tftf.h b/environments/shim/include/tftf.h +new file mode 100644 +index 0000000..746e137 +--- /dev/null ++++ b/environments/shim/include/tftf.h +@@ -0,0 +1,174 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __TFTF_H__ ++#define __TFTF_H__ ++ ++#ifndef __ASSEMBLY__ ++#include ++#include ++#include ++ ++#define TFTF_WELCOME_STR "Booting trusted firmware test framework" ++ ++/* Maximum size of test output (in bytes) */ ++#define TESTCASE_OUTPUT_MAX_SIZE 512 ++ ++/* Size of build message used to differentiate different TFTF binaries */ ++#define BUILD_MESSAGE_SIZE 0x20 ++ ++typedef unsigned int STATUS; ++ ++extern const char build_message[]; ++ ++typedef test_result_t (*test_function_t)(void); ++ ++typedef struct { ++ /* Test result (success, crashed, failed, ...). */ ++ test_result_t result; ++ unsigned long long duration; ++ /* ++ * Offset of test output string from TEST_NVM_RESULT_BUFFER_OFFSET. ++ * Only relevant if test has an output, i.e. if \a output_size is not ++ * zero. ++ */ ++ unsigned output_offset; ++ /* Size of test output string, excluding final \0. */ ++ unsigned output_size; ++} TESTCASE_RESULT; ++ ++typedef struct { ++ unsigned index; ++ const char *name; ++ const char *description; ++ test_function_t test; ++} test_case_t; ++ ++typedef struct { ++ const char *name; ++ const char *description; ++ const test_case_t *testcases; ++} test_suite_t; ++ ++/* ++ * Reference to a specific test. ++ */ ++typedef struct { ++ unsigned int testsuite_idx; ++ unsigned int testcase_idx; ++} test_ref_t; ++ ++/* ++ * The progress in the execution of a test. ++ * This is used to implement the following state machine. ++ * ++ * +-> TEST_READY (initial state of the test) <--------------+ ++ * | | | ++ * | | Test framework prepares the test environment. | ++ * | | | ++ * | v | ++ * | TEST_IN_PROGRESS | ++ * | | | ++ * | | Hand over to the test function. | ++ * | | If the test wants to reboot the platform ---> TEST_REBOOTING | ++ * | | Test function returns into framework. | | ++ * | | | Reboot | ++ * | | | | ++ * | | +---------+ ++ * | v ++ * | TEST_COMPLETE ++ * | | ++ * | | Do some framework management. ++ * | | Move to next test. ++ * +--------+ ++ */ ++typedef enum { ++ TEST_PROGRESS_MIN = 0, ++ TEST_READY = TEST_PROGRESS_MIN, ++ TEST_IN_PROGRESS, ++ TEST_COMPLETE, ++ TEST_REBOOTING, ++ ++ TEST_PROGRESS_MAX, ++} test_progress_t; ++ ++#define TEST_PROGRESS_IS_VALID(_progress) \ ++ ((_progress >= TEST_PROGRESS_MIN) && (_progress < TEST_PROGRESS_MAX)) ++ ++/* ++ * The definition of this global variable is generated by the script ++ * 'tftf_generate_test_list' during the build process ++ */ ++extern const test_suite_t testsuites[]; ++ ++extern TESTCASE_RESULT testcase_results[]; ++ ++/* Set/Get the test to run in NVM */ ++STATUS tftf_set_test_to_run(const test_ref_t test_to_run); ++STATUS tftf_get_test_to_run(test_ref_t *test_to_run); ++/* Set/Get the progress of the current test in NVM */ ++STATUS tftf_set_test_progress(test_progress_t test_progress); ++STATUS tftf_get_test_progress(test_progress_t *test_progress); ++ ++/** ++** Save test result into NVM. ++*/ ++STATUS tftf_testcase_set_result(const test_case_t *testcase, ++ test_result_t result, ++ unsigned long long duration); ++/** ++** Get a testcase result from NVM. ++** ++** @param[in] testcase The targeted testcase. ++** @param[out] result Testcase result. Only \a result.result and ++** \a result.duration are of interest for the caller and the 2 other fields ++** should be ignored (they correspond to a location in NVM). ++** @param[out] test_output Buffer to store the test output, if any. ++** \a test_output must be big enough to hold the whole test output. ++** Test output will be \a TESTCASE_OUTPUT_MAX_SIZE bytes maximum. ++*/ ++STATUS tftf_testcase_get_result(const test_case_t *testcase, TESTCASE_RESULT *result, char *test_output); ++ ++void print_testsuite_start(const test_suite_t *testsuite); ++void print_test_start(const test_case_t *test); ++void print_test_end(const test_case_t *test); ++void print_tests_summary(void); ++ ++/* ++ * Exit the TFTF. ++ * This function can be used when a fatal error is encountered or as part of the ++ * normal termination process. It does the necessary cleanups then put the ++ * core in a low-power state. ++ */ ++void __dead2 tftf_exit(void); ++ ++void tftf_arch_setup(void); ++ ++/* ++ * This function detects the power state format used by PSCI which can ++ * be either extended or original format. For the Original format, ++ * the State-ID can either be NULL or can be using the recommended encoding. ++ * This function needs to be invoked once during cold boot prior to the ++ * invocation of any PSCI power state helper functions. ++ */ ++void tftf_detect_psci_pstate_format(void); ++ ++/* ++ * Run the next test on the calling CPU. ++ * Once the test is complete, if the calling CPU is the last one to exit the ++ * test then do the necessary bookkeeping, report the overall test result and ++ * move on to the next test. Otherwise, shut down the calling CPU. ++ * ++ * This function never returns. ++ */ ++void __dead2 run_tests(void); ++ ++/* Entry point for a CPU that has just been powered up */ ++void tftf_hotplug_entry(void); ++ ++#endif /*__ASSEMBLY__*/ ++ ++#endif +diff --git a/environments/shim/lib/aarch64/cache_helpers.S b/environments/shim/lib/aarch64/cache_helpers.S +new file mode 100644 +index 0000000..9e67dad +--- /dev/null ++++ b/environments/shim/lib/aarch64/cache_helpers.S +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++ ++ .globl flush_dcache_range ++ .globl clean_dcache_range ++ .globl inv_dcache_range ++ .globl dcsw_op_louis ++ .globl dcsw_op_all ++ .globl dcsw_op_level1 ++ .globl dcsw_op_level2 ++ .globl dcsw_op_level3 ++ ++/* ++ * This macro can be used for implementing various data cache operations `op` ++ */ ++.macro do_dcache_maintenance_by_mva op ++ /* Exit early if size is zero */ ++ cbz x1, exit_loop_\op ++ dcache_line_size x2, x3 ++ add x1, x0, x1 ++ sub x3, x2, #1 ++ bic x0, x0, x3 ++loop_\op: ++ dc \op, x0 ++ add x0, x0, x2 ++ cmp x0, x1 ++ b.lo loop_\op ++ dsb sy ++exit_loop_\op: ++ ret ++.endm ++ /* ------------------------------------------ ++ * Clean+Invalidate from base address till ++ * size. 'x0' = addr, 'x1' = size ++ * ------------------------------------------ ++ */ ++func flush_dcache_range ++ do_dcache_maintenance_by_mva civac ++endfunc flush_dcache_range ++ ++ /* ------------------------------------------ ++ * Clean from base address till size. ++ * 'x0' = addr, 'x1' = size ++ * ------------------------------------------ ++ */ ++func clean_dcache_range ++ do_dcache_maintenance_by_mva cvac ++endfunc clean_dcache_range ++ ++ /* ------------------------------------------ ++ * Invalidate from base address till ++ * size. 'x0' = addr, 'x1' = size ++ * ------------------------------------------ ++ */ ++func inv_dcache_range ++ do_dcache_maintenance_by_mva ivac ++endfunc inv_dcache_range ++ ++ ++ /* --------------------------------------------------------------- ++ * Data cache operations by set/way to the level specified ++ * ++ * The main function, do_dcsw_op requires: ++ * x0: The operation type (0-2), as defined in arch.h ++ * x3: The last cache level to operate on ++ * x9: clidr_el1 ++ * x10: The cache level to begin operation from ++ * and will carry out the operation on each data cache from level 0 ++ * to the level in x3 in sequence ++ * ++ * The dcsw_op macro sets up the x3 and x9 parameters based on ++ * clidr_el1 cache information before invoking the main function ++ * --------------------------------------------------------------- ++ */ ++ ++ .macro dcsw_op shift, fw, ls ++ mrs x9, clidr_el1 ++ ubfx x3, x9, \shift, \fw ++ lsl x3, x3, \ls ++ mov x10, xzr ++ b do_dcsw_op ++ .endm ++ ++func do_dcsw_op ++ cbz x3, exit ++ adr x14, dcsw_loop_table // compute inner loop address ++ add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions ++#if ENABLE_BTI ++ add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction ++#endif ++ mov x0, x9 ++ mov w8, #1 ++loop1: ++ add x2, x10, x10, lsr #1 // work out 3x current cache level ++ lsr x1, x0, x2 // extract cache type bits from clidr ++ and x1, x1, #7 // mask the bits for current cache only ++ cmp x1, #2 // see what cache we have at this level ++ b.lo level_done // nothing to do if no cache or icache ++ ++ msr csselr_el1, x10 // select current cache level in csselr ++ isb // isb to sych the new cssr&csidr ++ mrs x1, ccsidr_el1 // read the new ccsidr ++ and x2, x1, #7 // extract the length of the cache lines ++ add x2, x2, #4 // add 4 (line length offset) ++ ubfx x4, x1, #3, #10 // maximum way number ++ clz w5, w4 // bit position of way size increment ++ lsl w9, w4, w5 // w9 = aligned max way number ++ lsl w16, w8, w5 // w16 = way number loop decrement ++ orr w9, w10, w9 // w9 = combine way and cache number ++ ubfx w6, w1, #13, #15 // w6 = max set number ++ lsl w17, w8, w2 // w17 = set number loop decrement ++ dsb sy // barrier before we start this level ++ br x14 // jump to DC operation specific loop ++ ++ .macro dcsw_loop _op ++#if ENABLE_BTI ++ bti j ++#endif ++loop2_\_op: ++ lsl w7, w6, w2 // w7 = aligned max set number ++ ++loop3_\_op: ++ orr w11, w9, w7 // combine cache, way and set number ++ dc \_op, x11 ++ subs w7, w7, w17 // decrement set number ++ b.hs loop3_\_op ++ ++ subs x9, x9, x16 // decrement way number ++ b.hs loop2_\_op ++ ++ b level_done ++ .endm ++ ++level_done: ++ add x10, x10, #2 // increment cache number ++ cmp x3, x10 ++ b.hi loop1 ++ msr csselr_el1, xzr // select cache level 0 in csselr ++ dsb sy // barrier to complete final cache operation ++ isb ++exit: ++ ret ++endfunc do_dcsw_op ++ ++dcsw_loop_table: ++ dcsw_loop isw ++ dcsw_loop cisw ++ dcsw_loop csw ++ ++ ++func dcsw_op_louis ++ dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT ++endfunc dcsw_op_louis ++ ++ ++func dcsw_op_all ++ dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT ++endfunc dcsw_op_all ++ ++ /* --------------------------------------------------------------- ++ * Helper macro for data cache operations by set/way for the ++ * level specified ++ * --------------------------------------------------------------- ++ */ ++ .macro dcsw_op_level level ++ mrs x9, clidr_el1 ++ mov x3, \level ++ sub x10, x3, #2 ++ b do_dcsw_op ++ .endm ++ ++ /* --------------------------------------------------------------- ++ * Data cache operations by set/way for level 1 cache ++ * ++ * The main function, do_dcsw_op requires: ++ * x0: The operation type (0-2), as defined in arch.h ++ * --------------------------------------------------------------- ++ */ ++func dcsw_op_level1 ++ dcsw_op_level #(1 << LEVEL_SHIFT) ++endfunc dcsw_op_level1 ++ ++ /* --------------------------------------------------------------- ++ * Data cache operations by set/way for level 2 cache ++ * ++ * The main function, do_dcsw_op requires: ++ * x0: The operation type (0-2), as defined in arch.h ++ * --------------------------------------------------------------- ++ */ ++func dcsw_op_level2 ++ dcsw_op_level #(2 << LEVEL_SHIFT) ++endfunc dcsw_op_level2 ++ ++ /* --------------------------------------------------------------- ++ * Data cache operations by set/way for level 3 cache ++ * ++ * The main function, do_dcsw_op requires: ++ * x0: The operation type (0-2), as defined in arch.h ++ * --------------------------------------------------------------- ++ */ ++func dcsw_op_level3 ++ dcsw_op_level #(3 << LEVEL_SHIFT) ++endfunc dcsw_op_level3 +diff --git a/environments/shim/lib/aarch64/misc_helpers.S b/environments/shim/lib/aarch64/misc_helpers.S +new file mode 100644 +index 0000000..16d6899 +--- /dev/null ++++ b/environments/shim/lib/aarch64/misc_helpers.S +@@ -0,0 +1,226 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++#include ++ ++ .globl smc ++ ++ .globl zeromem16 ++ .globl memcpy16 ++ ++ .globl disable_mmu ++ .globl disable_mmu_icache ++ ++func smc ++ smc #0 ++endfunc smc ++ ++/* ----------------------------------------------------------------------- ++ * void zeromem16(void *mem, unsigned int length); ++ * ++ * Initialise a memory region to 0. ++ * The memory address must be 16-byte aligned. ++ * ----------------------------------------------------------------------- ++ */ ++func zeromem16 ++#if ENABLE_ASSERTIONS ++ tst x0, #0xf ++ ASM_ASSERT(eq) ++#endif ++ add x2, x0, x1 ++/* zero 16 bytes at a time */ ++z_loop16: ++ sub x3, x2, x0 ++ cmp x3, #16 ++ b.lt z_loop1 ++ stp xzr, xzr, [x0], #16 ++ b z_loop16 ++/* zero byte per byte */ ++z_loop1: ++ cmp x0, x2 ++ b.eq z_end ++ strb wzr, [x0], #1 ++ b z_loop1 ++z_end: ++ ret ++endfunc zeromem16 ++ ++ ++/* -------------------------------------------------------------------------- ++ * void memcpy16(void *dest, const void *src, unsigned int length) ++ * ++ * Copy length bytes from memory area src to memory area dest. ++ * The memory areas should not overlap. ++ * Destination and source addresses must be 16-byte aligned. ++ * -------------------------------------------------------------------------- ++ */ ++func memcpy16 ++#if ENABLE_ASSERTIONS ++ orr x3, x0, x1 ++ tst x3, #0xf ++ ASM_ASSERT(eq) ++#endif ++/* copy 16 bytes at a time */ ++m_loop16: ++ cmp x2, #16 ++ b.lt m_loop1 ++ ldp x3, x4, [x1], #16 ++ stp x3, x4, [x0], #16 ++ sub x2, x2, #16 ++ b m_loop16 ++/* copy byte per byte */ ++m_loop1: ++ cbz x2, m_end ++ ldrb w3, [x1], #1 ++ strb w3, [x0], #1 ++ subs x2, x2, #1 ++ b.ne m_loop1 ++m_end: ++ ret ++endfunc memcpy16 ++ ++/* --------------------------------------------------------------------------- ++ * Disable the MMU at the current exception level (NS-EL1 or EL2) ++ * This is implemented in assembler to ensure that the data cache is cleaned ++ * and invalidated after the MMU is disabled without any intervening cacheable ++ * data accesses ++ * --------------------------------------------------------------------------- ++ */ ++func disable_mmu ++ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) ++do_disable_mmu: ++ asm_read_sctlr_el1_or_el2 ++ bic x0, x0, x1 ++ asm_write_sctlr_el1_or_el2 x1 ++ isb /* ensure MMU is off */ ++ mov x0, #DCCISW /* DCache clean and invalidate */ ++ b dcsw_op_all ++endfunc disable_mmu ++ ++func disable_mmu_icache ++ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) ++ b do_disable_mmu ++endfunc disable_mmu_icache ++ ++/* Need this label for asm_read/write_sctlr_el1_or_el2 */ ++dead: ++ b dead ++ ++/* --------------------------------------------------------------------------- ++ * Helper to fixup Global Offset table (GOT) and dynamic relocations ++ * (.rela.dyn) at runtime. ++ * ++ * This function is meant to be used when the firmware is compiled with -fpie ++ * and linked with -pie options. We rely on the linker script exporting ++ * appropriate markers for start and end of the section. For GOT, we ++ * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect ++ * __RELA_START__ and __RELA_END__. ++ * ++ * The function takes the limits of the memory to apply fixups to as ++ * arguments (which is usually the limits of the relocable BL image). ++ * x0 - the start of the fixup region ++ * x1 - the limit of the fixup region ++ * These addresses have to be page (4KB aligned). ++ * --------------------------------------------------------------------------- ++ */ ++.globl fixup_gdt_reloc ++func fixup_gdt_reloc ++ mov x6, x0 ++ mov x7, x1 ++ ++ /* Test if the limits are 4K aligned */ ++#if ENABLE_ASSERTIONS ++ orr x0, x0, x1 ++ tst x0, #(PAGE_SIZE - 1) ++ ASM_ASSERT(eq) ++#endif ++ /* ++ * Calculate the offset based on return address in x30. ++ * Assume that this function is called within a page at the start of ++ * fixup region. ++ */ ++ and x2, x30, #~(PAGE_SIZE - 1) ++ sub x0, x2, x6 /* Diff(S) = Current Address - Compiled Address */ ++ ++ adrp x1, __GOT_START__ ++ add x1, x1, :lo12:__GOT_START__ ++ adrp x2, __GOT_END__ ++ add x2, x2, :lo12:__GOT_END__ ++ ++ /* ++ * GOT is an array of 64_bit addresses which must be fixed up as ++ * new_addr = old_addr + Diff(S). ++ * The new_addr is the address currently the binary is executing from ++ * and old_addr is the address at compile time. ++ */ ++1: ++ ldr x3, [x1] ++ /* Skip adding offset if address is < lower limit */ ++ cmp x3, x6 ++ b.lo 2f ++ /* Skip adding offset if address is >= upper limit */ ++ cmp x3, x7 ++ b.ge 2f ++ add x3, x3, x0 ++ str x3, [x1] ++2: ++ add x1, x1, #8 ++ cmp x1, x2 ++ b.lo 1b ++ ++ /* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */ ++ adrp x1, __RELA_START__ ++ add x1, x1, :lo12:__RELA_START__ ++ adrp x2, __RELA_END__ ++ add x2, x2, :lo12:__RELA_END__ ++ /* ++ * According to ELF-64 specification, the RELA data structure is as ++ * follows: ++ * typedef struct ++ * { ++ * Elf64_Addr r_offset; ++ * Elf64_Xword r_info; ++ * Elf64_Sxword r_addend; ++ * } Elf64_Rela; ++ * ++ * r_offset is address of reference ++ * r_info is symbol index and type of relocation (in this case ++ * 0x403 which corresponds to R_AARCH64_RELATIVE). ++ * r_addend is constant part of expression. ++ * ++ * Size of Elf64_Rela structure is 24 bytes. ++ */ ++1: ++ /* Assert that the relocation type is R_AARCH64_RELATIVE */ ++#if ENABLE_ASSERTIONS ++ ldr x3, [x1, #8] ++ cmp x3, #0x403 ++ ASM_ASSERT(eq) ++#endif ++ ldr x3, [x1] /* r_offset */ ++ add x3, x0, x3 ++ ldr x4, [x1, #16] /* r_addend */ ++ ++ /* Skip adding offset if r_addend is < lower limit */ ++ cmp x4, x6 ++ b.lo 2f ++ /* Skip adding offset if r_addend entry is >= upper limit */ ++ cmp x4, x7 ++ b.ge 2f ++ ++ add x4, x0, x4 /* Diff(S) + r_addend */ ++ str x4, [x3] ++ ++2: add x1, x1, #24 ++ cmp x1, x2 ++ b.lo 1b ++ ++ ret ++endfunc fixup_gdt_reloc +diff --git a/environments/shim/lib/libc/assert.c b/environments/shim/lib/libc/assert.c +new file mode 100644 +index 0000000..dbf8507 +--- /dev/null ++++ b/environments/shim/lib/libc/assert.c +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++void __assert(const char *file, unsigned int line, const char *assertion) ++{ ++ printf("ASSERT: %s:%d:%s\n", file, line, assertion); ++ panic(); ++} +diff --git a/environments/shim/lib/libc/bget_malloc.c b/environments/shim/lib/libc/bget_malloc.c +new file mode 100644 +index 0000000..62ec4bf +--- /dev/null ++++ b/environments/shim/lib/libc/bget_malloc.c +@@ -0,0 +1,951 @@ ++// SPDX-License-Identifier: BSD-2-Clause ++/* ++ * Copyright (c) 2014, STMicroelectronics International N.V. ++ */ ++ ++#define PROTOTYPES ++ ++/* ++ * BGET CONFIGURATION ++ * ================== ++ */ ++/* #define BGET_ENABLE_ALL_OPTIONS */ ++#ifdef BGET_ENABLE_OPTION ++#define TestProg 20000 /* Generate built-in test program ++ if defined. The value specifies ++ how many buffer allocation attempts ++ the test program should make. */ ++#endif ++ ++ ++#ifdef __LP64__ ++#define SizeQuant 16 ++#endif ++#ifdef __ILP32__ ++#define SizeQuant 8 ++#endif ++ /* Buffer allocation size quantum: ++ all buffers allocated are a ++ multiple of this size. This ++ MUST be a power of two. */ ++ ++#ifdef BGET_ENABLE_OPTION ++#define BufDump 1 /* Define this symbol to enable the ++ bpoold() function which dumps the ++ buffers in a buffer pool. */ ++ ++#define BufValid 1 /* Define this symbol to enable the ++ bpoolv() function for validating ++ a buffer pool. */ ++ ++#define DumpData 1 /* Define this symbol to enable the ++ bufdump() function which allows ++ dumping the contents of an allocated ++ or free buffer. */ ++ ++#define BufStats 1 /* Define this symbol to enable the ++ bstats() function which calculates ++ the total free space in the buffer ++ pool, the largest available ++ buffer, and the total space ++ currently allocated. */ ++ ++#define FreeWipe 1 /* Wipe free buffers to a guaranteed ++ pattern of garbage to trip up ++ miscreants who attempt to use ++ pointers into released buffers. */ ++ ++#define BestFit 1 /* Use a best fit algorithm when ++ searching for space for an ++ allocation request. This uses ++ memory more efficiently, but ++ allocation will be much slower. */ ++ ++#define BECtl 1 /* Define this symbol to enable the ++ bectl() function for automatic ++ pool space control. */ ++#endif ++ ++#ifdef MEM_DEBUG ++#undef NDEBUG ++#define DumpData 1 ++#define BufValid 1 ++#define FreeWipe 1 ++#endif ++ ++#ifdef CFG_WITH_STATS ++#define BufStats 1 ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(__KERNEL__) ++/* Compiling for TEE Core */ ++#include ++#include ++#include ++ ++static void tag_asan_free(void *buf, size_t len) ++{ ++ asan_tag_heap_free(buf, (uint8_t *)buf + len); ++} ++ ++static void tag_asan_alloced(void *buf, size_t len) ++{ ++ asan_tag_access(buf, (uint8_t *)buf + len); ++} ++ ++static void *memset_unchecked(void *s, int c, size_t n) ++{ ++ return asan_memset_unchecked(s, c, n); ++} ++ ++static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, ++ size_t n) ++{ ++ return asan_memcpy_unchecked(dst, src, n); ++} ++ ++#else /*__KERNEL__*/ ++/* Compiling for TA */ ++ ++static void tag_asan_free(void *buf __unused, size_t len __unused) ++{ ++} ++ ++static void tag_asan_alloced(void *buf __unused, size_t len __unused) ++{ ++} ++ ++static void *memset_unchecked(void *s, int c, size_t n) ++{ ++ return memset(s, c, n); ++} ++ ++static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, ++ size_t n) ++{ ++ return memcpy(dst, src, n); ++} ++ ++#endif /*__KERNEL__*/ ++ ++#include "bget.c" /* this is ugly, but this is bget */ ++ ++struct malloc_pool { ++ void *buf; ++ size_t len; ++}; ++ ++struct malloc_ctx { ++ struct bpoolset poolset; ++ struct malloc_pool *pool; ++ size_t pool_len; ++#ifdef BufStats ++ struct malloc_stats mstats; ++#endif ++#ifdef __KERNEL__ ++ unsigned int spinlock; ++#endif ++}; ++ ++#ifdef __KERNEL__ ++ ++static uint32_t malloc_lock(struct malloc_ctx *ctx) ++{ ++ return cpu_spin_lock_xsave(&ctx->spinlock); ++} ++ ++static void malloc_unlock(struct malloc_ctx *ctx, uint32_t exceptions) ++{ ++ cpu_spin_unlock_xrestore(&ctx->spinlock, exceptions); ++} ++ ++#else /* __KERNEL__ */ ++ ++static uint32_t malloc_lock(struct malloc_ctx *ctx __unused) ++{ ++ return 0; ++} ++ ++static void malloc_unlock(struct malloc_ctx *ctx __unused, ++ uint32_t exceptions __unused) ++{ ++} ++ ++#endif /* __KERNEL__ */ ++ ++#define DEFINE_CTX(name) struct malloc_ctx name = \ ++ { .poolset = { .freelist = { {0, 0}, \ ++ {&name.poolset.freelist, \ ++ &name.poolset.freelist}}}} ++ ++static DEFINE_CTX(malloc_ctx); ++ ++#ifdef CFG_VIRTUALIZATION ++static __nex_data DEFINE_CTX(nex_malloc_ctx); ++#endif ++ ++static void print_oom(size_t req_size __maybe_unused, void *ctx __maybe_unused) ++{ ++#if defined(__KERNEL__) && defined(CFG_CORE_DUMP_OOM) ++ EMSG("Memory allocation failed: size %zu context %p", req_size, ctx); ++ EPRINT_STACK(); ++#endif ++} ++ ++#ifdef BufStats ++ ++static void raw_malloc_return_hook(void *p, size_t requested_size, ++ struct malloc_ctx *ctx) ++{ ++ if (ctx->poolset.totalloc > ctx->mstats.max_allocated) ++ ctx->mstats.max_allocated = ctx->poolset.totalloc; ++ ++ if (!p) { ++ ctx->mstats.num_alloc_fail++; ++ print_oom(requested_size, ctx); ++ if (requested_size > ctx->mstats.biggest_alloc_fail) { ++ ctx->mstats.biggest_alloc_fail = requested_size; ++ ctx->mstats.biggest_alloc_fail_used = ++ ctx->poolset.totalloc; ++ } ++ } ++} ++ ++static void gen_malloc_reset_stats(struct malloc_ctx *ctx) ++{ ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ ctx->mstats.max_allocated = 0; ++ ctx->mstats.num_alloc_fail = 0; ++ ctx->mstats.biggest_alloc_fail = 0; ++ ctx->mstats.biggest_alloc_fail_used = 0; ++ malloc_unlock(ctx, exceptions); ++} ++ ++void malloc_reset_stats(void) ++{ ++ gen_malloc_reset_stats(&malloc_ctx); ++} ++ ++static void gen_malloc_get_stats(struct malloc_ctx *ctx, ++ struct malloc_stats *stats) ++{ ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ memcpy_unchecked(stats, &ctx->mstats, sizeof(*stats)); ++ stats->allocated = ctx->poolset.totalloc; ++ malloc_unlock(ctx, exceptions); ++} ++ ++void malloc_get_stats(struct malloc_stats *stats) ++{ ++ gen_malloc_get_stats(&malloc_ctx, stats); ++} ++ ++#else /* BufStats */ ++ ++static void raw_malloc_return_hook(void *p, size_t requested_size, ++ struct malloc_ctx *ctx ) ++{ ++ if (!p) ++ print_oom(requested_size, ctx); ++} ++ ++#endif /* BufStats */ ++ ++#ifdef BufValid ++static void raw_malloc_validate_pools(struct malloc_ctx *ctx) ++{ ++ size_t n; ++ ++ for (n = 0; n < ctx->pool_len; n++) ++ bpoolv(ctx->pool[n].buf); ++} ++#else ++static void raw_malloc_validate_pools(struct malloc_ctx *ctx __unused) ++{ ++} ++#endif ++ ++struct bpool_iterator { ++ struct bfhead *next_buf; ++ size_t pool_idx; ++}; ++ ++static void bpool_foreach_iterator_init(struct malloc_ctx *ctx, ++ struct bpool_iterator *iterator) ++{ ++ iterator->pool_idx = 0; ++ iterator->next_buf = BFH(ctx->pool[0].buf); ++} ++ ++static bool bpool_foreach_pool(struct bpool_iterator *iterator, void **buf, ++ size_t *len, bool *isfree) ++{ ++ struct bfhead *b = iterator->next_buf; ++ bufsize bs = b->bh.bsize; ++ ++ if (bs == ESent) ++ return false; ++ ++ if (bs < 0) { ++ /* Allocated buffer */ ++ bs = -bs; ++ ++ *isfree = false; ++ } else { ++ /* Free Buffer */ ++ *isfree = true; ++ ++ /* Assert that the free list links are intact */ ++ assert(b->ql.blink->ql.flink == b); ++ assert(b->ql.flink->ql.blink == b); ++ } ++ ++ *buf = (uint8_t *)b + sizeof(struct bhead); ++ *len = bs - sizeof(struct bhead); ++ ++ iterator->next_buf = BFH((uint8_t *)b + bs); ++ return true; ++} ++ ++static bool bpool_foreach(struct malloc_ctx *ctx, ++ struct bpool_iterator *iterator, void **buf) ++{ ++ while (true) { ++ size_t len; ++ bool isfree; ++ ++ if (bpool_foreach_pool(iterator, buf, &len, &isfree)) { ++ if (isfree) ++ continue; ++ return true; ++ } ++ ++ if ((iterator->pool_idx + 1) >= ctx->pool_len) ++ return false; ++ ++ iterator->pool_idx++; ++ iterator->next_buf = BFH(ctx->pool[iterator->pool_idx].buf); ++ } ++} ++ ++/* Convenience macro for looping over all allocated buffers */ ++#define BPOOL_FOREACH(ctx, iterator, bp) \ ++ for (bpool_foreach_iterator_init((ctx),(iterator)); \ ++ bpool_foreach((ctx),(iterator), (bp));) ++ ++static void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size, ++ struct malloc_ctx *ctx) ++{ ++ void *ptr = NULL; ++ bufsize s; ++ ++ /* ++ * Make sure that malloc has correct alignment of returned buffers. ++ * The assumption is that uintptr_t will be as wide as the largest ++ * required alignment of any type. ++ */ ++ COMPILE_TIME_ASSERT(SizeQuant >= sizeof(uintptr_t)); ++ ++ raw_malloc_validate_pools(ctx); ++ ++ /* Compute total size */ ++ if (ADD_OVERFLOW(pl_size, hdr_size, &s)) ++ goto out; ++ if (ADD_OVERFLOW(s, ftr_size, &s)) ++ goto out; ++ ++ /* BGET doesn't like 0 sized allocations */ ++ if (!s) ++ s++; ++ ++ ptr = bget(s, &ctx->poolset); ++out: ++ raw_malloc_return_hook(ptr, pl_size, ctx); ++ ++ return ptr; ++} ++ ++static void raw_free(void *ptr, struct malloc_ctx *ctx, bool wipe) ++{ ++ raw_malloc_validate_pools(ctx); ++ ++ if (ptr) ++ brel(ptr, &ctx->poolset, wipe); ++} ++ ++static void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb, ++ size_t pl_size, struct malloc_ctx *ctx) ++{ ++ void *ptr = NULL; ++ bufsize s; ++ ++ raw_malloc_validate_pools(ctx); ++ ++ /* Compute total size */ ++ if (MUL_OVERFLOW(pl_nmemb, pl_size, &s)) ++ goto out; ++ if (ADD_OVERFLOW(s, hdr_size, &s)) ++ goto out; ++ if (ADD_OVERFLOW(s, ftr_size, &s)) ++ goto out; ++ ++ /* BGET doesn't like 0 sized allocations */ ++ if (!s) ++ s++; ++ ++ ptr = bgetz(s, &ctx->poolset); ++out: ++ raw_malloc_return_hook(ptr, pl_nmemb * pl_size, ctx); ++ ++ return ptr; ++} ++ ++static void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size, ++ size_t pl_size, struct malloc_ctx *ctx) ++{ ++ void *p = NULL; ++ bufsize s; ++ ++ /* Compute total size */ ++ if (ADD_OVERFLOW(pl_size, hdr_size, &s)) ++ goto out; ++ if (ADD_OVERFLOW(s, ftr_size, &s)) ++ goto out; ++ ++ raw_malloc_validate_pools(ctx); ++ ++ /* BGET doesn't like 0 sized allocations */ ++ if (!s) ++ s++; ++ ++ p = bgetr(ptr, s, &ctx->poolset); ++out: ++ raw_malloc_return_hook(p, pl_size, ctx); ++ ++ return p; ++} ++ ++/* Most of the stuff in this function is copied from bgetr() in bget.c */ ++static __maybe_unused bufsize bget_buf_size(void *buf) ++{ ++ bufsize osize; /* Old size of buffer */ ++ struct bhead *b; ++ ++ b = BH(((char *)buf) - sizeof(struct bhead)); ++ osize = -b->bsize; ++#ifdef BECtl ++ if (osize == 0) { ++ /* Buffer acquired directly through acqfcn. */ ++ struct bdhead *bd; ++ ++ bd = BDH(((char *)buf) - sizeof(struct bdhead)); ++ osize = bd->tsize - sizeof(struct bdhead); ++ } else ++#endif ++ osize -= sizeof(struct bhead); ++ assert(osize > 0); ++ return osize; ++} ++ ++#ifdef ENABLE_MDBG ++ ++struct mdbg_hdr { ++ const char *fname; ++ uint16_t line; ++ uint32_t pl_size; ++ uint32_t magic; ++#if defined(ARM64) ++ uint64_t pad; ++#endif ++}; ++ ++#define MDBG_HEADER_MAGIC 0xadadadad ++#define MDBG_FOOTER_MAGIC 0xecececec ++ ++static size_t mdbg_get_ftr_size(size_t pl_size) ++{ ++ size_t ftr_pad = ROUNDUP(pl_size, sizeof(uint32_t)) - pl_size; ++ ++ return ftr_pad + sizeof(uint32_t); ++} ++ ++static uint32_t *mdbg_get_footer(struct mdbg_hdr *hdr) ++{ ++ uint32_t *footer; ++ ++ footer = (uint32_t *)((uint8_t *)(hdr + 1) + hdr->pl_size + ++ mdbg_get_ftr_size(hdr->pl_size)); ++ footer--; ++ return footer; ++} ++ ++static void mdbg_update_hdr(struct mdbg_hdr *hdr, const char *fname, ++ int lineno, size_t pl_size) ++{ ++ uint32_t *footer; ++ ++ hdr->fname = fname; ++ hdr->line = lineno; ++ hdr->pl_size = pl_size; ++ hdr->magic = MDBG_HEADER_MAGIC; ++ ++ footer = mdbg_get_footer(hdr); ++ *footer = MDBG_FOOTER_MAGIC; ++} ++ ++static void *gen_mdbg_malloc(struct malloc_ctx *ctx, const char *fname, ++ int lineno, size_t size) ++{ ++ struct mdbg_hdr *hdr; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ /* ++ * Check struct mdbg_hdr doesn't get bad alignment. ++ * This is required by C standard: the buffer returned from ++ * malloc() should be aligned with a fundamental alignment. ++ * For ARM32, the required alignment is 8. For ARM64, it is 16. ++ */ ++ COMPILE_TIME_ASSERT( ++ (sizeof(struct mdbg_hdr) % (__alignof(uintptr_t) * 2)) == 0); ++ ++ hdr = raw_malloc(sizeof(struct mdbg_hdr), ++ mdbg_get_ftr_size(size), size, ctx); ++ if (hdr) { ++ mdbg_update_hdr(hdr, fname, lineno, size); ++ hdr++; ++ } ++ ++ malloc_unlock(ctx, exceptions); ++ return hdr; ++} ++ ++static void assert_header(struct mdbg_hdr *hdr __maybe_unused) ++{ ++ assert(hdr->magic == MDBG_HEADER_MAGIC); ++ assert(*mdbg_get_footer(hdr) == MDBG_FOOTER_MAGIC); ++} ++ ++static void gen_mdbg_free(struct malloc_ctx *ctx, void *ptr, bool wipe) ++{ ++ struct mdbg_hdr *hdr = ptr; ++ ++ if (hdr) { ++ hdr--; ++ assert_header(hdr); ++ hdr->magic = 0; ++ *mdbg_get_footer(hdr) = 0; ++ raw_free(hdr, ctx, wipe); ++ } ++} ++ ++static void free_helper(void *ptr, bool wipe) ++{ ++ uint32_t exceptions = malloc_lock(&malloc_ctx); ++ ++ gen_mdbg_free(&malloc_ctx, ptr, wipe); ++ malloc_unlock(&malloc_ctx, exceptions); ++} ++ ++static void *gen_mdbg_calloc(struct malloc_ctx *ctx, const char *fname, int lineno, ++ size_t nmemb, size_t size) ++{ ++ struct mdbg_hdr *hdr; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ hdr = raw_calloc(sizeof(struct mdbg_hdr), ++ mdbg_get_ftr_size(nmemb * size), nmemb, size, ++ ctx); ++ if (hdr) { ++ mdbg_update_hdr(hdr, fname, lineno, nmemb * size); ++ hdr++; ++ } ++ malloc_unlock(ctx, exceptions); ++ return hdr; ++} ++ ++static void *gen_mdbg_realloc_unlocked(struct malloc_ctx *ctx, const char *fname, ++ int lineno, void *ptr, size_t size) ++{ ++ struct mdbg_hdr *hdr = ptr; ++ ++ if (hdr) { ++ hdr--; ++ assert_header(hdr); ++ } ++ hdr = raw_realloc(hdr, sizeof(struct mdbg_hdr), ++ mdbg_get_ftr_size(size), size, ctx); ++ if (hdr) { ++ mdbg_update_hdr(hdr, fname, lineno, size); ++ hdr++; ++ } ++ return hdr; ++} ++ ++static void *gen_mdbg_realloc(struct malloc_ctx *ctx, const char *fname, ++ int lineno, void *ptr, size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ p = gen_mdbg_realloc_unlocked(ctx, fname, lineno, ptr, size); ++ malloc_unlock(ctx, exceptions); ++ return p; ++} ++ ++#define realloc_unlocked(ctx, ptr, size) \ ++ gen_mdbg_realloc_unlocked(ctx, __FILE__, __LINE__, (ptr), (size)) ++ ++static void *get_payload_start_size(void *raw_buf, size_t *size) ++{ ++ struct mdbg_hdr *hdr = raw_buf; ++ ++ assert(bget_buf_size(hdr) >= hdr->pl_size); ++ *size = hdr->pl_size; ++ return hdr + 1; ++} ++ ++static void gen_mdbg_check(struct malloc_ctx *ctx, int bufdump) ++{ ++ struct bpool_iterator itr; ++ void *b; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ raw_malloc_validate_pools(ctx); ++ ++ BPOOL_FOREACH(ctx, &itr, &b) { ++ struct mdbg_hdr *hdr = (struct mdbg_hdr *)b; ++ ++ assert_header(hdr); ++ ++ if (bufdump > 0) { ++ const char *fname = hdr->fname; ++ ++ if (!fname) ++ fname = "unknown"; ++ ++ IMSG("buffer: %d bytes %s:%d\n", ++ hdr->pl_size, fname, hdr->line); ++ } ++ } ++ ++ malloc_unlock(ctx, exceptions); ++} ++ ++void *mdbg_malloc(const char *fname, int lineno, size_t size) ++{ ++ return gen_mdbg_malloc(&malloc_ctx, fname, lineno, size); ++} ++ ++void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) ++{ ++ return gen_mdbg_calloc(&malloc_ctx, fname, lineno, nmemb, size); ++} ++ ++void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) ++{ ++ return gen_mdbg_realloc(&malloc_ctx, fname, lineno, ptr, size); ++} ++ ++void mdbg_check(int bufdump) ++{ ++ gen_mdbg_check(&malloc_ctx, bufdump); ++} ++#else ++ ++void *malloc(size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&malloc_ctx); ++ ++ p = raw_malloc(0, 0, size, &malloc_ctx); ++ malloc_unlock(&malloc_ctx, exceptions); ++ return p; ++} ++ ++static void free_helper(void *ptr, bool wipe) ++{ ++ uint32_t exceptions = malloc_lock(&malloc_ctx); ++ ++ raw_free(ptr, &malloc_ctx, wipe); ++ malloc_unlock(&malloc_ctx, exceptions); ++} ++ ++void *calloc(size_t nmemb, size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&malloc_ctx); ++ ++ p = raw_calloc(0, 0, nmemb, size, &malloc_ctx); ++ malloc_unlock(&malloc_ctx, exceptions); ++ return p; ++} ++ ++static void *realloc_unlocked(struct malloc_ctx *ctx, void *ptr, ++ size_t size) ++{ ++ return raw_realloc(ptr, 0, 0, size, ctx); ++} ++ ++void *realloc(void *ptr, size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&malloc_ctx); ++ ++ p = realloc_unlocked(&malloc_ctx, ptr, size); ++ malloc_unlock(&malloc_ctx, exceptions); ++ return p; ++} ++ ++static void *get_payload_start_size(void *ptr, size_t *size) ++{ ++ *size = bget_buf_size(ptr); ++ return ptr; ++} ++ ++#endif ++ ++void free(void *ptr) ++{ ++ free_helper(ptr, false); ++} ++ ++void free_wipe(void *ptr) ++{ ++ free_helper(ptr, true); ++} ++ ++static void gen_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len) ++{ ++ void *p; ++ size_t l; ++ uint32_t exceptions; ++ uintptr_t start = (uintptr_t)buf; ++ uintptr_t end = start + len; ++ const size_t min_len = ((sizeof(struct malloc_pool) + (SizeQuant - 1)) & ++ (~(SizeQuant - 1))) + ++ sizeof(struct bhead) * 2; ++ ++ ++ start = ROUNDUP(start, SizeQuant); ++ end = ROUNDDOWN(end, SizeQuant); ++ assert(start < end); ++ ++ if ((end - start) < min_len) { ++ DMSG("Skipping too small pool"); ++ return; ++ } ++ ++ exceptions = malloc_lock(ctx); ++ ++ tag_asan_free((void *)start, end - start); ++ bpool((void *)start, end - start, &ctx->poolset); ++ l = ctx->pool_len + 1; ++ p = realloc_unlocked(ctx, ctx->pool, sizeof(struct malloc_pool) * l); ++ assert(p); ++ ctx->pool = p; ++ ctx->pool[ctx->pool_len].buf = (void *)start; ++ ctx->pool[ctx->pool_len].len = end - start; ++#ifdef BufStats ++ ctx->mstats.size += ctx->pool[ctx->pool_len].len; ++#endif ++ ctx->pool_len = l; ++ malloc_unlock(ctx, exceptions); ++} ++ ++static bool gen_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, ++ void *buf, size_t len) ++{ ++ struct bpool_iterator itr; ++ void *b; ++ uint8_t *start_buf = buf; ++ uint8_t *end_buf = start_buf + len; ++ bool ret = false; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ raw_malloc_validate_pools(ctx); ++ ++ /* Check for wrapping */ ++ if (start_buf > end_buf) ++ goto out; ++ ++ BPOOL_FOREACH(ctx, &itr, &b) { ++ uint8_t *start_b; ++ uint8_t *end_b; ++ size_t s; ++ ++ start_b = get_payload_start_size(b, &s); ++ end_b = start_b + s; ++ ++ if (start_buf >= start_b && end_buf <= end_b) { ++ ret = true; ++ goto out; ++ } ++ } ++ ++out: ++ malloc_unlock(ctx, exceptions); ++ ++ return ret; ++} ++ ++static bool gen_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, ++ void *buf, size_t len) ++{ ++ uintptr_t buf_start = (uintptr_t) buf; ++ uintptr_t buf_end = buf_start + len; ++ size_t n; ++ bool ret = false; ++ uint32_t exceptions = malloc_lock(ctx); ++ ++ raw_malloc_validate_pools(ctx); ++ ++ for (n = 0; n < ctx->pool_len; n++) { ++ uintptr_t pool_start = (uintptr_t)ctx->pool[n].buf; ++ uintptr_t pool_end = pool_start + ctx->pool[n].len; ++ ++ if (buf_start > buf_end || pool_start > pool_end) { ++ ret = true; /* Wrapping buffers, shouldn't happen */ ++ goto out; ++ } ++ ++ if (buf_end > pool_start || buf_start < pool_end) { ++ ret = true; ++ goto out; ++ } ++ } ++ ++out: ++ malloc_unlock(ctx, exceptions); ++ return ret; ++} ++ ++void malloc_add_pool(void *buf, size_t len) ++{ ++ gen_malloc_add_pool(&malloc_ctx, buf, len); ++} ++ ++bool malloc_buffer_is_within_alloced(void *buf, size_t len) ++{ ++ return gen_malloc_buffer_is_within_alloced(&malloc_ctx, buf, len); ++} ++ ++bool malloc_buffer_overlaps_heap(void *buf, size_t len) ++{ ++ return gen_malloc_buffer_overlaps_heap(&malloc_ctx, buf, len); ++} ++ ++#ifdef CFG_VIRTUALIZATION ++ ++#ifndef ENABLE_MDBG ++ ++void *nex_malloc(size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&nex_malloc_ctx); ++ ++ p = raw_malloc(0, 0, size, &nex_malloc_ctx); ++ malloc_unlock(&nex_malloc_ctx, exceptions); ++ return p; ++} ++ ++void *nex_calloc(size_t nmemb, size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&nex_malloc_ctx); ++ ++ p = raw_calloc(0, 0, nmemb, size, &nex_malloc_ctx); ++ malloc_unlock(&nex_malloc_ctx, exceptions); ++ return p; ++} ++ ++void *nex_realloc(void *ptr, size_t size) ++{ ++ void *p; ++ uint32_t exceptions = malloc_lock(&nex_malloc_ctx); ++ ++ p = realloc_unlocked(&nex_malloc_ctx, ptr, size); ++ malloc_unlock(&nex_malloc_ctx, exceptions); ++ return p; ++} ++ ++void nex_free(void *ptr) ++{ ++ uint32_t exceptions = malloc_lock(&nex_malloc_ctx); ++ ++ raw_free(ptr, &nex_malloc_ctx, false /* !wipe */); ++ malloc_unlock(&nex_malloc_ctx, exceptions); ++} ++ ++#else /* ENABLE_MDBG */ ++ ++void *nex_mdbg_malloc(const char *fname, int lineno, size_t size) ++{ ++ return gen_mdbg_malloc(&nex_malloc_ctx, fname, lineno, size); ++} ++ ++void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) ++{ ++ return gen_mdbg_calloc(&nex_malloc_ctx, fname, lineno, nmemb, size); ++} ++ ++void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) ++{ ++ return gen_mdbg_realloc(&nex_malloc_ctx, fname, lineno, ptr, size); ++} ++ ++void nex_mdbg_check(int bufdump) ++{ ++ gen_mdbg_check(&nex_malloc_ctx, bufdump); ++} ++ ++void nex_free(void *ptr) ++{ ++ uint32_t exceptions = malloc_lock(&nex_malloc_ctx); ++ ++ gen_mdbg_free(&nex_malloc_ctx, ptr, false /* !wipe */); ++ malloc_unlock(&nex_malloc_ctx, exceptions); ++} ++ ++#endif /* ENABLE_MDBG */ ++ ++void nex_malloc_add_pool(void *buf, size_t len) ++{ ++ gen_malloc_add_pool(&nex_malloc_ctx, buf, len); ++} ++ ++bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len) ++{ ++ return gen_malloc_buffer_is_within_alloced(&nex_malloc_ctx, buf, len); ++} ++ ++bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len) ++{ ++ return gen_malloc_buffer_overlaps_heap(&nex_malloc_ctx, buf, len); ++} ++ ++#ifdef BufStats ++ ++void nex_malloc_reset_stats(void) ++{ ++ gen_malloc_reset_stats(&nex_malloc_ctx); ++} ++ ++void nex_malloc_get_stats(struct malloc_stats *stats) ++{ ++ gen_malloc_get_stats(&nex_malloc_ctx, stats); ++} ++ ++#endif ++ ++#endif +diff --git a/environments/shim/lib/libc/memcmp.c b/environments/shim/lib/libc/memcmp.c +new file mode 100644 +index 0000000..a4c798b +--- /dev/null ++++ b/environments/shim/lib/libc/memcmp.c +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++int memcmp(const void *s1, const void *s2, size_t len) ++{ ++ const unsigned char *s = s1; ++ const unsigned char *d = s2; ++ unsigned char sc; ++ unsigned char dc; ++ ++ while (len--) { ++ sc = *s++; ++ dc = *d++; ++ if (sc - dc) ++ return (sc - dc); ++ } ++ ++ return 0; ++} +diff --git a/environments/shim/lib/libc/memcpy.c b/environments/shim/lib/libc/memcpy.c +new file mode 100644 +index 0000000..fc0c9fe +--- /dev/null ++++ b/environments/shim/lib/libc/memcpy.c +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++void *memcpy(void *dst, const void *src, size_t len) ++{ ++ const char *s = src; ++ char *d = dst; ++ ++ while (len--) ++ *d++ = *s++; ++ ++ return dst; ++} +diff --git a/environments/shim/lib/libc/memmove.c b/environments/shim/lib/libc/memmove.c +new file mode 100644 +index 0000000..63acf26 +--- /dev/null ++++ b/environments/shim/lib/libc/memmove.c +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++void *memmove(void *dst, const void *src, size_t len) ++{ ++ /* ++ * The following test makes use of unsigned arithmetic overflow to ++ * more efficiently test the condition !(src <= dst && dst < str+len). ++ * It also avoids the situation where the more explicit test would give ++ * incorrect results were the calculation str+len to overflow (though ++ * that issue is probably moot as such usage is probably undefined ++ * behaviour and a bug anyway. ++ */ ++ if ((size_t)dst - (size_t)src >= len) { ++ /* destination not in source data, so can safely use memcpy */ ++ return memcpy(dst, src, len); ++ } else { ++ /* copy backwards... */ ++ const char *end = dst; ++ const char *s = (const char *)src + len; ++ char *d = (char *)dst + len; ++ while (d != end) ++ *--d = *--s; ++ } ++ return dst; ++} +diff --git a/environments/shim/lib/libc/memset.c b/environments/shim/lib/libc/memset.c +new file mode 100644 +index 0000000..03aa809 +--- /dev/null ++++ b/environments/shim/lib/libc/memset.c +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++void *memset(void *dst, int val, size_t count) ++{ ++ char *ptr = dst; ++ ++ while (count--) ++ *ptr++ = val; ++ ++ return dst; ++} +diff --git a/environments/shim/lib/libc/printf.c b/environments/shim/lib/libc/printf.c +new file mode 100644 +index 0000000..60203fb +--- /dev/null ++++ b/environments/shim/lib/libc/printf.c +@@ -0,0 +1,251 @@ ++/* ++ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define get_num_va_args(_args, _lcount) \ ++ (((_lcount) > 1) ? va_arg(_args, long long int) : \ ++ (((_lcount) == 1) ? va_arg(_args, long int) : \ ++ va_arg(_args, int))) ++ ++#define get_unum_va_args(_args, _lcount) \ ++ (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \ ++ (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \ ++ va_arg(_args, unsigned int))) ++ ++static int string_print(const char *str, char padc, int padn) ++{ ++ int i = 0, count = 0; ++ ++ assert(str != NULL); ++ ++ while (str[i] != '\0') ++ i++; ++ ++ if (padn > 0) { ++ while (i < padn) { ++ (void)putchar(padc); ++ count++; ++ padn--; ++ } ++ } ++ ++ for ( ; *str != '\0'; str++) { ++ (void)putchar(*str); ++ count++; ++ } ++ ++ if (padn < 0) { ++ while (i < -padn) { ++ (void)putchar(padc); ++ count++; ++ padn++; ++ } ++ } ++ ++ return count; ++} ++ ++static int unsigned_num_print(unsigned long long int unum, unsigned int radix, ++ char padc, int padn) ++{ ++ /* Just need enough space to store 64 bit decimal integer */ ++ char num_buf[20]; ++ int i = 0, count = 0; ++ int width; ++ unsigned int rem; ++ ++ do { ++ rem = unum % radix; ++ if (rem < 0xa) ++ num_buf[i] = '0' + rem; ++ else ++ num_buf[i] = 'a' + (rem - 0xa); ++ i++; ++ unum /= radix; ++ } while (unum > 0U); ++ ++ width = i; ++ ++ if (padn > 0) { ++ while (width < padn) { ++ (void)putchar(padc); ++ count++; ++ padn--; ++ } ++ } ++ ++ while (--i >= 0) { ++ (void)putchar(num_buf[i]); ++ count++; ++ } ++ ++ if (padn < 0) { ++ while (width < -padn) { ++ (void)putchar(padc); ++ count++; ++ padn++; ++ } ++ } ++ ++ return count; ++} ++ ++/******************************************************************* ++ * Simplified version of printf() with smaller memory footprint. ++ * The following type specifiers are supported by this print ++ * %x - hexadecimal format ++ * %s - string format ++ * %d or %i - signed decimal format ++ * %u - unsigned decimal format ++ * %p - pointer format ++ * ++ * The following length specifiers are supported by this print ++ * %l - long int (64-bit on AArch64) ++ * %ll - long long int (64-bit on AArch64) ++ * %z - size_t sized integer formats (64 bit on AArch64) ++ * ++ * The following padding specifiers are supported by this print ++ * %0NN - Left-pad the number with 0s (NN is a decimal number) ++ * %NN - Left-pad the number or string with spaces (NN is a decimal number) ++ * %-NN - Right-pad the number or string with spaces (NN is a decimal number) ++ * ++ * The print exits on all other formats specifiers other than valid ++ * combinations of the above specifiers. ++ *******************************************************************/ ++int vprintf(const char *fmt, va_list args) ++{ ++ int l_count; ++ int left; ++ long long int num; ++ unsigned long long int unum; ++ char *str; ++ char padc; /* Padding character */ ++ int padn; /* Number of characters to pad */ ++ int count = 0; /* Number of printed characters */ ++ ++ while (*fmt != '\0') { ++ l_count = 0; ++ left = 0; ++ padc = '\0'; ++ padn = 0; ++ ++ if (*fmt == '%') { ++ fmt++; ++ /* Check the format specifier */ ++loop: ++ switch (*fmt) { ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ padc = ' '; ++ for (padn = 0; *fmt >= '0' && *fmt <= '9'; fmt++) ++ padn = (padn * 10) + (*fmt - '0'); ++ if (left) ++ padn = -padn; ++ goto loop; ++ case '-': ++ left = 1; ++ fmt++; ++ goto loop; ++ case 'i': /* Fall through to next one */ ++ case 'd': ++ num = get_num_va_args(args, l_count); ++ if (num < 0) { ++ (void)putchar('-'); ++ unum = (unsigned long long int)-num; ++ padn--; ++ } else ++ unum = (unsigned long long int)num; ++ ++ count += unsigned_num_print(unum, 10, ++ padc, padn); ++ break; ++ case 's': ++ str = va_arg(args, char *); ++ count += string_print(str, padc, padn); ++ break; ++ case 'p': ++ unum = (uintptr_t)va_arg(args, void *); ++ if (unum > 0U) { ++ count += string_print("0x", padc, 0); ++ padn -= 2; ++ } ++ ++ count += unsigned_num_print(unum, 16, ++ padc, padn); ++ break; ++ case 'x': ++ unum = get_unum_va_args(args, l_count); ++ count += unsigned_num_print(unum, 16, ++ padc, padn); ++ break; ++ case 'z': ++ if (sizeof(size_t) == 8U) ++ l_count = 2; ++ ++ fmt++; ++ goto loop; ++ case 'l': ++ l_count++; ++ fmt++; ++ goto loop; ++ case 'u': ++ unum = get_unum_va_args(args, l_count); ++ count += unsigned_num_print(unum, 10, ++ padc, padn); ++ break; ++ case '0': ++ padc = '0'; ++ padn = 0; ++ fmt++; ++ ++ for (;;) { ++ char ch = *fmt; ++ if ((ch < '0') || (ch > '9')) { ++ goto loop; ++ } ++ padn = (padn * 10) + (ch - '0'); ++ fmt++; ++ } ++ assert(0); /* Unreachable */ ++ default: ++ /* Exit on any other format specifier */ ++ return -1; ++ } ++ fmt++; ++ continue; ++ } ++ (void)putchar(*fmt); ++ fmt++; ++ count++; ++ } ++ ++ return count; ++} ++ ++int printf(const char *fmt, ...) ++{ ++ int count; ++ va_list va; ++ ++ va_start(va, fmt); ++ count = vprintf(fmt, va); ++ va_end(va); ++ ++ return count; ++} +diff --git a/environments/shim/lib/libc/putchar.c b/environments/shim/lib/libc/putchar.c +new file mode 100644 +index 0000000..037e28a +--- /dev/null ++++ b/environments/shim/lib/libc/putchar.c +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++ ++int putchar(int c) ++{ ++ int res; ++ if (console_putc((unsigned char)c) >= 0) ++ res = c; ++ else ++ res = EOF; ++ ++ return res; ++} +diff --git a/environments/shim/lib/libc/rand.c b/environments/shim/lib/libc/rand.c +new file mode 100644 +index 0000000..59cb796 +--- /dev/null ++++ b/environments/shim/lib/libc/rand.c +@@ -0,0 +1,65 @@ ++/*- ++ * Portions Copyright (c) 2010, Intel Corporation. All rights reserved.
++ * Copyright (c) 1990, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++//__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.17.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $"); ++#include ++ ++static unsigned int next = 1; ++ ++/** Compute a pseudo-random number. ++ * ++ * Compute x = (7^5 * x) mod (2^31 - 1) ++ * without overflowing 31 bits: ++ * (2^31 - 1) = 127773 * (7^5) + 2836 ++ * From "Random number generators: good ones are hard to find", ++ * Park and Miller, Communications of the ACM, vol. 31, no. 10, ++ * October 1988, p. 1195. ++**/ ++int ++rand() ++{ ++ int hi, lo, x; ++ ++ /* Can't be initialized with 0, so use another value. */ ++ if (next == 0) ++ next = 123459876; ++ hi = next / 127773; ++ lo = next % 127773; ++ x = 16807 * lo - 2836 * hi; ++ if (x < 0) ++ x += 0x7fffffff; ++ return ((next = x) % ((unsigned int)RAND_MAX + 1)); ++} ++ ++void ++srand(unsigned int seed) ++{ ++ next = (unsigned int)seed; ++} +diff --git a/environments/shim/lib/libc/snprintf.c b/environments/shim/lib/libc/snprintf.c +new file mode 100644 +index 0000000..ef15a26 +--- /dev/null ++++ b/environments/shim/lib/libc/snprintf.c +@@ -0,0 +1,250 @@ ++/* ++ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++//#include ++ ++#define get_num_va_args(_args, _lcount) \ ++ (((_lcount) > 1) ? va_arg(_args, long long int) : \ ++ (((_lcount) == 1) ? va_arg(_args, long int) : \ ++ va_arg(_args, int))) ++ ++#define get_unum_va_args(_args, _lcount) \ ++ (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \ ++ (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \ ++ va_arg(_args, unsigned int))) ++ ++static void string_print(char **s, size_t n, size_t *chars_printed, ++ const char *str) ++{ ++ while (*str != '\0') { ++ if (*chars_printed < n) { ++ *(*s) = *str; ++ (*s)++; ++ } ++ ++ (*chars_printed)++; ++ str++; ++ } ++} ++ ++static void unsigned_num_print(char **s, size_t n, size_t *count, ++ unsigned long long int unum, unsigned int radix, ++ char padc, int padn) ++{ ++ /* Just need enough space to store 64 bit decimal integer */ ++ char num_buf[20]; ++ int i = 0; ++ int width; ++ unsigned int rem; ++ ++ do { ++ rem = unum % radix; ++ if (rem < 0xa) ++ num_buf[i] = '0' + rem; ++ else ++ num_buf[i] = 'a' + (rem - 0xa); ++ i++; ++ unum /= radix; ++ } while (unum > 0U); ++ ++ width = i; ++ ++ if (padn > 0) { ++ while (width < padn) { ++ if (*count < n) { ++ *(*s) = padc; ++ (*s)++; ++ } ++ (*count)++; ++ padn--; ++ } ++ } ++ ++ while (--i >= 0) { ++ if (*count < n) { ++ *(*s) = num_buf[i]; ++ (*s)++; ++ } ++ (*count)++; ++ } ++ ++ if (padn < 0) { ++ while (width < -padn) { ++ if (*count < n) { ++ *(*s) = padc; ++ (*s)++; ++ } ++ (*count)++; ++ padn++; ++ } ++ } ++} ++ ++/* ++ * Scaled down version of vsnprintf(3). ++ */ ++int vsnprintf(char *s, size_t n, const char *fmt, va_list args) ++{ ++ int l_count; ++ int left; ++ char *str; ++ int num; ++ unsigned long long int unum; ++ char padc; /* Padding character */ ++ int padn; /* Number of characters to pad */ ++ size_t count = 0U; ++ ++ if (n == 0U) { ++ /* There isn't space for anything. */ ++ } else if (n == 1U) { ++ /* Buffer is too small to actually write anything else. */ ++ *s = '\0'; ++ n = 0U; ++ } else { ++ /* Reserve space for the terminator character. */ ++ n--; ++ } ++ ++ while (*fmt != '\0') { ++ l_count = 0; ++ left = 0; ++ padc = '\0'; ++ padn = 0; ++ ++ if (*fmt == '%') { ++ fmt++; ++ /* Check the format specifier. */ ++loop: ++ switch (*fmt) { ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ padc = ' '; ++ for (padn = 0; *fmt >= '0' && *fmt <= '9'; fmt++) ++ padn = (padn * 10) + (*fmt - '0'); ++ if (left) ++ padn = -padn; ++ goto loop; ++ case '-': ++ left = 1; ++ fmt++; ++ goto loop; ++ case 'i': ++ case 'd': ++ num = get_num_va_args(args, l_count); ++ ++ if (num < 0) { ++ if (count < n) { ++ *s = '-'; ++ s++; ++ } ++ count++; ++ ++ unum = (unsigned int)-num; ++ } else { ++ unum = (unsigned int)num; ++ } ++ ++ unsigned_num_print(&s, n, &count, unum, 10, ++ padc, padn); ++ break; ++ case 'l': ++ l_count++; ++ fmt++; ++ goto loop; ++ case 's': ++ str = va_arg(args, char *); ++ string_print(&s, n, &count, str); ++ break; ++ case 'u': ++ unum = get_unum_va_args(args, l_count); ++ unsigned_num_print(&s, n, &count, unum, 10, ++ padc, padn); ++ break; ++ case 'x': ++ unum = get_unum_va_args(args, l_count); ++ unsigned_num_print(&s, n, &count, unum, 16, ++ padc, padn); ++ break; ++ case '0': ++ padc = '0'; ++ padn = 0; ++ fmt++; ++ ++ for (;;) { ++ char ch = *fmt; ++ if ((ch < '0') || (ch > '9')) { ++ goto loop; ++ } ++ padn = (padn * 10) + (ch - '0'); ++ fmt++; ++ } ++ assert(0); /* Unreachable */ ++ default: ++ /* ++ * Exit on any other format specifier and abort ++ * when in debug mode. ++ */ ++ WARN("snprintf: specifier with ASCII code '%d' not supported.\n", ++ *fmt); ++ assert(0); ++ return -1; ++ } ++ fmt++; ++ continue; ++ } ++ ++ if (count < n) { ++ *s = *fmt; ++ s++; ++ } ++ ++ fmt++; ++ count++; ++ } ++ ++ if (n > 0U) ++ *s = '\0'; ++ ++ return (int)count; ++} ++ ++/******************************************************************* ++ * Reduced snprintf to be used for Trusted firmware. ++ * The following type specifiers are supported: ++ * ++ * %d or %i - signed decimal format ++ * %s - string format ++ * %u - unsigned decimal format ++ * ++ * The function panics on all other formats specifiers. ++ * ++ * It returns the number of characters that would be written if the ++ * buffer was big enough. If it returns a value lower than n, the ++ * whole string has been written. ++ *******************************************************************/ ++int snprintf(char *s, size_t n, const char *fmt, ...) ++{ ++ va_list args; ++ int chars_printed; ++ ++ va_start(args, fmt); ++ chars_printed = vsnprintf(s, n, fmt, args); ++ va_end(args); ++ ++ return chars_printed; ++} +diff --git a/environments/shim/lib/libc/strcmp.c b/environments/shim/lib/libc/strcmp.c +new file mode 100644 +index 0000000..b742f9b +--- /dev/null ++++ b/environments/shim/lib/libc/strcmp.c +@@ -0,0 +1,52 @@ ++/*- ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * Copyright (c) 1990, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * This code is derived from software contributed to Berkeley by ++ * Chris Torek. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * Portions copyright (c) 2018, ARM Limited and Contributors. ++ * All rights reserved. ++ */ ++ ++#include ++ ++/* ++ * Compare strings. ++ */ ++int ++strcmp(const char *s1, const char *s2) ++{ ++ while (*s1 == *s2++) ++ if (*s1++ == '\0') ++ return (0); ++ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); ++} +diff --git a/environments/shim/lib/libc/strlen.c b/environments/shim/lib/libc/strlen.c +new file mode 100644 +index 0000000..3c27630 +--- /dev/null ++++ b/environments/shim/lib/libc/strlen.c +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++size_t strlen(const char *s) ++{ ++ const char *cursor = s; ++ ++ while (*cursor) ++ cursor++; ++ ++ return cursor - s; ++} +diff --git a/environments/shim/lib/libc/strstr.c b/environments/shim/lib/libc/strstr.c +new file mode 100644 +index 0000000..572011e +--- /dev/null ++++ b/environments/shim/lib/libc/strstr.c +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++ ++char* strstr(const char* hay, const char* needle) ++{ ++ if (*needle == '\0') ++ return hay; ++ ++ for (int i = 0; i < strlen(hay); i++) ++ { ++ if (*(hay + i) == *needle) ++ { ++ char* ptr = strstr(hay + i + 1, needle + 1); ++ return (ptr) ? ptr - 1 : NULL; ++ } ++ } ++ ++ return NULL; ++} +diff --git a/environments/shim/lib/locks/aarch64/spinlock.S b/environments/shim/lib/locks/aarch64/spinlock.S +new file mode 100644 +index 0000000..1438f54 +--- /dev/null ++++ b/environments/shim/lib/locks/aarch64/spinlock.S +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++ ++ .globl init_spinlock ++ .globl spin_lock ++ .globl spin_unlock ++ ++func init_spinlock ++ str wzr, [x0] ++ ret ++endfunc init_spinlock ++ ++func spin_lock ++ mov w2, #1 ++ sevl ++l1: wfe ++l2: ldaxr w1, [x0] ++ cbnz w1, l1 ++ stxr w1, w2, [x0] ++ cbnz w1, l2 ++ ret ++endfunc spin_lock ++ ++ ++func spin_unlock ++ stlr wzr, [x0] ++ ret ++endfunc spin_unlock +diff --git a/environments/shim/lib/smc/aarch64/asm_smc.S b/environments/shim/lib/smc/aarch64/asm_smc.S +new file mode 100644 +index 0000000..b396986 +--- /dev/null ++++ b/environments/shim/lib/smc/aarch64/asm_smc.S +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2013-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++ ++ .section .text, "ax" ++ ++ .macro smccc_conduit _conduit ++ ++ /* ++ * According to the AAPCS64, x8 is the indirect result location ++ * register. It contains the address of the memory block that the caller ++ * has reserved to hold the result, i.e. the smc_ret_values structure ++ * in our case. ++ * x8 might be clobbered across the SMC call so save it on the stack. ++ * Although x8 contains an 8 byte value, we are allocating 16bytes on the stack ++ * to respect 16byte stack-alignment. ++ */ ++ str x8, [sp, #-16]! ++ ++ /* "Conduit" arguments are already stored in x0-x7 */ ++ \_conduit #0 ++ ++ /* Pop x8 into a caller-saved register */ ++ ldr x9, [sp], #16 ++ ++ /* ++ * Return values are stored in x0-x7, put them in the 'smc_ret_values' ++ * return structure ++ */ ++ stp x0, x1, [x9, #0] ++ stp x2, x3, [x9, #16] ++ stp x4, x5, [x9, #32] ++ stp x6, x7, [x9, #48] ++ ++ .endm ++ ++/* --------------------------------------------------------------------------- ++ * smc_ret_values asm_tftf_smc64(uint32_t fid, ++ * u_register_t arg1, ++ * u_register_t arg2, ++ * u_register_t arg3, ++ * u_register_t arg4, ++ * u_register_t arg5, ++ * u_register_t arg6, ++ * u_register_t arg7); ++ * --------------------------------------------------------------------------- ++ */ ++ .globl asm_tftf_smc64 ++ ++func asm_tftf_smc64 ++ smccc_conduit smc ++ ret ++endfunc asm_tftf_smc64 ++ ++/* --------------------------------------------------------------------------- ++ * hvc_ret_values asm_tftf_hvcc64(uint32_t fid, ++ * u_register_t arg1, ++ * u_register_t arg2, ++ * u_register_t arg3, ++ * u_register_t arg4, ++ * u_register_t arg5, ++ * u_register_t arg6, ++ * u_register_t arg7); ++ * --------------------------------------------------------------------------- ++ */ ++ .globl asm_tftf_hvc64 ++ ++func asm_tftf_hvc64 ++ smccc_conduit hvc ++ ret ++endfunc asm_tftf_hvc64 +diff --git a/environments/shim/lib/smc/aarch64/hvc.c b/environments/shim/lib/smc/aarch64/hvc.c +new file mode 100644 +index 0000000..c833864 +--- /dev/null ++++ b/environments/shim/lib/smc/aarch64/hvc.c +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#include ++#include ++ ++hvc_ret_values asm_tftf_hvc64(uint32_t fid, ++ u_register_t arg1, ++ u_register_t arg2, ++ u_register_t arg3, ++ u_register_t arg4, ++ u_register_t arg5, ++ u_register_t arg6, ++ u_register_t arg7); ++ ++hvc_ret_values tftf_hvc(const hvc_args *args) ++{ ++ return asm_tftf_hvc64(args->fid, ++ args->arg1, ++ args->arg2, ++ args->arg3, ++ args->arg4, ++ args->arg5, ++ args->arg6, ++ args->arg7); ++} +diff --git a/environments/shim/lib/utils/mp_printf.c b/environments/shim/lib/utils/mp_printf.c +new file mode 100644 +index 0000000..777c736 +--- /dev/null ++++ b/environments/shim/lib/utils/mp_printf.c +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++/* Lock to avoid concurrent accesses to the serial console */ ++static spinlock_t printf_lock; ++ ++void mp_printf(const char *fmt, ...) ++{ ++ va_list args; ++ va_start(args, fmt); ++ ++ spin_lock(&printf_lock); ++ vprintf(fmt, args); ++ spin_unlock(&printf_lock); ++ ++ va_end(args); ++} +diff --git a/environments/shim/lib/xlat_tables_v2/aarch64/enable_mmu.S b/environments/shim/lib/xlat_tables_v2/aarch64/enable_mmu.S +new file mode 100644 +index 0000000..00e3d51 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/aarch64/enable_mmu.S +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++ ++ .global enable_mmu_direct_el1 ++ .global enable_mmu_direct_el2 ++ .global enable_mmu_direct_el3 ++ ++ /* Macros to read and write to system register for a given EL. */ ++ .macro _msr reg_name, el, gp_reg ++ msr \reg_name\()_el\()\el, \gp_reg ++ .endm ++ ++ .macro _mrs gp_reg, reg_name, el ++ mrs \gp_reg, \reg_name\()_el\()\el ++ .endm ++ ++ .macro tlbi_invalidate_all el ++ .if \el == 1 ++ TLB_INVALIDATE(vmalle1) ++ .elseif \el == 2 ++ TLB_INVALIDATE(alle2) ++ .elseif \el == 3 ++ TLB_INVALIDATE(alle3) ++ .else ++ .error "EL must be 1, 2 or 3" ++ .endif ++ .endm ++ ++ /* void enable_mmu_direct_el(unsigned int flags) */ ++ .macro define_mmu_enable_func el ++ func enable_mmu_direct_\()el\el ++#if ENABLE_ASSERTIONS ++ _mrs x1, sctlr, \el ++ tst x1, #SCTLR_M_BIT ++ ASM_ASSERT(eq) ++#endif ++ /* Invalidate all TLB entries */ ++ tlbi_invalidate_all \el ++ ++ mov x7, x0 ++ adrp x0, mmu_cfg_params ++ add x0, x0, :lo12:mmu_cfg_params ++ ++ /* MAIR */ ++ ldr x1, [x0, #(MMU_CFG_MAIR << 3)] ++ _msr mair, \el, x1 ++ ++ /* TCR */ ++ ldr x2, [x0, #(MMU_CFG_TCR << 3)] ++ _msr tcr, \el, x2 ++ ++ /* TTBR */ ++ ldr x3, [x0, #(MMU_CFG_TTBR0 << 3)] ++ _msr ttbr0, \el, x3 ++ ++ /* ++ * Ensure all translation table writes have drained into memory, the TLB ++ * invalidation is complete, and translation register writes are ++ * committed before enabling the MMU ++ */ ++ dsb ish ++ isb ++ ++ /* Set and clear required fields of SCTLR */ ++ _mrs x4, sctlr, \el ++ mov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT ++ orr x4, x4, x5 ++ ++ /* Additionally, amend SCTLR fields based on flags */ ++ bic x5, x4, #SCTLR_C_BIT ++ tst x7, #DISABLE_DCACHE ++ csel x4, x5, x4, ne ++ ++ _msr sctlr, \el, x4 ++ isb ++ ++ ret ++ endfunc enable_mmu_direct_\()el\el ++ .endm ++ ++ /* ++ * Define MMU-enabling functions for EL1, EL2 and EL3: ++ * ++ * enable_mmu_direct_el1 ++ * enable_mmu_direct_el2 ++ * enable_mmu_direct_el3 ++ */ ++ define_mmu_enable_func 1 ++ define_mmu_enable_func 2 ++ define_mmu_enable_func 3 +diff --git a/environments/shim/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/environments/shim/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +new file mode 100644 +index 0000000..037dbf8 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +@@ -0,0 +1,295 @@ ++/* ++ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../xlat_tables_private.h" ++ ++/* ++ * Returns true if the provided granule size is supported, false otherwise. ++ */ ++bool xlat_arch_is_granule_size_supported(size_t size) ++{ ++ u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1(); ++ ++ if (size == PAGE_SIZE_4KB) { ++ return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) & ++ ID_AA64MMFR0_EL1_TGRAN4_MASK) == ++ ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED; ++ } else if (size == PAGE_SIZE_16KB) { ++ return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) & ++ ID_AA64MMFR0_EL1_TGRAN16_MASK) == ++ ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED; ++ } else if (size == PAGE_SIZE_64KB) { ++ return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) & ++ ID_AA64MMFR0_EL1_TGRAN64_MASK) == ++ ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED; ++ } else { ++ return 0; ++ } ++} ++ ++size_t xlat_arch_get_max_supported_granule_size(void) ++{ ++ if (xlat_arch_is_granule_size_supported(PAGE_SIZE_64KB)) { ++ return PAGE_SIZE_64KB; ++ } else if (xlat_arch_is_granule_size_supported(PAGE_SIZE_16KB)) { ++ return PAGE_SIZE_16KB; ++ } else { ++ assert(xlat_arch_is_granule_size_supported(PAGE_SIZE_4KB)); ++ return PAGE_SIZE_4KB; ++ } ++} ++ ++unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr) ++{ ++ /* Physical address can't exceed 48 bits */ ++ assert((max_addr & ADDR_MASK_48_TO_63) == 0U); ++ ++ /* 48 bits address */ ++ if ((max_addr & ADDR_MASK_44_TO_47) != 0U) ++ return TCR_PS_BITS_256TB; ++ ++ /* 44 bits address */ ++ if ((max_addr & ADDR_MASK_42_TO_43) != 0U) ++ return TCR_PS_BITS_16TB; ++ ++ /* 42 bits address */ ++ if ((max_addr & ADDR_MASK_40_TO_41) != 0U) ++ return TCR_PS_BITS_4TB; ++ ++ /* 40 bits address */ ++ if ((max_addr & ADDR_MASK_36_TO_39) != 0U) ++ return TCR_PS_BITS_1TB; ++ ++ /* 36 bits address */ ++ if ((max_addr & ADDR_MASK_32_TO_35) != 0U) ++ return TCR_PS_BITS_64GB; ++ ++ return TCR_PS_BITS_4GB; ++} ++ ++#if ENABLE_ASSERTIONS ++/* ++ * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is ++ * supported in ARMv8.2 onwards. ++ */ ++static const unsigned int pa_range_bits_arr[] = { ++ PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, ++ PARANGE_0101, PARANGE_0110 ++}; ++ ++unsigned long long xlat_arch_get_max_supported_pa(void) ++{ ++ u_register_t pa_range = read_id_aa64mmfr0_el1() & ++ ID_AA64MMFR0_EL1_PARANGE_MASK; ++ ++ /* All other values are reserved */ ++ assert(pa_range < ARRAY_SIZE(pa_range_bits_arr)); ++ ++ return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL; ++} ++ ++/* ++ * Return minimum virtual address space size supported by the architecture ++ */ ++uintptr_t xlat_get_min_virt_addr_space_size(void) ++{ ++ uintptr_t ret; ++ ++ if (is_armv8_4_ttst_present()) ++ ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST; ++ else ++ ret = MIN_VIRT_ADDR_SPACE_SIZE; ++ ++ return ret; ++} ++#endif /* ENABLE_ASSERTIONS*/ ++ ++bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx) ++{ ++ if (ctx->xlat_regime == EL1_EL0_REGIME) { ++ assert(xlat_arch_current_el() >= 1U); ++ return (read_sctlr_el1() & SCTLR_M_BIT) != 0U; ++ } else if (ctx->xlat_regime == EL2_REGIME) { ++ assert(xlat_arch_current_el() >= 2U); ++ return (read_sctlr_el2() & SCTLR_M_BIT) != 0U; ++ } else { ++ assert(ctx->xlat_regime == EL3_REGIME); ++ assert(xlat_arch_current_el() >= 3U); ++ return (read_sctlr_el3() & SCTLR_M_BIT) != 0U; ++ } ++} ++ ++bool is_dcache_enabled(void) ++{ ++ unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); ++ ++ if (el == 1U) { ++ return (read_sctlr_el1() & SCTLR_C_BIT) != 0U; ++ } else if (el == 2U) { ++ return (read_sctlr_el2() & SCTLR_C_BIT) != 0U; ++ } else { ++ return (read_sctlr_el3() & SCTLR_C_BIT) != 0U; ++ } ++} ++ ++uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) ++{ ++ if (xlat_regime == EL1_EL0_REGIME) { ++ return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN); ++ } else { ++ assert((xlat_regime == EL2_REGIME) || ++ (xlat_regime == EL3_REGIME)); ++ return UPPER_ATTRS(XN); ++ } ++} ++ ++void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime) ++{ ++ /* ++ * Ensure the translation table write has drained into memory before ++ * invalidating the TLB entry. ++ */ ++ dsbishst(); ++ ++ /* ++ * This function only supports invalidation of TLB entries for the EL3 ++ * and EL1&0 translation regimes. ++ * ++ * Also, it is architecturally UNDEFINED to invalidate TLBs of a higher ++ * exception level (see section D4.9.2 of the ARM ARM rev B.a). ++ */ ++ if (xlat_regime == EL1_EL0_REGIME) { ++ assert(xlat_arch_current_el() >= 1U); ++ tlbivaae1is(TLBI_ADDR(va)); ++ } else if (xlat_regime == EL2_REGIME) { ++ assert(xlat_arch_current_el() >= 2U); ++ tlbivae2is(TLBI_ADDR(va)); ++ } else { ++ assert(xlat_regime == EL3_REGIME); ++ assert(xlat_arch_current_el() >= 3U); ++ tlbivae3is(TLBI_ADDR(va)); ++ } ++} ++ ++void xlat_arch_tlbi_va_sync(void) ++{ ++ /* ++ * A TLB maintenance instruction can complete at any time after ++ * it is issued, but is only guaranteed to be complete after the ++ * execution of DSB by the PE that executed the TLB maintenance ++ * instruction. After the TLB invalidate instruction is ++ * complete, no new memory accesses using the invalidated TLB ++ * entries will be observed by any observer of the system ++ * domain. See section D4.8.2 of the ARMv8 (issue k), paragraph ++ * "Ordering and completion of TLB maintenance instructions". ++ */ ++ dsbish(); ++ ++ /* ++ * The effects of a completed TLB maintenance instruction are ++ * only guaranteed to be visible on the PE that executed the ++ * instruction after the execution of an ISB instruction by the ++ * PE that executed the TLB maintenance instruction. ++ */ ++ isb(); ++} ++ ++unsigned int xlat_arch_current_el(void) ++{ ++ unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); ++ ++ assert(el > 0U); ++ ++ return el; ++} ++ ++void setup_mmu_cfg(uint64_t *params, unsigned int flags, ++ const uint64_t *base_table, unsigned long long max_pa, ++ uintptr_t max_va, int xlat_regime) ++{ ++ uint64_t mair, ttbr0, tcr; ++ uintptr_t virtual_addr_space_size; ++ ++ /* Set attributes in the right indices of the MAIR. */ ++ mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); ++ mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); ++ mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); ++ ++ /* ++ * Limit the input address ranges and memory region sizes translated ++ * using TTBR0 to the given virtual address space size. ++ */ ++ assert(max_va < ((uint64_t)UINTPTR_MAX)); ++ ++ virtual_addr_space_size = (uintptr_t)max_va + 1U; ++ ++ assert(virtual_addr_space_size >= ++ xlat_get_min_virt_addr_space_size()); ++ assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE); ++ assert(IS_POWER_OF_TWO(virtual_addr_space_size)); ++ ++ /* ++ * __builtin_ctzll(0) is undefined but here we are guaranteed that ++ * virtual_addr_space_size is in the range [1,UINTPTR_MAX]. ++ */ ++ int t0sz = 64 - __builtin_ctzll(virtual_addr_space_size); ++ ++ tcr = (uint64_t)t0sz << TCR_T0SZ_SHIFT; ++ ++ /* ++ * Set the cacheability and shareability attributes for memory ++ * associated with translation table walks. ++ */ ++ if ((flags & XLAT_TABLE_NC) != 0U) { ++ /* Inner & outer non-cacheable non-shareable. */ ++ tcr |= TCR_SH_NON_SHAREABLE | ++ TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC; ++ } else { ++ /* Inner & outer WBWA & shareable. */ ++ tcr |= TCR_SH_INNER_SHAREABLE | ++ TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA; ++ } ++ ++ /* ++ * It is safer to restrict the max physical address accessible by the ++ * hardware as much as possible. ++ */ ++ unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa); ++ ++ if (xlat_regime == EL1_EL0_REGIME) { ++ /* ++ * TCR_EL1.EPD1: Disable translation table walk for addresses ++ * that are translated using TTBR1_EL1. ++ */ ++ tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT); ++ } else if (xlat_regime == EL2_REGIME) { ++ tcr |= TCR_EL2_RES1 | (tcr_ps_bits << TCR_EL2_PS_SHIFT); ++ } else { ++ assert(xlat_regime == EL3_REGIME); ++ tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT); ++ } ++ ++ /* Set TTBR bits as well */ ++ ttbr0 = (uint64_t) base_table; ++ ++ if (is_armv8_2_ttcnp_present()) { ++ /* Enable CnP bit so as to share page tables with all PEs. */ ++ ttbr0 |= TTBR_CNP_BIT; ++ } ++ ++ params[MMU_CFG_MAIR] = mair; ++ params[MMU_CFG_TCR] = tcr; ++ params[MMU_CFG_TTBR0] = ttbr0; ++} +diff --git a/environments/shim/lib/xlat_tables_v2/xlat_tables_context.c b/environments/shim/lib/xlat_tables_v2/xlat_tables_context.c +new file mode 100644 +index 0000000..0f3bab9 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/xlat_tables_context.c +@@ -0,0 +1,181 @@ ++/* ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "xlat_tables_private.h" ++ ++/* ++ * MMU configuration register values for the active translation context. Used ++ * from the MMU assembly helpers. ++ */ ++uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; ++ ++/* ++ * Allocate and initialise the default translation context for the software ++ * image currently executing. ++ */ ++REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES, ++ PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE); ++ ++void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size, ++ unsigned int attr) ++{ ++ mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); ++ ++ mmap_add_region_ctx(&tf_xlat_ctx, &mm); ++} ++ ++void mmap_add(const mmap_region_t *mm) ++{ ++ mmap_add_ctx(&tf_xlat_ctx, mm); ++} ++ ++void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, ++ size_t size, unsigned int attr) ++{ ++ mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); ++ ++ mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, &mm); ++ ++ *base_va = mm.base_va; ++} ++ ++void mmap_add_alloc_va(mmap_region_t *mm) ++{ ++ while (mm->granularity != 0U) { ++ assert(mm->base_va == 0U); ++ mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, mm); ++ mm++; ++ } ++} ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ ++int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, ++ size_t size, unsigned int attr) ++{ ++ mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); ++ ++ return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm); ++} ++ ++int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, ++ uintptr_t *base_va, size_t size, ++ unsigned int attr) ++{ ++ mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); ++ ++ int rc = mmap_add_dynamic_region_alloc_va_ctx(&tf_xlat_ctx, &mm); ++ ++ *base_va = mm.base_va; ++ ++ return rc; ++} ++ ++ ++int mmap_remove_dynamic_region(uintptr_t base_va, size_t size) ++{ ++ return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx, ++ base_va, size); ++} ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++void __init init_xlat_tables(void) ++{ ++ assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); ++ ++ unsigned int current_el = xlat_arch_current_el(); ++ ++ if (current_el == 1U) { ++ tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME; ++ } else if (current_el == 2U) { ++ tf_xlat_ctx.xlat_regime = EL2_REGIME; ++ } else { ++ assert(current_el == 3U); ++ tf_xlat_ctx.xlat_regime = EL3_REGIME; ++ } ++ ++ init_xlat_tables_ctx(&tf_xlat_ctx); ++} ++ ++int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr) ++{ ++ return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr); ++} ++ ++int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr) ++{ ++ return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr); ++} ++ ++/* ++ * If dynamic allocation of new regions is disabled then by the time we call the ++ * function enabling the MMU, we'll have registered all the memory regions to ++ * map for the system's lifetime. Therefore, at this point we know the maximum ++ * physical address that will ever be mapped. ++ * ++ * If dynamic allocation is enabled then we can't make any such assumption ++ * because the maximum physical address could get pushed while adding a new ++ * region. Therefore, in this case we have to assume that the whole address ++ * space size might be mapped. ++ */ ++#ifdef PLAT_XLAT_TABLES_DYNAMIC ++#define MAX_PHYS_ADDR tf_xlat_ctx.pa_max_address ++#else ++#define MAX_PHYS_ADDR tf_xlat_ctx.max_pa ++#endif ++ ++#ifndef __aarch64__ ++ ++void enable_mmu_svc_mon(unsigned int flags) ++{ ++ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, ++ tf_xlat_ctx.base_table, MAX_PHYS_ADDR, ++ tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); ++ enable_mmu_direct_svc_mon(flags); ++} ++ ++void enable_mmu_hyp(unsigned int flags) ++{ ++ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, ++ tf_xlat_ctx.base_table, MAX_PHYS_ADDR, ++ tf_xlat_ctx.va_max_address, EL2_REGIME); ++ enable_mmu_direct_hyp(flags); ++} ++ ++#else ++ ++void enable_mmu_el1(unsigned int flags) ++{ ++ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, ++ tf_xlat_ctx.base_table, MAX_PHYS_ADDR, ++ tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); ++ enable_mmu_direct_el1(flags); ++} ++ ++void enable_mmu_el2(unsigned int flags) ++{ ++ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, ++ tf_xlat_ctx.base_table, MAX_PHYS_ADDR, ++ tf_xlat_ctx.va_max_address, EL2_REGIME); ++ enable_mmu_direct_el2(flags); ++} ++ ++void enable_mmu_el3(unsigned int flags) ++{ ++ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, ++ tf_xlat_ctx.base_table, MAX_PHYS_ADDR, ++ tf_xlat_ctx.va_max_address, EL3_REGIME); ++ enable_mmu_direct_el3(flags); ++} ++ ++#endif /* !__aarch64__ */ +diff --git a/environments/shim/lib/xlat_tables_v2/xlat_tables_core.c b/environments/shim/lib/xlat_tables_v2/xlat_tables_core.c +new file mode 100644 +index 0000000..c3dd445 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/xlat_tables_core.c +@@ -0,0 +1,1226 @@ ++/* ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xlat_tables_private.h" ++ ++/* Helper function that cleans the data cache only if it is enabled. */ ++static inline __attribute__((unused)) void xlat_clean_dcache_range(uintptr_t addr, size_t size) ++{ ++ if (is_dcache_enabled()) ++ clean_dcache_range(addr, size); ++} ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ ++/* ++ * The following functions assume that they will be called using subtables only. ++ * The base table can't be unmapped, so it is not needed to do any special ++ * handling for it. ++ */ ++ ++/* ++ * Returns the index of the array corresponding to the specified translation ++ * table. ++ */ ++static int xlat_table_get_index(const xlat_ctx_t *ctx, const uint64_t *table) ++{ ++ for (int i = 0; i < ctx->tables_num; i++) ++ if (ctx->tables[i] == table) ++ return i; ++ ++ /* ++ * Maybe we were asked to get the index of the base level table, which ++ * should never happen. ++ */ ++ assert(false); ++ ++ return -1; ++} ++ ++/* Returns a pointer to an empty translation table. */ ++static uint64_t *xlat_table_get_empty(const xlat_ctx_t *ctx) ++{ ++ for (int i = 0; i < ctx->tables_num; i++) ++ if (ctx->tables_mapped_regions[i] == 0) ++ return ctx->tables[i]; ++ ++ return NULL; ++} ++ ++/* Increments region count for a given table. */ ++static void xlat_table_inc_regions_count(const xlat_ctx_t *ctx, ++ const uint64_t *table) ++{ ++ int idx = xlat_table_get_index(ctx, table); ++ ++ ctx->tables_mapped_regions[idx]++; ++} ++ ++/* Decrements region count for a given table. */ ++static void xlat_table_dec_regions_count(const xlat_ctx_t *ctx, ++ const uint64_t *table) ++{ ++ int idx = xlat_table_get_index(ctx, table); ++ ++ ctx->tables_mapped_regions[idx]--; ++} ++ ++/* Returns 0 if the specified table isn't empty, otherwise 1. */ ++static bool xlat_table_is_empty(const xlat_ctx_t *ctx, const uint64_t *table) ++{ ++ return ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)] == 0; ++} ++ ++#else /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++/* Returns a pointer to the first empty translation table. */ ++static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx) ++{ ++ assert(ctx->next_table < ctx->tables_num); ++ ++ return ctx->tables[ctx->next_table++]; ++} ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++/* ++ * Returns a block/page table descriptor for the given level and attributes. ++ */ ++uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, ++ unsigned long long addr_pa, unsigned int level) ++{ ++ uint64_t desc; ++ uint32_t mem_type; ++ ++ /* Make sure that the granularity is fine enough to map this address. */ ++ assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0U); ++ ++ desc = addr_pa; ++ /* ++ * There are different translation table descriptors for level 3 and the ++ * rest. ++ */ ++ desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; ++ /* ++ * Always set the access flag, as this library assumes access flag ++ * faults aren't managed. ++ */ ++ desc |= LOWER_ATTRS(ACCESS_FLAG); ++ /* ++ * Deduce other fields of the descriptor based on the MT_NS and MT_RW ++ * memory region attributes. ++ */ ++ desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U; ++ desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); ++ ++ /* ++ * Do not allow unprivileged access when the mapping is for a privileged ++ * EL. For translation regimes that do not have mappings for access for ++ * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED. ++ */ ++ if (ctx->xlat_regime == EL1_EL0_REGIME) { ++ if ((attr & MT_USER) != 0U) { ++ /* EL0 mapping requested, so we give User access */ ++ desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED); ++ } else { ++ /* EL1 mapping requested, no User access granted */ ++ desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED); ++ } ++ } else { ++ assert((ctx->xlat_regime == EL2_REGIME) || ++ (ctx->xlat_regime == EL3_REGIME)); ++ desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1); ++ } ++ ++ /* ++ * Deduce shareability domain and executability of the memory region ++ * from the memory type of the attributes (MT_TYPE). ++ * ++ * Data accesses to device memory and non-cacheable normal memory are ++ * coherent for all observers in the system, and correspondingly are ++ * always treated as being Outer Shareable. Therefore, for these 2 types ++ * of memory, it is not strictly needed to set the shareability field ++ * in the translation tables. ++ */ ++ mem_type = MT_TYPE(attr); ++ if (mem_type == MT_DEVICE) { ++ desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH); ++ /* ++ * Always map device memory as execute-never. ++ * This is to avoid the possibility of a speculative instruction ++ * fetch, which could be an issue if this memory region ++ * corresponds to a read-sensitive peripheral. ++ */ ++ desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); ++ ++ } else { /* Normal memory */ ++ /* ++ * Always map read-write normal memory as execute-never. ++ * This library assumes that it is used by software that does ++ * not self-modify its code, therefore R/W memory is reserved ++ * for data storage, which must not be executable. ++ * ++ * Note that setting the XN bit here is for consistency only. ++ * The function that enables the MMU sets the SCTLR_ELx.WXN bit, ++ * which makes any writable memory region to be treated as ++ * execute-never, regardless of the value of the XN bit in the ++ * translation table. ++ * ++ * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER ++ * attribute to figure out the value of the XN bit. The actual ++ * XN bit(s) to set in the descriptor depends on the context's ++ * translation regime and the policy applied in ++ * xlat_arch_regime_get_xn_desc(). ++ */ ++ if (((attr & MT_RW) != 0U) || ((attr & MT_EXECUTE_NEVER) != 0U)) { ++ desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); ++ } ++ ++ if (mem_type == MT_MEMORY) { ++ desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); ++#if ENABLE_BTI ++ /* Check if Branch Target Identification is implemented */ ++ if (is_armv8_5_bti_present() && ++ ((attr & (MT_TYPE_MASK | MT_RW | ++ MT_EXECUTE_NEVER)) == MT_CODE)) { ++ /* Set GP bit for block and page code entries */ ++ desc |= GP; ++ } ++#endif ++ } else { ++ assert(mem_type == MT_NON_CACHEABLE); ++ desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); ++ } ++ } ++ ++ return desc; ++} ++ ++/* ++ * Enumeration of actions that can be made when mapping table entries depending ++ * on the previous value in that entry and information about the region being ++ * mapped. ++ */ ++typedef enum { ++ ++ /* Do nothing */ ++ ACTION_NONE, ++ ++ /* Write a block (or page, if in level 3) entry. */ ++ ACTION_WRITE_BLOCK_ENTRY, ++ ++ /* ++ * Create a new table and write a table entry pointing to it. Recurse ++ * into it for further processing. ++ */ ++ ACTION_CREATE_NEW_TABLE, ++ ++ /* ++ * There is a table descriptor in this entry, read it and recurse into ++ * that table for further processing. ++ */ ++ ACTION_RECURSE_INTO_TABLE, ++ ++} action_t; ++ ++/* ++ * Function that returns the first VA of the table affected by the specified ++ * mmap region. ++ */ ++static uintptr_t xlat_tables_find_start_va(mmap_region_t *mm, ++ const uintptr_t table_base_va, ++ const unsigned int level) ++{ ++ uintptr_t table_idx_va; ++ ++ if (mm->base_va > table_base_va) { ++ /* Find the first index of the table affected by the region. */ ++ table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level); ++ } else { ++ /* Start from the beginning of the table. */ ++ table_idx_va = table_base_va; ++ } ++ ++ return table_idx_va; ++} ++ ++/* ++ * Function that returns table index for the given VA and level arguments. ++ */ ++static inline unsigned int xlat_tables_va_to_index(const uintptr_t table_base_va, ++ const uintptr_t va, ++ const unsigned int level) ++{ ++ return (unsigned int)((va - table_base_va) >> XLAT_ADDR_SHIFT(level)); ++} ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ ++/* ++ * From the given arguments, it decides which action to take when unmapping the ++ * specified region. ++ */ ++static action_t xlat_tables_unmap_region_action(const mmap_region_t *mm, ++ const uintptr_t table_idx_va, const uintptr_t table_idx_end_va, ++ const unsigned int level, const uint64_t desc_type) ++{ ++ action_t action; ++ uintptr_t region_end_va = mm->base_va + mm->size - 1U; ++ ++ if ((mm->base_va <= table_idx_va) && ++ (region_end_va >= table_idx_end_va)) { ++ /* Region covers all block */ ++ ++ if (level == 3U) { ++ /* ++ * Last level, only page descriptors allowed, ++ * erase it. ++ */ ++ assert(desc_type == PAGE_DESC); ++ ++ action = ACTION_WRITE_BLOCK_ENTRY; ++ } else { ++ /* ++ * Other levels can have table descriptors. If ++ * so, recurse into it and erase descriptors ++ * inside it as needed. If there is a block ++ * descriptor, just erase it. If an invalid ++ * descriptor is found, this table isn't ++ * actually mapped, which shouldn't happen. ++ */ ++ if (desc_type == TABLE_DESC) { ++ action = ACTION_RECURSE_INTO_TABLE; ++ } else { ++ assert(desc_type == BLOCK_DESC); ++ action = ACTION_WRITE_BLOCK_ENTRY; ++ } ++ } ++ ++ } else if ((mm->base_va <= table_idx_end_va) || ++ (region_end_va >= table_idx_va)) { ++ /* ++ * Region partially covers block. ++ * ++ * It can't happen in level 3. ++ * ++ * There must be a table descriptor here, if not there ++ * was a problem when mapping the region. ++ */ ++ assert(level < 3U); ++ assert(desc_type == TABLE_DESC); ++ ++ action = ACTION_RECURSE_INTO_TABLE; ++ } else { ++ /* The region doesn't cover the block at all */ ++ action = ACTION_NONE; ++ } ++ ++ return action; ++} ++/* ++ * Recursive function that writes to the translation tables and unmaps the ++ * specified region. ++ */ ++static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm, ++ const uintptr_t table_base_va, ++ uint64_t *const table_base, ++ const unsigned int table_entries, ++ const unsigned int level) ++{ ++ assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); ++ ++ uint64_t *subtable; ++ uint64_t desc; ++ ++ uintptr_t table_idx_va; ++ uintptr_t table_idx_end_va; /* End VA of this entry */ ++ ++ uintptr_t region_end_va = mm->base_va + mm->size - 1U; ++ ++ unsigned int table_idx; ++ ++ table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); ++ table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); ++ ++ while (table_idx < table_entries) { ++ ++ table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1U; ++ ++ desc = table_base[table_idx]; ++ uint64_t desc_type = desc & DESC_MASK; ++ ++ action_t action = xlat_tables_unmap_region_action(mm, ++ table_idx_va, table_idx_end_va, level, ++ desc_type); ++ ++ if (action == ACTION_WRITE_BLOCK_ENTRY) { ++ ++ table_base[table_idx] = INVALID_DESC; ++ xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); ++ ++ } else if (action == ACTION_RECURSE_INTO_TABLE) { ++ ++ subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); ++ ++ /* Recurse to write into subtable */ ++ xlat_tables_unmap_region(ctx, mm, table_idx_va, ++ subtable, XLAT_TABLE_ENTRIES, ++ level + 1U); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)subtable, ++ XLAT_TABLE_ENTRIES * sizeof(uint64_t)); ++#endif ++ /* ++ * If the subtable is now empty, remove its reference. ++ */ ++ if (xlat_table_is_empty(ctx, subtable)) { ++ table_base[table_idx] = INVALID_DESC; ++ xlat_arch_tlbi_va(table_idx_va, ++ ctx->xlat_regime); ++ } ++ ++ } else { ++ assert(action == ACTION_NONE); ++ } ++ ++ table_idx++; ++ table_idx_va += XLAT_BLOCK_SIZE(level); ++ ++ /* If reached the end of the region, exit */ ++ if (region_end_va <= table_idx_va) ++ break; ++ } ++ ++ if (level > ctx->base_level) ++ xlat_table_dec_regions_count(ctx, table_base); ++} ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++/* ++ * From the given arguments, it decides which action to take when mapping the ++ * specified region. ++ */ ++static action_t xlat_tables_map_region_action(const mmap_region_t *mm, ++ unsigned int desc_type, unsigned long long dest_pa, ++ uintptr_t table_entry_base_va, unsigned int level) ++{ ++ uintptr_t mm_end_va = mm->base_va + mm->size - 1U; ++ uintptr_t table_entry_end_va = ++ table_entry_base_va + XLAT_BLOCK_SIZE(level) - 1U; ++ ++ /* ++ * The descriptor types allowed depend on the current table level. ++ */ ++ ++ if ((mm->base_va <= table_entry_base_va) && ++ (mm_end_va >= table_entry_end_va)) { ++ ++ /* ++ * Table entry is covered by region ++ * -------------------------------- ++ * ++ * This means that this table entry can describe the whole ++ * translation with this granularity in principle. ++ */ ++ ++ if (level == 3U) { ++ /* ++ * Last level, only page descriptors are allowed. ++ */ ++ if (desc_type == PAGE_DESC) { ++ /* ++ * There's another region mapped here, don't ++ * overwrite. ++ */ ++ return ACTION_NONE; ++ } else { ++ assert(desc_type == INVALID_DESC); ++ return ACTION_WRITE_BLOCK_ENTRY; ++ } ++ ++ } else { ++ ++ /* ++ * Other levels. Table descriptors are allowed. Block ++ * descriptors too, but they have some limitations. ++ */ ++ ++ if (desc_type == TABLE_DESC) { ++ /* There's already a table, recurse into it. */ ++ return ACTION_RECURSE_INTO_TABLE; ++ ++ } else if (desc_type == INVALID_DESC) { ++ /* ++ * There's nothing mapped here, create a new ++ * entry. ++ * ++ * Check if the destination granularity allows ++ * us to use a block descriptor or we need a ++ * finer table for it. ++ * ++ * Also, check if the current level allows block ++ * descriptors. If not, create a table instead. ++ */ ++ if (((dest_pa & XLAT_BLOCK_MASK(level)) != 0U) ++ || (level < MIN_LVL_BLOCK_DESC) || ++ (mm->granularity < XLAT_BLOCK_SIZE(level))) ++ return ACTION_CREATE_NEW_TABLE; ++ else ++ return ACTION_WRITE_BLOCK_ENTRY; ++ ++ } else { ++ /* ++ * There's another region mapped here, don't ++ * overwrite. ++ */ ++ assert(desc_type == BLOCK_DESC); ++ ++ return ACTION_NONE; ++ } ++ } ++ ++ } else if ((mm->base_va <= table_entry_end_va) || ++ (mm_end_va >= table_entry_base_va)) { ++ ++ /* ++ * Region partially covers table entry ++ * ----------------------------------- ++ * ++ * This means that this table entry can't describe the whole ++ * translation, a finer table is needed. ++ ++ * There cannot be partial block overlaps in level 3. If that ++ * happens, some of the preliminary checks when adding the ++ * mmap region failed to detect that PA and VA must at least be ++ * aligned to PAGE_SIZE. ++ */ ++ assert(level < 3U); ++ ++ if (desc_type == INVALID_DESC) { ++ /* ++ * The block is not fully covered by the region. Create ++ * a new table, recurse into it and try to map the ++ * region with finer granularity. ++ */ ++ return ACTION_CREATE_NEW_TABLE; ++ ++ } else { ++ assert(desc_type == TABLE_DESC); ++ /* ++ * The block is not fully covered by the region, but ++ * there is already a table here. Recurse into it and ++ * try to map with finer granularity. ++ * ++ * PAGE_DESC for level 3 has the same value as ++ * TABLE_DESC, but this code can't run on a level 3 ++ * table because there can't be overlaps in level 3. ++ */ ++ return ACTION_RECURSE_INTO_TABLE; ++ } ++ } else { ++ ++ /* ++ * This table entry is outside of the region specified in the ++ * arguments, don't write anything to it. ++ */ ++ return ACTION_NONE; ++ } ++} ++ ++/* ++ * Recursive function that writes to the translation tables and maps the ++ * specified region. On success, it returns the VA of the last byte that was ++ * successfully mapped. On error, it returns the VA of the next entry that ++ * should have been mapped. ++ */ ++static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm, ++ uintptr_t table_base_va, ++ uint64_t *const table_base, ++ unsigned int table_entries, ++ unsigned int level) ++{ ++ assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); ++ ++ uintptr_t mm_end_va = mm->base_va + mm->size - 1U; ++ ++ uintptr_t table_idx_va; ++ unsigned long long table_idx_pa; ++ ++ uint64_t *subtable; ++ uint64_t desc; ++ ++ unsigned int table_idx; ++ ++ table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); ++ table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ if (level > ctx->base_level) ++ xlat_table_inc_regions_count(ctx, table_base); ++#endif ++ ++ while (table_idx < table_entries) { ++ ++ desc = table_base[table_idx]; ++ ++ table_idx_pa = mm->base_pa + table_idx_va - mm->base_va; ++ ++ action_t action = xlat_tables_map_region_action(mm, ++ (uint32_t)(desc & DESC_MASK), table_idx_pa, ++ table_idx_va, level); ++ ++ if (action == ACTION_WRITE_BLOCK_ENTRY) { ++ ++ table_base[table_idx] = ++ xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa, ++ level); ++ ++ } else if (action == ACTION_CREATE_NEW_TABLE) { ++ uintptr_t end_va; ++ ++ subtable = xlat_table_get_empty(ctx); ++ if (subtable == NULL) { ++ /* Not enough free tables to map this region */ ++ return table_idx_va; ++ } ++ ++ /* Point to new subtable from this one. */ ++ table_base[table_idx] = TABLE_DESC | (unsigned long)subtable; ++ ++ /* Recurse to write into subtable */ ++ end_va = xlat_tables_map_region(ctx, mm, table_idx_va, ++ subtable, XLAT_TABLE_ENTRIES, ++ level + 1U); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)subtable, ++ XLAT_TABLE_ENTRIES * sizeof(uint64_t)); ++#endif ++ if (end_va != ++ (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) ++ return end_va; ++ ++ } else if (action == ACTION_RECURSE_INTO_TABLE) { ++ uintptr_t end_va; ++ ++ subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); ++ /* Recurse to write into subtable */ ++ end_va = xlat_tables_map_region(ctx, mm, table_idx_va, ++ subtable, XLAT_TABLE_ENTRIES, ++ level + 1U); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)subtable, ++ XLAT_TABLE_ENTRIES * sizeof(uint64_t)); ++#endif ++ if (end_va != ++ (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) ++ return end_va; ++ ++ } else { ++ ++ assert(action == ACTION_NONE); ++ ++ } ++ ++ table_idx++; ++ table_idx_va += XLAT_BLOCK_SIZE(level); ++ ++ /* If reached the end of the region, exit */ ++ if (mm_end_va <= table_idx_va) ++ break; ++ } ++ ++ return table_idx_va - 1U; ++} ++ ++/* ++ * Function that verifies that a region can be mapped. ++ * Returns: ++ * 0: Success, the mapping is allowed. ++ * EINVAL: Invalid values were used as arguments. ++ * ERANGE: The memory limits were surpassed. ++ * ENOMEM: There is not enough memory in the mmap array. ++ * EPERM: Region overlaps another one in an invalid way. ++ */ ++static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm) ++{ ++ unsigned long long base_pa = mm->base_pa; ++ uintptr_t base_va = mm->base_va; ++ size_t size = mm->size; ++ size_t granularity = mm->granularity; ++ ++ unsigned long long end_pa = base_pa + size - 1U; ++ uintptr_t end_va = base_va + size - 1U; ++ ++ if (!IS_PAGE_ALIGNED(base_pa) || !IS_PAGE_ALIGNED(base_va) || ++ !IS_PAGE_ALIGNED(size)) ++ return -EINVAL; ++ ++ if ((granularity != XLAT_BLOCK_SIZE(1U)) && ++ (granularity != XLAT_BLOCK_SIZE(2U)) && ++ (granularity != XLAT_BLOCK_SIZE(3U))) { ++ return -EINVAL; ++ } ++ ++ /* Check for overflows */ ++ if ((base_pa > end_pa) || (base_va > end_va)) ++ return -ERANGE; ++ ++ if ((base_va + (uintptr_t)size - (uintptr_t)1) > ctx->va_max_address) ++ return -ERANGE; ++ ++ if ((base_pa + (unsigned long long)size - 1ULL) > ctx->pa_max_address) ++ return -ERANGE; ++ ++ /* Check that there is space in the ctx->mmap array */ ++ if (ctx->mmap[ctx->mmap_num - 1].size != 0U) ++ return -ENOMEM; ++ ++ /* Check for PAs and VAs overlaps with all other regions */ ++ for (const mmap_region_t *mm_cursor = ctx->mmap; ++ mm_cursor->size != 0U; ++mm_cursor) { ++ ++ uintptr_t mm_cursor_end_va = mm_cursor->base_va ++ + mm_cursor->size - 1U; ++ ++ /* ++ * Check if one of the regions is completely inside the other ++ * one. ++ */ ++ bool fully_overlapped_va = ++ ((base_va >= mm_cursor->base_va) && ++ (end_va <= mm_cursor_end_va)) || ++ ((mm_cursor->base_va >= base_va) && ++ (mm_cursor_end_va <= end_va)); ++ ++ /* ++ * Full VA overlaps are only allowed if both regions are ++ * identity mapped (zero offset) or have the same VA to PA ++ * offset. Also, make sure that it's not the exact same area. ++ * This can only be done with static regions. ++ */ ++ if (fully_overlapped_va) { ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ if (((mm->attr & MT_DYNAMIC) != 0U) || ++ ((mm_cursor->attr & MT_DYNAMIC) != 0U)) ++ return -EPERM; ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ if ((mm_cursor->base_va - mm_cursor->base_pa) != ++ (base_va - base_pa)) ++ return -EPERM; ++ ++ if ((base_va == mm_cursor->base_va) && ++ (size == mm_cursor->size)) ++ return -EPERM; ++ ++ } else { ++ /* ++ * If the regions do not have fully overlapping VAs, ++ * then they must have fully separated VAs and PAs. ++ * Partial overlaps are not allowed ++ */ ++ ++ unsigned long long mm_cursor_end_pa = ++ mm_cursor->base_pa + mm_cursor->size - 1U; ++ ++ bool separated_pa = (end_pa < mm_cursor->base_pa) || ++ (base_pa > mm_cursor_end_pa); ++ bool separated_va = (end_va < mm_cursor->base_va) || ++ (base_va > mm_cursor_end_va); ++ ++ if (!separated_va || !separated_pa) ++ return -EPERM; ++ } ++ } ++ ++ return 0; ++} ++ ++void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) ++{ ++ mmap_region_t *mm_cursor = ctx->mmap, *mm_destination; ++ const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num; ++ const mmap_region_t *mm_last; ++ unsigned long long end_pa = mm->base_pa + mm->size - 1U; ++ uintptr_t end_va = mm->base_va + mm->size - 1U; ++ int ret; ++ ++ /* Ignore empty regions */ ++ if (mm->size == 0U) ++ return; ++ ++ /* Static regions must be added before initializing the xlat tables. */ ++ assert(!ctx->initialized); ++ ++ ret = mmap_add_region_check(ctx, mm); ++ if (ret != 0) { ++ ERROR("mmap_add_region_check() failed. error %d\n", ret); ++ assert(false); ++ return; ++ } ++ ++ /* ++ * Find correct place in mmap to insert new region. ++ * ++ * 1 - Lower region VA end first. ++ * 2 - Smaller region size first. ++ * ++ * VA 0 0xFF ++ * ++ * 1st |------| ++ * 2nd |------------| ++ * 3rd |------| ++ * 4th |---| ++ * 5th |---| ++ * 6th |----------| ++ * 7th |-------------------------------------| ++ * ++ * This is required for overlapping regions only. It simplifies adding ++ * regions with the loop in xlat_tables_init_internal because the outer ++ * ones won't overwrite block or page descriptors of regions added ++ * previously. ++ * ++ * Overlapping is only allowed for static regions. ++ */ ++ ++ while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) ++ && (mm_cursor->size != 0U)) { ++ ++mm_cursor; ++ } ++ ++ while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && ++ (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { ++ ++mm_cursor; ++ } ++ ++ /* ++ * Find the last entry marker in the mmap ++ */ ++ mm_last = ctx->mmap; ++ while ((mm_last->size != 0U) && (mm_last < mm_end)) { ++ ++mm_last; ++ } ++ ++ /* ++ * Check if we have enough space in the memory mapping table. ++ * This shouldn't happen as we have checked in mmap_add_region_check ++ * that there is free space. ++ */ ++ assert(mm_last->size == 0U); ++ ++ /* Make room for new region by moving other regions up by one place */ ++ mm_destination = mm_cursor + 1; ++ (void)memmove(mm_destination, mm_cursor, ++ (uintptr_t)mm_last - (uintptr_t)mm_cursor); ++ ++ /* ++ * Check we haven't lost the empty sentinel from the end of the array. ++ * This shouldn't happen as we have checked in mmap_add_region_check ++ * that there is free space. ++ */ ++ assert(mm_end->size == 0U); ++ ++ *mm_cursor = *mm; ++ ++ if (end_pa > ctx->max_pa) ++ ctx->max_pa = end_pa; ++ if (end_va > ctx->max_va) ++ ctx->max_va = end_va; ++} ++ ++/* ++ * Determine the table level closest to the initial lookup level that ++ * can describe this translation. Then, align base VA to the next block ++ * at the determined level. ++ */ ++static void mmap_alloc_va_align_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) ++{ ++ /* ++ * By or'ing the size and base PA the alignment will be the one ++ * corresponding to the smallest boundary of the two of them. ++ * ++ * There are three different cases. For example (for 4 KiB page size): ++ * ++ * +--------------+------------------++--------------+ ++ * | PA alignment | Size multiple of || VA alignment | ++ * +--------------+------------------++--------------+ ++ * | 2 MiB | 2 MiB || 2 MiB | (1) ++ * | 2 MiB | 4 KiB || 4 KiB | (2) ++ * | 4 KiB | 2 MiB || 4 KiB | (3) ++ * +--------------+------------------++--------------+ ++ * ++ * - In (1), it is possible to take advantage of the alignment of the PA ++ * and the size of the region to use a level 2 translation table ++ * instead of a level 3 one. ++ * ++ * - In (2), the size is smaller than a block entry of level 2, so it is ++ * needed to use a level 3 table to describe the region or the library ++ * will map more memory than the desired one. ++ * ++ * - In (3), even though the region has the size of one level 2 block ++ * entry, it isn't possible to describe the translation with a level 2 ++ * block entry because of the alignment of the base PA. ++ * ++ * Only bits 47:21 of a level 2 block descriptor are used by the MMU, ++ * bits 20:0 of the resulting address are 0 in this case. Because of ++ * this, the PA generated as result of this translation is aligned to ++ * 2 MiB. The PA that was requested to be mapped is aligned to 4 KiB, ++ * though, which means that the resulting translation is incorrect. ++ * The only way to prevent this is by using a finer granularity. ++ */ ++ unsigned long long align_check; ++ ++ align_check = mm->base_pa | (unsigned long long)mm->size; ++ ++ /* ++ * Assume it is always aligned to level 3. There's no need to check that ++ * level because its block size is PAGE_SIZE. The checks to verify that ++ * the addresses and size are aligned to PAGE_SIZE are inside ++ * mmap_add_region. ++ */ ++ for (unsigned int level = ctx->base_level; level <= 2U; ++level) { ++ ++ if ((align_check & XLAT_BLOCK_MASK(level)) != 0U) ++ continue; ++ ++ mm->base_va = round_up(mm->base_va, XLAT_BLOCK_SIZE(level)); ++ return; ++ } ++} ++ ++void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) ++{ ++ mm->base_va = ctx->max_va + 1UL; ++ ++ assert(mm->size > 0U); ++ ++ mmap_alloc_va_align_ctx(ctx, mm); ++ ++ /* Detect overflows. More checks are done in mmap_add_region_check(). */ ++ assert(mm->base_va > ctx->max_va); ++ ++ mmap_add_region_ctx(ctx, mm); ++} ++ ++void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) ++{ ++ const mmap_region_t *mm_cursor = mm; ++ ++ while (mm_cursor->granularity != 0U) { ++ mmap_add_region_ctx(ctx, mm_cursor); ++ mm_cursor++; ++ } ++} ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ ++int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) ++{ ++ mmap_region_t *mm_cursor = ctx->mmap; ++ const mmap_region_t *mm_last = mm_cursor + ctx->mmap_num; ++ unsigned long long end_pa = mm->base_pa + mm->size - 1U; ++ uintptr_t end_va = mm->base_va + mm->size - 1U; ++ int ret; ++ ++ /* Nothing to do */ ++ if (mm->size == 0U) ++ return 0; ++ ++ /* Now this region is a dynamic one */ ++ mm->attr |= MT_DYNAMIC; ++ ++ ret = mmap_add_region_check(ctx, mm); ++ if (ret != 0) ++ return ret; ++ ++ /* ++ * Find the adequate entry in the mmap array in the same way done for ++ * static regions in mmap_add_region_ctx(). ++ */ ++ ++ while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) ++ && (mm_cursor->size != 0U)) { ++ ++mm_cursor; ++ } ++ ++ while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && ++ (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { ++ ++mm_cursor; ++ } ++ ++ /* Make room for new region by moving other regions up by one place */ ++ (void)memmove(mm_cursor + 1U, mm_cursor, ++ (uintptr_t)mm_last - (uintptr_t)mm_cursor); ++ ++ /* ++ * Check we haven't lost the empty sentinal from the end of the array. ++ * This shouldn't happen as we have checked in mmap_add_region_check ++ * that there is free space. ++ */ ++ assert(mm_last->size == 0U); ++ ++ *mm_cursor = *mm; ++ ++ /* ++ * Update the translation tables if the xlat tables are initialized. If ++ * not, this region will be mapped when they are initialized. ++ */ ++ if (ctx->initialized) { ++ end_va = xlat_tables_map_region(ctx, mm_cursor, ++ 0U, ctx->base_table, ctx->base_table_entries, ++ ctx->base_level); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)ctx->base_table, ++ ctx->base_table_entries * sizeof(uint64_t)); ++#endif ++ /* Failed to map, remove mmap entry, unmap and return error. */ ++ if (end_va != (mm_cursor->base_va + mm_cursor->size - 1U)) { ++ (void)memmove(mm_cursor, mm_cursor + 1U, ++ (uintptr_t)mm_last - (uintptr_t)mm_cursor); ++ ++ /* ++ * Check if the mapping function actually managed to map ++ * anything. If not, just return now. ++ */ ++ if (mm->base_va >= end_va) ++ return -ENOMEM; ++ ++ /* ++ * Something went wrong after mapping some table ++ * entries, undo every change done up to this point. ++ */ ++ mmap_region_t unmap_mm = { ++ .base_pa = 0U, ++ .base_va = mm->base_va, ++ .size = end_va - mm->base_va, ++ .attr = 0U ++ }; ++ xlat_tables_unmap_region(ctx, &unmap_mm, 0U, ++ ctx->base_table, ctx->base_table_entries, ++ ctx->base_level); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)ctx->base_table, ++ ctx->base_table_entries * sizeof(uint64_t)); ++#endif ++ return -ENOMEM; ++ } ++ ++ /* ++ * Make sure that all entries are written to the memory. There ++ * is no need to invalidate entries when mapping dynamic regions ++ * because new table/block/page descriptors only replace old ++ * invalid descriptors, that aren't TLB cached. ++ */ ++ dsbishst(); ++ } ++ ++ if (end_pa > ctx->max_pa) ++ ctx->max_pa = end_pa; ++ if (end_va > ctx->max_va) ++ ctx->max_va = end_va; ++ ++ return 0; ++} ++ ++int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) ++{ ++ mm->base_va = ctx->max_va + 1UL; ++ ++ if (mm->size == 0U) ++ return 0; ++ ++ mmap_alloc_va_align_ctx(ctx, mm); ++ ++ /* Detect overflows. More checks are done in mmap_add_region_check(). */ ++ if (mm->base_va < ctx->max_va) { ++ return -ENOMEM; ++ } ++ ++ return mmap_add_dynamic_region_ctx(ctx, mm); ++} ++ ++/* ++ * Removes the region with given base Virtual Address and size from the given ++ * context. ++ * ++ * Returns: ++ * 0: Success. ++ * EINVAL: Invalid values were used as arguments (region not found). ++ * EPERM: Tried to remove a static region. ++ */ ++int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va, ++ size_t size) ++{ ++ mmap_region_t *mm = ctx->mmap; ++ const mmap_region_t *mm_last = mm + ctx->mmap_num; ++ int update_max_va_needed = 0; ++ int update_max_pa_needed = 0; ++ ++ /* Check sanity of mmap array. */ ++ assert(mm[ctx->mmap_num].size == 0U); ++ ++ while (mm->size != 0U) { ++ if ((mm->base_va == base_va) && (mm->size == size)) ++ break; ++ ++mm; ++ } ++ ++ /* Check that the region was found */ ++ if (mm->size == 0U) ++ return -EINVAL; ++ ++ /* If the region is static it can't be removed */ ++ if ((mm->attr & MT_DYNAMIC) == 0U) ++ return -EPERM; ++ ++ /* Check if this region is using the top VAs or PAs. */ ++ if ((mm->base_va + mm->size - 1U) == ctx->max_va) ++ update_max_va_needed = 1; ++ if ((mm->base_pa + mm->size - 1U) == ctx->max_pa) ++ update_max_pa_needed = 1; ++ ++ /* Update the translation tables if needed */ ++ if (ctx->initialized) { ++ xlat_tables_unmap_region(ctx, mm, 0U, ctx->base_table, ++ ctx->base_table_entries, ++ ctx->base_level); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)ctx->base_table, ++ ctx->base_table_entries * sizeof(uint64_t)); ++#endif ++ xlat_arch_tlbi_va_sync(); ++ } ++ ++ /* Remove this region by moving the rest down by one place. */ ++ (void)memmove(mm, mm + 1U, (uintptr_t)mm_last - (uintptr_t)mm); ++ ++ /* Check if we need to update the max VAs and PAs */ ++ if (update_max_va_needed == 1) { ++ ctx->max_va = 0U; ++ mm = ctx->mmap; ++ while (mm->size != 0U) { ++ if ((mm->base_va + mm->size - 1U) > ctx->max_va) ++ ctx->max_va = mm->base_va + mm->size - 1U; ++ ++mm; ++ } ++ } ++ ++ if (update_max_pa_needed == 1) { ++ ctx->max_pa = 0U; ++ mm = ctx->mmap; ++ while (mm->size != 0U) { ++ if ((mm->base_pa + mm->size - 1U) > ctx->max_pa) ++ ctx->max_pa = mm->base_pa + mm->size - 1U; ++ ++mm; ++ } ++ } ++ ++ return 0; ++} ++ ++void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, ++ uintptr_t va_max, struct mmap_region *mmap, ++ unsigned int mmap_num, uint64_t **tables, ++ unsigned int tables_num, uint64_t *base_table, ++ int xlat_regime, int *mapped_regions) ++{ ++ ctx->xlat_regime = xlat_regime; ++ ++ ctx->pa_max_address = pa_max; ++ ctx->va_max_address = va_max; ++ ++ ctx->mmap = mmap; ++ ctx->mmap_num = mmap_num; ++ memset(ctx->mmap, 0, sizeof(struct mmap_region) * mmap_num); ++ ++ ctx->tables = (void *) tables; ++ ctx->tables_num = tables_num; ++ ++ uintptr_t va_space_size = va_max + 1; ++ ctx->base_level = GET_XLAT_TABLE_LEVEL_BASE(va_space_size); ++ ctx->base_table = base_table; ++ ctx->base_table_entries = GET_NUM_BASE_LEVEL_ENTRIES(va_space_size); ++ ++ ctx->tables_mapped_regions = mapped_regions; ++ ++ ctx->max_pa = 0; ++ ctx->max_va = 0; ++ ctx->initialized = 0; ++} ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) ++{ ++ assert(ctx != NULL); ++ assert(!ctx->initialized); ++ assert((ctx->xlat_regime == EL3_REGIME) || ++ (ctx->xlat_regime == EL2_REGIME) || ++ (ctx->xlat_regime == EL1_EL0_REGIME)); ++ assert(!is_mmu_enabled_ctx(ctx)); ++ ++ mmap_region_t *mm = ctx->mmap; ++ ++ assert(ctx->va_max_address >= ++ (xlat_get_min_virt_addr_space_size() - 1U)); ++ assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U)); ++ assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U)); ++ ++ xlat_mmap_print(mm); ++ ++ /* All tables must be zeroed before mapping any region. */ ++ ++ for (unsigned int i = 0U; i < ctx->base_table_entries; i++) ++ ctx->base_table[i] = INVALID_DESC; ++ ++ for (int j = 0; j < ctx->tables_num; j++) { ++#if PLAT_XLAT_TABLES_DYNAMIC ++ ctx->tables_mapped_regions[j] = 0; ++#endif ++ for (unsigned int i = 0U; i < XLAT_TABLE_ENTRIES; i++) ++ ctx->tables[j][i] = INVALID_DESC; ++ } ++ ++ while (mm->size != 0U) { ++ uintptr_t end_va = xlat_tables_map_region(ctx, mm, 0U, ++ ctx->base_table, ctx->base_table_entries, ++ ctx->base_level); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ xlat_clean_dcache_range((uintptr_t)ctx->base_table, ++ ctx->base_table_entries * sizeof(uint64_t)); ++#endif ++ if (end_va != (mm->base_va + mm->size - 1U)) { ++ ERROR("Not enough memory to map region:\n" ++ " VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n", ++ mm->base_va, mm->base_pa, mm->size, mm->attr); ++ panic(); ++ } ++ ++ mm++; ++ } ++ ++ assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa()); ++ assert(ctx->max_va <= ctx->va_max_address); ++ assert(ctx->max_pa <= ctx->pa_max_address); ++ ++ ctx->initialized = true; ++ ++ xlat_tables_print(ctx); ++} +diff --git a/environments/shim/lib/xlat_tables_v2/xlat_tables_private.h b/environments/shim/lib/xlat_tables_v2/xlat_tables_private.h +new file mode 100644 +index 0000000..8f51686 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/xlat_tables_private.h +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef XLAT_TABLES_PRIVATE_H ++#define XLAT_TABLES_PRIVATE_H ++ ++#include ++#include ++#include ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++/* ++ * Private shifts and masks to access fields of an mmap attribute ++ */ ++/* Dynamic or static */ ++#define MT_DYN_SHIFT U(31) ++ ++/* ++ * Memory mapping private attributes ++ * ++ * Private attributes not exposed in the public header. ++ */ ++ ++/* ++ * Regions mapped before the MMU can't be unmapped dynamically (they are ++ * static) and regions mapped with MMU enabled can be unmapped. This ++ * behaviour can't be overridden. ++ * ++ * Static regions can overlap each other, dynamic regions can't. ++ */ ++#define MT_STATIC (U(0) << MT_DYN_SHIFT) ++#define MT_DYNAMIC (U(1) << MT_DYN_SHIFT) ++ ++#endif /* PLAT_XLAT_TABLES_DYNAMIC */ ++ ++extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; ++ ++/* ++ * Return the execute-never mask that will prevent instruction fetch at the ++ * given translation regime. ++ */ ++uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime); ++ ++/* ++ * Invalidate all TLB entries that match the given virtual address. This ++ * operation applies to all PEs in the same Inner Shareable domain as the PE ++ * that executes this function. This functions must be called for every ++ * translation table entry that is modified. It only affects the specified ++ * translation regime. ++ * ++ * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries ++ * pertaining to a higher exception level, e.g. invalidating EL3 entries from ++ * S-EL1. ++ */ ++void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime); ++ ++/* ++ * This function has to be called at the end of any code that uses the function ++ * xlat_arch_tlbi_va(). ++ */ ++void xlat_arch_tlbi_va_sync(void); ++ ++/* Print VA, PA, size and attributes of all regions in the mmap array. */ ++void xlat_mmap_print(const mmap_region_t *mmap); ++ ++/* ++ * Print the current state of the translation tables by reading them from ++ * memory. ++ */ ++void xlat_tables_print(xlat_ctx_t *ctx); ++ ++/* ++ * Returns a block/page table descriptor for the given level and attributes. ++ */ ++uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, ++ unsigned long long addr_pa, unsigned int level); ++ ++/* ++ * Architecture-specific initialization code. ++ */ ++ ++/* Returns the current Exception Level. The returned EL must be 1 or higher. */ ++unsigned int xlat_arch_current_el(void); ++ ++/* ++ * Return the maximum physical address supported by the hardware. ++ * This value depends on the execution state (AArch32/AArch64). ++ */ ++unsigned long long xlat_arch_get_max_supported_pa(void); ++ ++/* ++ * Returns true if the MMU of the translation regime managed by the given ++ * xlat_ctx_t is enabled, false otherwise. ++ */ ++bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx); ++ ++/* Returns true if the data cache is enabled at the current EL. */ ++bool is_dcache_enabled(void); ++ ++/* ++ * Returns minimum virtual address space size supported by the architecture ++ */ ++uintptr_t xlat_get_min_virt_addr_space_size(void); ++ ++#endif /* XLAT_TABLES_PRIVATE_H */ +diff --git a/environments/shim/lib/xlat_tables_v2/xlat_tables_utils.c b/environments/shim/lib/xlat_tables_v2/xlat_tables_utils.c +new file mode 100644 +index 0000000..168d492 +--- /dev/null ++++ b/environments/shim/lib/xlat_tables_v2/xlat_tables_utils.c +@@ -0,0 +1,573 @@ ++/* ++ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xlat_tables_private.h" ++ ++#if LOG_LEVEL < LOG_LEVEL_VERBOSE ++ ++void xlat_mmap_print(__unused const mmap_region_t *mmap) ++{ ++ /* Empty */ ++} ++ ++void xlat_tables_print(__unused xlat_ctx_t *ctx) ++{ ++ /* Empty */ ++} ++ ++#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */ ++ ++void xlat_mmap_print(const mmap_region_t *mmap) ++{ ++ printf("mmap:\n"); ++ const mmap_region_t *mm = mmap; ++ ++ while (mm->size != 0U) { ++ printf(" VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x granularity:0x%zx\n", ++ mm->base_va, mm->base_pa, mm->size, mm->attr, ++ mm->granularity); ++ ++mm; ++ }; ++ printf("\n"); ++} ++ ++/* Print the attributes of the specified block descriptor. */ ++static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc) ++{ ++ uint64_t mem_type_index = ATTR_INDEX_GET(desc); ++ int xlat_regime = ctx->xlat_regime; ++ ++ if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { ++ printf("MEM"); ++ } else if (mem_type_index == ATTR_NON_CACHEABLE_INDEX) { ++ printf("NC"); ++ } else { ++ assert(mem_type_index == ATTR_DEVICE_INDEX); ++ printf("DEV"); ++ } ++ ++ if ((xlat_regime == EL3_REGIME) || (xlat_regime == EL2_REGIME)) { ++ /* For EL3 and EL2 only check the AP[2] and XN bits. */ ++ printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); ++ printf(((desc & UPPER_ATTRS(XN)) != 0ULL) ? "-XN" : "-EXEC"); ++ } else { ++ assert(xlat_regime == EL1_EL0_REGIME); ++ /* ++ * For EL0 and EL1: ++ * - In AArch64 PXN and UXN can be set independently but in ++ * AArch32 there is no UXN (XN affects both privilege levels). ++ * For consistency, we set them simultaneously in both cases. ++ * - RO and RW permissions must be the same in EL1 and EL0. If ++ * EL0 can access that memory region, so can EL1, with the ++ * same permissions. ++ */ ++#if ENABLE_ASSERTIONS ++ uint64_t xn_mask = xlat_arch_regime_get_xn_desc(EL1_EL0_REGIME); ++ uint64_t xn_perm = desc & xn_mask; ++ ++ assert((xn_perm == xn_mask) || (xn_perm == 0ULL)); ++#endif ++ printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); ++ /* Only check one of PXN and UXN, the other one is the same. */ ++ printf(((desc & UPPER_ATTRS(PXN)) != 0ULL) ? "-XN" : "-EXEC"); ++ /* ++ * Privileged regions can only be accessed from EL1, user ++ * regions can be accessed from EL1 and EL0. ++ */ ++ printf(((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED)) != 0ULL) ++ ? "-USER" : "-PRIV"); ++ } ++ ++ printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S"); ++ ++#ifdef __aarch64__ ++ /* Check Guarded Page bit */ ++ if ((desc & GP) != 0ULL) { ++ printf("-GP"); ++ } ++#endif ++} ++ ++static const char * const level_spacers[] = { ++ "[LV0] ", ++ " [LV1] ", ++ " [LV2] ", ++ " [LV3] " ++}; ++ ++static const char *invalid_descriptors_ommited = ++ "%s(%d invalid descriptors omitted)\n"; ++ ++/* ++ * Recursive function that reads the translation tables passed as an argument ++ * and prints their status. ++ */ ++static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va, ++ const uint64_t *table_base, unsigned int table_entries, ++ unsigned int level) ++{ ++ assert(level <= XLAT_TABLE_LEVEL_MAX); ++ ++ uint64_t desc; ++ uintptr_t table_idx_va = table_base_va; ++ unsigned int table_idx = 0U; ++ size_t level_size = XLAT_BLOCK_SIZE(level); ++ ++ /* ++ * Keep track of how many invalid descriptors are counted in a row. ++ * Whenever multiple invalid descriptors are found, only the first one ++ * is printed, and a line is added to inform about how many descriptors ++ * have been omitted. ++ */ ++ int invalid_row_count = 0; ++ ++ while (table_idx < table_entries) { ++ ++ desc = table_base[table_idx]; ++ ++ if ((desc & DESC_MASK) == INVALID_DESC) { ++ ++ if (invalid_row_count == 0) { ++ printf("%sVA:0x%lx size:0x%zx\n", ++ level_spacers[level], ++ table_idx_va, level_size); ++ } ++ invalid_row_count++; ++ ++ } else { ++ ++ if (invalid_row_count > 1) { ++ printf(invalid_descriptors_ommited, ++ level_spacers[level], ++ invalid_row_count - 1); ++ } ++ invalid_row_count = 0; ++ ++ /* ++ * Check if this is a table or a block. Tables are only ++ * allowed in levels other than 3, but DESC_PAGE has the ++ * same value as DESC_TABLE, so we need to check. ++ */ ++ if (((desc & DESC_MASK) == TABLE_DESC) && ++ (level < XLAT_TABLE_LEVEL_MAX)) { ++ /* ++ * Do not print any PA for a table descriptor, ++ * as it doesn't directly map physical memory ++ * but instead points to the next translation ++ * table in the translation table walk. ++ */ ++ printf("%sVA:0x%lx size:0x%zx\n", ++ level_spacers[level], ++ table_idx_va, level_size); ++ ++ uintptr_t addr_inner = desc & TABLE_ADDR_MASK; ++ ++ xlat_tables_print_internal(ctx, table_idx_va, ++ (uint64_t *)addr_inner, ++ XLAT_TABLE_ENTRIES, level + 1U); ++ } else { ++ printf("%sVA:0x%lx PA:0x%llx size:0x%zx ", ++ level_spacers[level], table_idx_va, ++ (uint64_t)(desc & TABLE_ADDR_MASK), ++ level_size); ++ xlat_desc_print(ctx, desc); ++ printf("\n"); ++ } ++ } ++ ++ table_idx++; ++ table_idx_va += level_size; ++ } ++ ++ if (invalid_row_count > 1) { ++ printf(invalid_descriptors_ommited, ++ level_spacers[level], invalid_row_count - 1); ++ } ++} ++ ++void xlat_tables_print(xlat_ctx_t *ctx) ++{ ++ const char *xlat_regime_str; ++ int used_page_tables; ++ ++ if (ctx->xlat_regime == EL1_EL0_REGIME) { ++ xlat_regime_str = "1&0"; ++ } else if (ctx->xlat_regime == EL2_REGIME) { ++ xlat_regime_str = "2"; ++ } else { ++ assert(ctx->xlat_regime == EL3_REGIME); ++ xlat_regime_str = "3"; ++ } ++ VERBOSE("Translation tables state:\n"); ++ VERBOSE(" Xlat regime: EL%s\n", xlat_regime_str); ++ VERBOSE(" Max allowed PA: 0x%llx\n", ctx->pa_max_address); ++ VERBOSE(" Max allowed VA: 0x%lx\n", ctx->va_max_address); ++ VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa); ++ VERBOSE(" Max mapped VA: 0x%lx\n", ctx->max_va); ++ ++ VERBOSE(" Initial lookup level: %u\n", ctx->base_level); ++ VERBOSE(" Entries @initial lookup level: %u\n", ++ ctx->base_table_entries); ++ ++#if PLAT_XLAT_TABLES_DYNAMIC ++ used_page_tables = 0; ++ for (int i = 0; i < ctx->tables_num; ++i) { ++ if (ctx->tables_mapped_regions[i] != 0) ++ ++used_page_tables; ++ } ++#else ++ used_page_tables = ctx->next_table; ++#endif ++ VERBOSE(" Used %d sub-tables out of %d (spare: %d)\n", ++ used_page_tables, ctx->tables_num, ++ ctx->tables_num - used_page_tables); ++ ++ xlat_tables_print_internal(ctx, 0U, ctx->base_table, ++ ctx->base_table_entries, ctx->base_level); ++} ++ ++#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ ++ ++/* ++ * Do a translation table walk to find the block or page descriptor that maps ++ * virtual_addr. ++ * ++ * On success, return the address of the descriptor within the translation ++ * table. Its lookup level is stored in '*out_level'. ++ * On error, return NULL. ++ * ++ * xlat_table_base ++ * Base address for the initial lookup level. ++ * xlat_table_base_entries ++ * Number of entries in the translation table for the initial lookup level. ++ * virt_addr_space_size ++ * Size in bytes of the virtual address space. ++ */ ++static uint64_t *find_xlat_table_entry(uintptr_t virtual_addr, ++ void *xlat_table_base, ++ unsigned int xlat_table_base_entries, ++ unsigned long long virt_addr_space_size, ++ unsigned int *out_level) ++{ ++ unsigned int start_level; ++ uint64_t *table; ++ unsigned int entries; ++ ++ start_level = GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size); ++ ++ table = xlat_table_base; ++ entries = xlat_table_base_entries; ++ ++ for (unsigned int level = start_level; ++ level <= XLAT_TABLE_LEVEL_MAX; ++ ++level) { ++ uint64_t idx, desc, desc_type; ++ ++ idx = XLAT_TABLE_IDX(virtual_addr, level); ++ if (idx >= entries) { ++ WARN("Missing xlat table entry at address 0x%lx\n", ++ virtual_addr); ++ return NULL; ++ } ++ ++ desc = table[idx]; ++ desc_type = desc & DESC_MASK; ++ ++ if (desc_type == INVALID_DESC) { ++ VERBOSE("Invalid entry (memory not mapped)\n"); ++ return NULL; ++ } ++ ++ if (level == XLAT_TABLE_LEVEL_MAX) { ++ /* ++ * Only page descriptors allowed at the final lookup ++ * level. ++ */ ++ assert(desc_type == PAGE_DESC); ++ *out_level = level; ++ return &table[idx]; ++ } ++ ++ if (desc_type == BLOCK_DESC) { ++ *out_level = level; ++ return &table[idx]; ++ } ++ ++ assert(desc_type == TABLE_DESC); ++ table = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); ++ entries = XLAT_TABLE_ENTRIES; ++ } ++ ++ /* ++ * This shouldn't be reached, the translation table walk should end at ++ * most at level XLAT_TABLE_LEVEL_MAX and return from inside the loop. ++ */ ++ assert(false); ++ ++ return NULL; ++} ++ ++ ++static int xlat_get_mem_attributes_internal(const xlat_ctx_t *ctx, ++ uintptr_t base_va, uint32_t *attributes, uint64_t **table_entry, ++ unsigned long long *addr_pa, unsigned int *table_level) ++{ ++ uint64_t *entry; ++ uint64_t desc; ++ unsigned int level; ++ unsigned long long virt_addr_space_size; ++ ++ /* ++ * Sanity-check arguments. ++ */ ++ assert(ctx != NULL); ++ assert(ctx->initialized); ++ assert((ctx->xlat_regime == EL1_EL0_REGIME) || ++ (ctx->xlat_regime == EL2_REGIME) || ++ (ctx->xlat_regime == EL3_REGIME)); ++ ++ virt_addr_space_size = (unsigned long long)ctx->va_max_address + 1ULL; ++ assert(virt_addr_space_size > 0U); ++ ++ entry = find_xlat_table_entry(base_va, ++ ctx->base_table, ++ ctx->base_table_entries, ++ virt_addr_space_size, ++ &level); ++ if (entry == NULL) { ++ WARN("Address 0x%lx is not mapped.\n", base_va); ++ return -EINVAL; ++ } ++ ++ if (addr_pa != NULL) { ++ *addr_pa = *entry & TABLE_ADDR_MASK; ++ } ++ ++ if (table_entry != NULL) { ++ *table_entry = entry; ++ } ++ ++ if (table_level != NULL) { ++ *table_level = level; ++ } ++ ++ desc = *entry; ++ ++#if LOG_LEVEL >= LOG_LEVEL_VERBOSE ++ VERBOSE("Attributes: "); ++ xlat_desc_print(ctx, desc); ++ printf("\n"); ++#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ ++ ++ assert(attributes != NULL); ++ *attributes = 0U; ++ ++ uint64_t attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; ++ ++ if (attr_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { ++ *attributes |= MT_MEMORY; ++ } else if (attr_index == ATTR_NON_CACHEABLE_INDEX) { ++ *attributes |= MT_NON_CACHEABLE; ++ } else { ++ assert(attr_index == ATTR_DEVICE_INDEX); ++ *attributes |= MT_DEVICE; ++ } ++ ++ uint64_t ap2_bit = (desc >> AP2_SHIFT) & 1U; ++ ++ if (ap2_bit == AP2_RW) ++ *attributes |= MT_RW; ++ ++ if (ctx->xlat_regime == EL1_EL0_REGIME) { ++ uint64_t ap1_bit = (desc >> AP1_SHIFT) & 1U; ++ ++ if (ap1_bit == AP1_ACCESS_UNPRIVILEGED) ++ *attributes |= MT_USER; ++ } ++ ++ uint64_t ns_bit = (desc >> NS_SHIFT) & 1U; ++ ++ if (ns_bit == 1U) ++ *attributes |= MT_NS; ++ ++ uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime); ++ ++ if ((desc & xn_mask) == xn_mask) { ++ *attributes |= MT_EXECUTE_NEVER; ++ } else { ++ assert((desc & xn_mask) == 0U); ++ } ++ ++ return 0; ++} ++ ++ ++int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, ++ uint32_t *attr) ++{ ++ return xlat_get_mem_attributes_internal(ctx, base_va, attr, ++ NULL, NULL, NULL); ++} ++ ++ ++int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, ++ size_t size, uint32_t attr) ++{ ++ /* Note: This implementation isn't optimized. */ ++ ++ assert(ctx != NULL); ++ assert(ctx->initialized); ++ ++ unsigned long long virt_addr_space_size = ++ (unsigned long long)ctx->va_max_address + 1U; ++ assert(virt_addr_space_size > 0U); ++ ++ if (!IS_PAGE_ALIGNED(base_va)) { ++ WARN("%s: Address 0x%lx is not aligned on a page boundary.\n", ++ __func__, base_va); ++ return -EINVAL; ++ } ++ ++ if (size == 0U) { ++ WARN("%s: Size is 0.\n", __func__); ++ return -EINVAL; ++ } ++ ++ if ((size % PAGE_SIZE) != 0U) { ++ WARN("%s: Size 0x%zx is not a multiple of a page size.\n", ++ __func__, size); ++ return -EINVAL; ++ } ++ ++ if (((attr & MT_EXECUTE_NEVER) == 0U) && ((attr & MT_RW) != 0U)) { ++ WARN("%s: Mapping memory as read-write and executable not allowed.\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ size_t pages_count = size / PAGE_SIZE; ++ ++ VERBOSE("Changing memory attributes of %zu pages starting from address 0x%lx...\n", ++ pages_count, base_va); ++ ++ uintptr_t base_va_original = base_va; ++ ++ /* ++ * Sanity checks. ++ */ ++ for (size_t i = 0U; i < pages_count; ++i) { ++ const uint64_t *entry; ++ uint64_t desc, attr_index; ++ unsigned int level; ++ ++ entry = find_xlat_table_entry(base_va, ++ ctx->base_table, ++ ctx->base_table_entries, ++ virt_addr_space_size, ++ &level); ++ if (entry == NULL) { ++ WARN("Address 0x%lx is not mapped.\n", base_va); ++ return -EINVAL; ++ } ++ ++ desc = *entry; ++ ++ /* ++ * Check that all the required pages are mapped at page ++ * granularity. ++ */ ++ if (((desc & DESC_MASK) != PAGE_DESC) || ++ (level != XLAT_TABLE_LEVEL_MAX)) { ++ WARN("Address 0x%lx is not mapped at the right granularity.\n", ++ base_va); ++ WARN("Granularity is 0x%llx, should be 0x%x.\n", ++ (unsigned long long)XLAT_BLOCK_SIZE(level), PAGE_SIZE); ++ return -EINVAL; ++ } ++ ++ /* ++ * If the region type is device, it shouldn't be executable. ++ */ ++ attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; ++ if (attr_index == ATTR_DEVICE_INDEX) { ++ if ((attr & MT_EXECUTE_NEVER) == 0U) { ++ WARN("Setting device memory as executable at address 0x%lx.", ++ base_va); ++ return -EINVAL; ++ } ++ } ++ ++ base_va += PAGE_SIZE; ++ } ++ ++ /* Restore original value. */ ++ base_va = base_va_original; ++ ++ for (unsigned int i = 0U; i < pages_count; ++i) { ++ ++ uint32_t old_attr = 0U, new_attr; ++ uint64_t *entry = NULL; ++ unsigned int level = 0U; ++ unsigned long long addr_pa = 0ULL; ++ ++ (void) xlat_get_mem_attributes_internal(ctx, base_va, &old_attr, ++ &entry, &addr_pa, &level); ++ ++ /* ++ * From attr, only MT_RO/MT_RW, MT_EXECUTE/MT_EXECUTE_NEVER and ++ * MT_USER/MT_PRIVILEGED are taken into account. Any other ++ * information is ignored. ++ */ ++ ++ /* Clean the old attributes so that they can be rebuilt. */ ++ new_attr = old_attr & ~(MT_RW | MT_EXECUTE_NEVER | MT_USER); ++ ++ /* ++ * Update attributes, but filter out the ones this function ++ * isn't allowed to change. ++ */ ++ new_attr |= attr & (MT_RW | MT_EXECUTE_NEVER | MT_USER); ++ ++ /* ++ * The break-before-make sequence requires writing an invalid ++ * descriptor and making sure that the system sees the change ++ * before writing the new descriptor. ++ */ ++ *entry = INVALID_DESC; ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ dccvac((uintptr_t)entry); ++#endif ++ /* Invalidate any cached copy of this mapping in the TLBs. */ ++ xlat_arch_tlbi_va(base_va, ctx->xlat_regime); ++ ++ /* Ensure completion of the invalidation. */ ++ xlat_arch_tlbi_va_sync(); ++ ++ /* Write new descriptor */ ++ *entry = xlat_desc(ctx, new_attr, addr_pa, level); ++#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) ++ dccvac((uintptr_t)entry); ++#endif ++ base_va += PAGE_SIZE; ++ } ++ ++ /* Ensure that the last descriptor writen is seen by the system. */ ++ dsbish(); ++ ++ return 0; ++} +diff --git a/environments/shim/pl011/aarch64/pl011_console.S b/environments/shim/pl011/aarch64/pl011_console.S +new file mode 100644 +index 0000000..11501d7 +--- /dev/null ++++ b/environments/shim/pl011/aarch64/pl011_console.S +@@ -0,0 +1,246 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++#include ++ ++ .globl console_init ++ .globl console_pl011_putc ++ .globl console_getc ++ .globl console_try_getc ++ .globl console_flush ++ .globl console_core_init ++ .globl console_core_putc ++ .globl console_core_getc ++ .globl console_core_flush ++ ++ /* ++ * The console base is in the data section and not in .bss ++ * even though it is zero-init. In particular, this allows ++ * the console functions to start using this variable before ++ * the runtime memory is initialized for images which do not ++ * need to copy the .data section from ROM to RAM. ++ */ ++ .section .data.console_base ++ .align 3 ++console_base: .quad 0x0 ++ ++ /* ----------------------------------------------- ++ * int console_init(uintptr_t base_addr, ++ * unsigned int uart_clk, unsigned int baud_rate) ++ * ++ * Clobber list : x1 - x3 ++ * ----------------------------------------------- ++ */ ++func console_init ++ adrp x3, console_base ++ str x0, [x3, :lo12:console_base] ++ b console_core_init ++endfunc console_init ++ ++ /* ----------------------------------------------- ++ * int console_core_init(uintptr_t base_addr, ++ * unsigned int uart_clk, unsigned int baud_rate) ++ * Function to initialize the console without a ++ * C Runtime to print debug information. This ++ * function will be accessed by console_init and ++ * crash reporting. ++ * In: x0 - Console base address ++ * w1 - Uart clock in Hz ++ * w2 - Baud rate ++ * Out: w0 - Return 1 on success, 0 on error. ++ * Clobber list : x1 - x3 ++ * ----------------------------------------------- ++ */ ++func console_core_init ++ /* Check the input base address */ ++ cbz x0, init_fail ++ /* Check baud rate and uart clock for sanity */ ++ cbz w1, init_fail ++ cbz w2, init_fail ++ /* Disable uart before programming */ ++ ldr w3, [x0, #UARTCR] ++ bic w3, w3, #PL011_UARTCR_UARTEN ++ str w3, [x0, #UARTCR] ++ /* Program the baudrate */ ++ /* Divisor = (Uart clock * 4) / baudrate */ ++ lsl w1, w1, #2 ++ udiv w2, w1, w2 ++ /* IBRD = Divisor >> 6 */ ++ lsr w1, w2, #6 ++ /* Write the IBRD */ ++ str w1, [x0, #UARTIBRD] ++ /* FBRD = Divisor & 0x3F */ ++ and w1, w2, #0x3f ++ /* Write the FBRD */ ++ str w1, [x0, #UARTFBRD] ++ mov w1, #PL011_LINE_CONTROL ++ str w1, [x0, #UARTLCR_H] ++ /* Clear any pending errors */ ++ str wzr, [x0, #UARTECR] ++ /* Enable tx, rx, and uart overall */ ++ mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) ++ str w1, [x0, #UARTCR] ++ mov w0, #1 ++ ret ++init_fail: ++ mov w0, wzr ++ ret ++endfunc console_core_init ++ ++ /* ------------------------------------------------- ++ * To allow alternate implementation of putc, pl011 ++ * is appended in the function name. ++ * ++ * int console_pl011_putc(int c) ++ * ++ * Clobber list : x1, x2 ++ * ------------------------------------------------- ++ */ ++func console_pl011_putc ++ adrp x1, console_base ++ ldr x1, [x1, :lo12:console_base] ++ b console_core_putc ++endfunc console_pl011_putc ++ ++ /* --------------------------------------------- ++ * int console_core_putc(int c, uintptr_t base_addr) ++ * Function to output a character over the console. It ++ * returns the character printed on success or an error ++ * code. ++ * In : w0 - Character to be printed ++ * x1 - Console base address ++ * Out : w0 - Input character or error code. ++ * Clobber list : x2 ++ * --------------------------------------------- ++ */ ++func console_core_putc ++ /* Check the input parameter */ ++ cbz x1, putc_error ++ /* Prepend '\r' to '\n' */ ++ cmp w0, #0xA ++ b.ne 2f ++1: ++ /* Check if the transmit FIFO is full */ ++ ldr w2, [x1, #UARTFR] ++ tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b ++ mov w2, #0xD ++ str w2, [x1, #UARTDR] ++2: ++ /* Check if the transmit FIFO is full */ ++ ldr w2, [x1, #UARTFR] ++ tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b ++ ++ /* Only write 8 bits */ ++ and w0, w0, #0xFF ++ str w0, [x1, #UARTDR] ++ ret ++putc_error: ++ mov w0, #ERROR_NO_VALID_CONSOLE ++ ret ++endfunc console_core_putc ++ ++ /* --------------------------------------------- ++ * int console_getc(void) ++ * ++ * Clobber list : x0 - x3 ++ * --------------------------------------------- ++ */ ++func console_getc ++ adrp x2, console_base ++ ldr x2, [x2, :lo12:console_base] ++ mov x3, x30 ++ ++ /* Loop until it returns a character or an error. */ ++1: mov x0, x2 ++ bl console_core_getc ++ cmp w0, #ERROR_NO_PENDING_CHAR ++ b.eq 1b ++ ++ ret x3 ++endfunc console_getc ++ ++ /* --------------------------------------------- ++ * int console_try_getc(void) ++ * ++ * Clobber list : x0, x1 ++ * --------------------------------------------- ++ */ ++func console_try_getc ++ adrp x0, console_base ++ ldr x0, [x0, :lo12:console_base] ++ b console_core_getc ++endfunc console_try_getc ++ ++ /* --------------------------------------------- ++ * int console_core_getc(uintptr_t base_addr) ++ * Function to get a character from the console. ++ * It returns the character grabbed on success ++ * or an error code. ++ * In : x0 - Console base address ++ * Out : w0 - Return character or error code. ++ * Clobber list : x0, x1 ++ * --------------------------------------------- ++ */ ++func console_core_getc ++ cbz x0, getc_error ++ ++ /* Check if the receive FIFO is empty */ ++ ldr w1, [x0, #UARTFR] ++ tbnz w1, #PL011_UARTFR_RXFE_BIT, getc_empty ++ ++ /* Read a character from the FIFO */ ++ ldr w0, [x0, #UARTDR] ++ /* Mask out error flags */ ++ and w0, w0, #0xFF ++ ret ++ ++getc_empty: ++ mov w0, #ERROR_NO_PENDING_CHAR ++ ret ++getc_error: ++ mov w0, #ERROR_NO_VALID_CONSOLE ++ ret ++endfunc console_core_getc ++ ++ /* --------------------------------------------- ++ * int console_flush(void) ++ * ++ * Clobber list : x0, x1 ++ * --------------------------------------------- ++ */ ++func console_flush ++ adrp x0, console_base ++ ldr x0, [x0, :lo12:console_base] ++ b console_core_flush ++endfunc console_flush ++ ++ /* --------------------------------------------- ++ * int console_core_flush(uintptr_t base_addr) ++ * Function to force a write of all buffered ++ * data that hasn't been output. ++ * In : x0 - Console base address ++ * Out : w0 - Error code or 0. ++ * Clobber list : x0, x1 ++ * --------------------------------------------- ++ */ ++func console_core_flush ++ cbz x0, flush_error ++ ++1: ++ /* Loop until the transmit FIFO is empty */ ++ ldr w1, [x0, #UARTFR] ++ tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b ++ ++ mov w0, wzr ++ ret ++flush_error: ++ mov w0, #ERROR_NO_VALID_CONSOLE ++ ret ++endfunc console_core_flush +diff --git a/environments/shim/plat/plat_helpers.S b/environments/shim/plat/plat_helpers.S +new file mode 100644 +index 0000000..863b378 +--- /dev/null ++++ b/environments/shim/plat/plat_helpers.S +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (c) 2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++ .globl platform_get_core_pos ++ .globl plat_crash_console_init ++ .globl plat_crash_console_putc ++ .globl plat_crash_console_flush ++ ++/*---------------------------------------------------------------------- ++ * unsigned int platform_get_core_pos(unsigned long mpid) ++ * ++ * Function to calculate the core position on TC0 platforms. ++ * ++ * (ClusterId * TC0_MAX_CPUS_PER_CLUSTER * TC0_MAX_PE_PER_CPU) + ++ * (CPUId * TC0_MAX_PE_PER_CPU) + ++ * ThreadId ++ * ++ * which can be simplified as: ++ * ++ * ((ClusterId * TC0_MAX_CPUS_PER_CLUSTER + CPUId) * TC0_MAX_PE_PER_CPU) ++ * + ThreadId ++ * --------------------------------------------------------------------- ++ */ ++func platform_get_core_pos ++ /* ++ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it ++ * look as if in a multi-threaded implementation. ++ */ ++ tst x0, #MPIDR_MT_MASK ++ lsl x3, x0, #MPIDR_AFFINITY_BITS ++ csel x3, x3, x0, eq ++ ++ /* Extract individual affinity fields from MPIDR */ ++ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS ++ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ++ ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS ++ ++ /* Compute linear position */ ++ mov x3, #TC0_MAX_CPUS_PER_CLUSTER ++ madd x1, x2, x3, x1 ++ mov x3, #TC0_MAX_PE_PER_CPU ++ madd x0, x1, x3, x0 ++ ret ++endfunc platform_get_core_pos ++ ++/* --------------------------------------------- ++ * int plat_crash_console_init(void) ++ * Function to initialize the crash console ++ * without a C Runtime to print crash report. ++ * Clobber list : x0 - x4 ++ * --------------------------------------------- ++ */ ++func plat_crash_console_init ++ mov_imm x0, PLAT_ARM_UART_BASE ++ mov_imm x1, PLAT_ARM_UART_CLK_IN_HZ ++ mov_imm x2, PL011_BAUDRATE ++ b console_core_init ++endfunc plat_crash_console_init ++ ++/* --------------------------------------------- ++ * int plat_crash_console_putc(int c) ++ * Function to print a character on the crash ++ * console without a C Runtime. ++ * Clobber list : x1, x2 ++ * --------------------------------------------- ++ */ ++func plat_crash_console_putc ++ mov_imm x1, PLAT_ARM_UART_BASE ++ b console_core_putc ++endfunc plat_crash_console_putc ++ ++/* --------------------------------------------- ++ * int plat_crash_console_flush() ++ * Function to force a write of all buffered ++ * data that hasn't been output. ++ * Out : return -1 on error else return 0. ++ * Clobber list : x0 - x1 ++ * --------------------------------------------- ++ */ ++func plat_crash_console_flush ++ mov_imm x1, PLAT_ARM_UART_BASE ++ b console_core_flush ++endfunc plat_crash_console_flush +diff --git a/environments/shim/shim_main.c b/environments/shim/shim_main.c +new file mode 100644 +index 0000000..dcb5d7a +--- /dev/null ++++ b/environments/shim/shim_main.c +@@ -0,0 +1,119 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define KERNEL_START (uintptr_t)0x80000000 ++#define KERNEL_SIZE (uintptr_t)0x7d000000 ++ ++#define CRYPTO_START (uintptr_t)0xFEC00000 ++#define CRYPTO_SIZE (uintptr_t)0x200000 ++ ++static void shim_print_memory_layout(void) ++{ ++ NOTICE("Secure Partition memory layout:\n"); ++ ++ NOTICE(" Image regions\n"); ++ NOTICE(" Text region : %p - %p\n", ++ (void *)SP_TEXT_START, (void *)SP_TEXT_END); ++ NOTICE(" Read-only data region : %p - %p\n", ++ (void *)SP_RODATA_START, (void *)SP_RODATA_END); ++ NOTICE(" Data region : %p - %p\n", ++ (void *)SP_DATA_START, (void *)SP_DATA_END); ++ NOTICE(" BSS region : %p - %p\n", ++ (void *)SP_BSS_START, (void *)SP_BSS_END); ++ NOTICE(" Total image memory : %p - %p\n", ++ (void *)SP_IMAGE_BASE, ++ (void *)(SP_IMAGE_BASE + SP_IMAGE_SIZE)); ++} ++ ++static void shim_plat_configure_mmu() ++{ ++ NOTICE("SHIM_TEXT_START = %p\n", (void *)SHIM_TEXT_START); ++ mmap_add_region(SHIM_TEXT_START, ++ SHIM_TEXT_START, ++ SHIM_TEXT_END - SHIM_TEXT_START, ++ MT_CODE | MT_PRIVILEGED); ++ mmap_add_region(SHIM_RODATA_START, ++ SHIM_RODATA_START, ++ SHIM_RODATA_END - SHIM_RODATA_START, ++ MT_RO_DATA | MT_PRIVILEGED); ++ mmap_add_region(SHIM_DATA_START, ++ SHIM_DATA_START, ++ SHIM_DATA_END - SHIM_DATA_START, ++ MT_RW_DATA | MT_PRIVILEGED); ++ mmap_add_region(SHIM_BSS_START, ++ SHIM_BSS_START, ++ SHIM_BSS_END - SHIM_BSS_START, ++ MT_RW_DATA | MT_PRIVILEGED); ++ mmap_add_region(SP_TEXT_START, ++ SP_TEXT_START, ++ SP_TEXT_END - SP_TEXT_START, ++ MT_CODE | MT_USER); ++ mmap_add_region(SP_RODATA_START, ++ SP_RODATA_START, ++ SP_RODATA_END - SP_RODATA_START, ++ MT_RO_DATA | MT_USER); ++ mmap_add_region(SP_DATA_START, ++ SP_DATA_START, ++ SP_DATA_END - SP_DATA_START, ++ MT_RW_DATA | MT_USER); ++ mmap_add_region(SP_BSS_START, ++ SP_BSS_START, ++ SP_BSS_END - SP_BSS_START, ++ MT_RW_DATA | MT_USER); ++ ++ mmap_add_region(KERNEL_START, ++ KERNEL_START, ++ KERNEL_SIZE, ++ MT_RW_DATA | MT_USER | MT_NS | MT_EXECUTE_NEVER); ++ ++/* map the crypto address space in the secure storage partition to access the ++ * buffer created by crypto partition ++ */ ++#ifdef SECURE_STORAGE ++ mmap_add_region(CRYPTO_START, ++ CRYPTO_START, ++ CRYPTO_SIZE, ++ MT_RW_DATA | MT_USER | MT_EXECUTE_NEVER); ++#endif ++ ++ init_xlat_tables(); ++} ++ ++int shim_main(void) ++{ ++ assert(IS_IN_EL1() != 0); ++ ++ /* Initialise console */ ++ set_putc_impl(HVC_CALL_AS_STDOUT); ++ ++ NOTICE("Booting S-EL1 Shim\n"); ++ ++ /* Configure and enable Stage-1 MMU, enable D-Cache */ ++ shim_plat_configure_mmu(); ++ enable_mmu_el1(0); ++ ++ shim_print_memory_layout(); ++ ++ set_putc_impl(SVC_CALL_AS_STDOUT); ++ ++ return 0; ++} +diff --git a/environments/shim/sp.ld.S b/environments/shim/sp.ld.S +new file mode 100644 +index 0000000..924ad5b +--- /dev/null ++++ b/environments/shim/sp.ld.S +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++ ++#include ++#include ++ ++OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) ++OUTPUT_ARCH(PLATFORM_LINKER_ARCH) ++ENTRY(shim_entrypoint) ++ ++SECTIONS ++{ ++ . = SP_IMAGE_BASE; ++ ++ ASSERT(. == ALIGN(PAGE_SIZE), ++ "TEXT_START address is not aligned to PAGE_SIZE.") ++ ++ /*----------------- START S-EL1 SHIM ----------------*/ ++ ++ .shim_text : { ++ __SHIM_TEXT_START__ = .; ++ *spm_shim_entrypoint.S.obj(.text*) ++ *(.vectors) ++ . = NEXT(PAGE_SIZE); ++ __SHIM_TEXT_END__ = .; ++ } ++ ++ .shim_rodata : { ++ . = ALIGN(PAGE_SIZE); ++ __SHIM_RODATA_START__ = .; ++ ++ . = NEXT(PAGE_SIZE); ++ __SHIM_RODATA_END__ = .; ++ } ++ ++ .shim_data : { ++ . = ALIGN(PAGE_SIZE); ++ __SHIM_DATA_START__ = .; ++ ++ . = NEXT(PAGE_SIZE); ++ __SHIM_DATA_END__ = .; ++ } ++ ++ .shim_bss (NOLOAD) : { ++ . = ALIGN(PAGE_SIZE); ++ __SHIM_BSS_START__ = .; ++ ++ *(.bss.shim_stacks) ++ *(.bss.tf_base_xlat_table) ++ *(.bss.tf_mmap) ++ *xlat_tables_context.c.obj(COMMON) ++ *xlat_tables_context.c.obj(xlat_table) ++ ++ . = NEXT(PAGE_SIZE); ++ __SHIM_BSS_END__ = .; ++ } ++ ++ /*----------------- END S-EL1 SHIM ----------------*/ ++ ++ .text : { ++ __TEXT_START__ = .; ++ *sp_entrypoint.S.obj(.text*) ++ *(.text*) ++ *(.vectors) ++ . = NEXT(PAGE_SIZE); ++ __TEXT_END__ = .; ++ } ++ ++ .rodata : { ++ . = ALIGN(PAGE_SIZE); ++ __RODATA_START__ = .; ++ *(.rodata*) ++ ++ /* ++ * Keep the .got section in the RO section as it is patched ++ * prior to enabling the MMU and having the .got in RO is better for ++ * security. GOT is a table of addresses so ensure 8-byte alignment. ++ */ ++ . = ALIGN(8); ++ __GOT_START__ = .; ++ *(.got) ++ __GOT_END__ = .; ++ ++ . = NEXT(PAGE_SIZE); ++ __RODATA_END__ = .; ++ } ++ ++ .data : { ++ . = ALIGN(PAGE_SIZE); ++ __DATA_START__ = .; ++ *(.data*) ++ . = NEXT(PAGE_SIZE); ++ __DATA_END__ = .; ++ } ++ ++ /* ++ * .rela.dyn needs to come after .data for the read-elf utility to parse ++ * this section correctly. Ensure 8-byte alignment so that the fields of ++ * RELA data structure are aligned. ++ */ ++ . = ALIGN(8); ++ __RELA_START__ = .; ++ .rela.dyn . : { ++ } ++ __RELA_END__ = .; ++ ++ ++ .bss (NOLOAD) : { ++ . = ALIGN(PAGE_SIZE); ++ __BSS_START__ = .; ++ *(SORT_BY_ALIGNMENT(.bss*)) ++ *(COMMON) ++ . = NEXT(PAGE_SIZE); ++ __BSS_END__ = .; ++ } ++} +diff --git a/environments/shim/spm/common/aarch64/sp_arch_helpers.S b/environments/shim/spm/common/aarch64/sp_arch_helpers.S +new file mode 100644 +index 0000000..bfa8cce +--- /dev/null ++++ b/environments/shim/spm/common/aarch64/sp_arch_helpers.S +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2018-2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#define __ASSEMBLY__ ++#include ++ ++ .globl sp_svc ++ ++func sp_svc ++ /* ++ * Save the address of the svc_args structure on the stack. ++ * ++ * Although x0 contains an 8-byte value, we are allocating 16 bytes ++ * on the stack to respect the 16-byte stack-alignment. ++ */ ++ str x0, [sp, #-16]! ++ ++ /* Load the SVC arguments values into the appropriate registers. */ ++ ldp x6, x7, [x0, #48] ++ ldp x4, x5, [x0, #32] ++ ldp x2, x3, [x0, #16] ++ ldp x0, x1, [x0, #0] ++ ++ svc #0 ++ ++ /* ++ * Pop the svc_args structure address from the stack into a caller-saved ++ * register. ++ */ ++ ldr x9, [sp], #16 ++ ++ /* ++ * The return values are stored in x0-x3, put them in the svc_args ++ * return structure. ++ */ ++ stp x0, x1, [x9, #0] ++ stp x2, x3, [x9, #16] ++ ret ++endfunc sp_svc +diff --git a/environments/shim/spm/common/sp_debug.c b/environments/shim/spm/common/sp_debug.c +new file mode 100644 +index 0000000..8182abb +--- /dev/null ++++ b/environments/shim/spm/common/sp_debug.c +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ ++static int (*putc_impl)(int); ++ ++static int putc_hypcall(int c) ++{ ++ spm_debug_log((char)c); ++ ++ return c; ++} ++ ++static int putc_svccall(int c) ++{ ++ /* TODO svc call */ ++ svc_args args = { ++ .fid = SPM_DEBUG_LOG, ++ .arg1 = c ++ }; ++ sp_svc(&args); ++ ++ return c; ++} ++ ++static int putc_uart(int c) ++{ ++ console_pl011_putc(c); ++ ++ return c; ++} ++ ++void set_putc_impl(enum stdout_route route) ++{ ++ switch (route) { ++ ++ case HVC_CALL_AS_STDOUT: ++ putc_impl = putc_hypcall; ++ return; ++ ++ case SVC_CALL_AS_STDOUT: ++ putc_impl = putc_svccall; ++ return; ++ ++ case PL011_AS_STDOUT: ++ default: ++ break; ++ } ++ ++ putc_impl = putc_uart; ++} ++ ++int console_putc(int c) ++{ ++ if (!putc_impl) { ++ return -1; ++ } ++ ++ return putc_impl(c); ++} +diff --git a/environments/shim/spm/common/sp_debug.h b/environments/shim/spm/common/sp_debug.h +new file mode 100644 +index 0000000..e35c602 +--- /dev/null ++++ b/environments/shim/spm/common/sp_debug.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++enum stdout_route { ++ PL011_AS_STDOUT = 0, ++ HVC_CALL_AS_STDOUT, ++ SVC_CALL_AS_STDOUT, ++}; ++ ++void set_putc_impl(enum stdout_route); +diff --git a/environments/shim/spm/common/sp_helpers.c b/environments/shim/spm/common/sp_helpers.c +new file mode 100644 +index 0000000..1b650d3 +--- /dev/null ++++ b/environments/shim/spm/common/sp_helpers.c +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (c) 2018, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sp_helpers.h" ++ ++uintptr_t bound_rand(uintptr_t min, uintptr_t max) ++{ ++ /* ++ * This is not ideal as some numbers will never be generated because of ++ * the integer arithmetic rounding. ++ */ ++ return ((rand() * (UINT64_MAX/RAND_MAX)) % (max - min)) + min; ++} ++ ++/******************************************************************************* ++ * Test framework helpers ++ ******************************************************************************/ ++ ++void expect(int expr, int expected) ++{ ++ if (expr != expected) { ++ ERROR("Expected value %i, got %i\n", expected, expr); ++ while (1) ++ continue; ++ } ++} ++ ++void announce_test_section_start(const char *test_sect_desc) ++{ ++ INFO("========================================\n"); ++ INFO("Starting %s tests\n", test_sect_desc); ++ INFO("========================================\n"); ++} ++void announce_test_section_end(const char *test_sect_desc) ++{ ++ INFO("========================================\n"); ++ INFO("End of %s tests\n", test_sect_desc); ++ INFO("========================================\n"); ++} ++ ++void announce_test_start(const char *test_desc) ++{ ++ INFO("[+] %s\n", test_desc); ++} ++ ++void announce_test_end(const char *test_desc) ++{ ++ INFO("Test \"%s\" end.\n", test_desc); ++} ++ ++void sp_sleep(uint32_t ms) ++{ ++ uint64_t timer_freq = mmio_read_32(SYS_CNT_CONTROL_BASE + CNTFID_OFF); ++ VERBOSE("%s: Timer frequency = %llu\n", __func__, timer_freq); ++ ++ VERBOSE("%s: Sleeping for %u milliseconds...\n", __func__, ms); ++ uint64_t time1 = mmio_read_64(SYS_CNT_READ_BASE); ++ volatile uint64_t time2 = time1; ++ while ((time2 - time1) < ((ms * timer_freq) / 1000U)) { ++ time2 = mmio_read_64(SYS_CNT_READ_BASE); ++ } ++} ++ ++/******************************************************************************* ++ * Hypervisor Calls Wrappers ++ ******************************************************************************/ ++ ++ffa_int_id_t spm_interrupt_get(void) ++{ ++ hvc_args args = { ++ .fid = SPM_INTERRUPT_GET ++ }; ++ ++ hvc_ret_values ret = tftf_hvc(&args); ++ ++ return ret.ret0; ++} ++ ++void spm_debug_log(char c) ++{ ++ hvc_args args = { ++ .fid = SPM_DEBUG_LOG, ++ .arg1 = c ++ }; ++ ++ (void)tftf_hvc(&args); ++} +diff --git a/environments/shim/spm/common/sp_helpers.h b/environments/shim/spm/common/sp_helpers.h +new file mode 100644 +index 0000000..ec92227 +--- /dev/null ++++ b/environments/shim/spm/common/sp_helpers.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2018-2020, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SP_HELPERS_H ++#define SP_HELPERS_H ++ ++#include ++#include ++#include ++ ++#define SPM_VM_ID_FIRST SP_ID(1) ++ ++/* Should match with IDs defined in SPM/Hafnium */ ++#define SPM_INTERRUPT_GET (0xFF04) ++#define SPM_DEBUG_LOG (0xBD000000) ++ ++typedef struct { ++ u_register_t fid; ++ u_register_t arg1; ++ u_register_t arg2; ++ u_register_t arg3; ++ u_register_t arg4; ++ u_register_t arg5; ++ u_register_t arg6; ++ u_register_t arg7; ++} svc_args; ++ ++/* ++ * Trigger an SVC call. ++ * ++ * The arguments to pass through the SVC call must be stored in the svc_args ++ * structure. The return values of the SVC call will be stored in the same ++ * structure (overriding the input arguments). ++ * ++ * Return the first return value. It is equivalent to args.fid but is also ++ * provided as the return value for convenience. ++ */ ++u_register_t sp_svc(svc_args *args); ++ ++/* ++ * Choose a pseudo-random number within the [min,max] range (both limits are ++ * inclusive). ++ */ ++uintptr_t bound_rand(uintptr_t min, uintptr_t max); ++ ++/* ++ * Check that expr == expected. ++ * If not, loop forever. ++ */ ++void expect(int expr, int expected); ++ ++/* ++ * Test framework functions ++ */ ++ ++void announce_test_section_start(const char *test_sect_desc); ++void announce_test_section_end(const char *test_sect_desc); ++ ++void announce_test_start(const char *test_desc); ++void announce_test_end(const char *test_desc); ++ ++/* Sleep for at least 'ms' milliseconds. */ ++void sp_sleep(uint32_t ms); ++ ++/* ++ * Hypervisor Calls Wrappers ++ */ ++ ++ffa_int_id_t spm_interrupt_get(void); ++ ++void spm_debug_log(char c); ++ ++#endif /* SP_HELPERS_H */ +diff --git a/external/bget/bget.cmake b/external/bget/bget.cmake +new file mode 100644 +index 0000000..b51882a +--- /dev/null ++++ b/external/bget/bget.cmake +@@ -0,0 +1,52 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++cmake_minimum_required(VERSION 3.18) ++ ++set(BGET_ARCHIVE_FILE "${CMAKE_BINARY_DIR}/bget.tgz" CACHE PATH "Full path of BGET archive file") ++set(BGET_DIR "${CMAKE_BINARY_DIR}/bget" CACHE PATH "Path to BGET source") ++ ++function(dl_bget) ++ file(DOWNLOAD "https://www.fourmilab.ch/bget/bget.tar.gz" ${BGET_ARCHIVE_FILE} STATUS "_dl_res") ++ list(GET _dl_res 0 _dl_rv) ++ if(_dl_rv) ++ list(GET _dl_res 1 _dl_error) ++ message(FATAL_ERROR "Failed to download bget: ${_dl_error}") ++ endif() ++endfunction() ++ ++set(_bget_src "${TS_ROOT}/environments/shim/lib/libc") ++set(_bget_inc "${TS_ROOT}/environments/shim/include/lib/libc") ++ ++# If bget source is missing from project. ++if(NOT EXISTS "${_bget_inc}/bget.h" OR NOT EXISTS "${_bget_src}/bget.c") ++ # If bget source is not extracted. ++ if(NOT EXISTS "${BGET_DIR}/bget.h") ++ # if the archive is not downloaded ++ if(NOT EXISTS "${BGET_ARCHIVE_FILE}") ++ dl_bget() ++ endif() ++ ++ file(ARCHIVE_EXTRACT ++ INPUT "${BGET_ARCHIVE_FILE}" ++ DESTINATION "${BGET_DIR}" ++ ) ++ ++ if(NOT EXISTS "${BGET_DIR}/bget.c") ++ message(FATAL_ERROR "Failed to extract ${BGET_ARCHIVE_FILE}") ++ endif() ++ endif() ++ ++ # copy files to project ++ file(COPY "${BGET_DIR}/bget.c" DESTINATION "${_bget_src}") ++ file(COPY "${BGET_DIR}/bget.h" DESTINATION "${_bget_inc}") ++ ++ # Apply patch ++ execute_process(COMMAND git apply external/bget/bget.patch ++ WORKING_DIRECTORY ${TS_ROOT} ++ ) ++ ++endif() +diff --git a/external/bget/bget.patch b/external/bget/bget.patch +new file mode 100644 +index 0000000..382c5cd +--- /dev/null ++++ b/external/bget/bget.patch +@@ -0,0 +1,675 @@ ++Copyright (c) 2015, Linaro Limited ++Copyright (c) 2021, Arm Limited ++SPDX-License-Identifier: BSD-2-Clause ++ ++This file contains work dervived form OP-TEE os. The work is based on ++https://github.com/OP-TEE/optee_os SHA: 203ee23d005b2cec2f21b5de334c5a246be32599 ++ ++This patch allows re-creating the same state for the covered fies as can be seen ++in the version designated above. ++ ++diff --git a/environments/shim/include/lib/libc/bget.h b/environments/shim/include/lib/libc/bget.h ++index 0c72d0e..8071639 100644 ++--- a/environments/shim/include/lib/libc/bget.h +++++ b/environments/shim/include/lib/libc/bget.h ++@@ -1,9 +1,23 @@ +++/* +++ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +++ * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +++ */ +++ ++ /* ++ ++ Interface definitions for bget.c, the memory management package. ++ ++ */ ++ +++ ++ #ifndef _ ++ #ifdef PROTOTYPES ++ #define _(x) x /* If compiler knows prototypes */ ++@@ -13,18 +27,23 @@ ++ #endif ++ ++ typedef long bufsize; ++-void bpool _((void *buffer, bufsize len)); ++-void *bget _((bufsize size)); ++-void *bgetz _((bufsize size)); ++-void *bgetr _((void *buffer, bufsize newsize)); ++-void brel _((void *buf)); +++struct bpoolset; +++ +++void bpool _((void *buffer, bufsize len, struct bpoolset *poolset)); +++void *bget _((bufsize size, struct bpoolset *poolset)); +++void *bgetz _((bufsize size, struct bpoolset *poolset)); +++void *bgetr _((void *buffer, bufsize newsize, +++ struct bpoolset *poolset)); +++void brel _((void *buf, struct bpoolset *poolset, int wipe)); ++ void bectl _((int (*compact)(bufsize sizereq, int sequence), ++ void *(*acquire)(bufsize size), ++- void (*release)(void *buf), bufsize pool_incr)); +++ void (*release)(void *buf), bufsize pool_incr, +++ struct bpoolset *poolset)); ++ void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree, ++- long *nget, long *nrel)); +++ long *nget, long *nrel, struct bpoolset *poolset)); ++ void bstatse _((bufsize *pool_incr, long *npool, long *npget, ++- long *nprel, long *ndget, long *ndrel)); +++ long *nprel, long *ndget, long *ndrel, +++ struct bpoolset *poolset)); ++ void bufdump _((void *buf)); ++ void bpoold _((void *pool, int dumpalloc, int dumpfree)); ++ int bpoolv _((void *pool)); ++diff --git a/environments/shim/lib/libc/bget.c b/environments/shim/lib/libc/bget.c ++index 5423cb9..3e3d644 100644 ++--- a/environments/shim/lib/libc/bget.c +++++ b/environments/shim/lib/libc/bget.c ++@@ -398,6 +398,21 @@ ++ ================== ++ */ ++ +++/* +++ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +++ * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +++ */ +++ +++/* #define BGET_ENABLE_ALL_OPTIONS */ +++#ifdef BGET_ENABLE_OPTION ++ #define TestProg 20000 /* Generate built-in test program ++ if defined. The value specifies ++ how many buffer allocation attempts ++@@ -414,7 +429,7 @@ ++ ++ #define BufValid 1 /* Define this symbol to enable the ++ bpoolv() function for validating ++- a buffer pool. */ +++ a buffer pool. */ ++ ++ #define DumpData 1 /* Define this symbol to enable the ++ bufdump() function which allows ++@@ -442,8 +457,10 @@ ++ #define BECtl 1 /* Define this symbol to enable the ++ bectl() function for automatic ++ pool space control. */ +++#endif ++ ++ #include +++#include ++ ++ #ifdef lint ++ #define NDEBUG /* Exits in asserts confuse lint */ ++@@ -464,6 +481,12 @@ extern char *sprintf(); /* Sun includes don't define sprintf */ ++ #include ++ #endif ++ +++#ifdef __KERNEL__ +++#ifdef CFG_CORE_BGET_BESTFIT +++#define BestFit 1 +++#endif +++#endif +++ ++ /* Declare the interface, including the requested buffer size type, ++ bufsize. */ ++ ++@@ -506,38 +529,38 @@ struct bfhead { ++ }; ++ #define BFH(p) ((struct bfhead *) (p)) ++ ++-static struct bfhead freelist = { /* List of free buffers */ ++- {0, 0}, ++- {&freelist, &freelist} ++-}; ++- ++- +++/* Poolset definition */ +++struct bpoolset { +++ struct bfhead freelist; ++ #ifdef BufStats ++-static bufsize totalloc = 0; /* Total space currently allocated */ ++-static long numget = 0, numrel = 0; /* Number of bget() and brel() calls */ +++ bufsize totalloc; /* Total space currently allocated */ +++ long numget; /* Number of bget() calls */ +++ long numrel; /* Number of brel() calls */ ++ #ifdef BECtl ++-static long numpblk = 0; /* Number of pool blocks */ ++-static long numpget = 0, numprel = 0; /* Number of block gets and rels */ ++-static long numdget = 0, numdrel = 0; /* Number of direct gets and rels */ +++ long numpblk; /* Number of pool blocks */ +++ long numpget; /* Number of block gets and rels */ +++ long numprel; +++ long numdget; /* Number of direct gets and rels */ +++ long numdrel; ++ #endif /* BECtl */ ++ #endif /* BufStats */ ++ ++ #ifdef BECtl +++ /* Automatic expansion block management functions */ ++ ++-/* Automatic expansion block management functions */ +++ int (*compfcn) _((bufsize sizereq, int sequence)); +++ void *(*acqfcn) _((bufsize size)); +++ void (*relfcn) _((void *buf)); ++ ++-static int (*compfcn) _((bufsize sizereq, int sequence)) = NULL; ++-static void *(*acqfcn) _((bufsize size)) = NULL; ++-static void (*relfcn) _((void *buf)) = NULL; ++- ++-static bufsize exp_incr = 0; /* Expansion block size */ ++-static bufsize pool_len = 0; /* 0: no bpool calls have been made +++ bufsize exp_incr; /* Expansion block size */ +++ bufsize pool_len; /* 0: no bpool calls have been made ++ -1: not all pool blocks are ++ the same size ++ >0: (common) block size for all ++ bpool calls made so far ++ */ ++ #endif +++}; ++ ++ /* Minimum allocation quantum: */ ++ ++@@ -554,8 +577,9 @@ static bufsize pool_len = 0; /* 0: no bpool calls have been made ++ ++ /* BGET -- Allocate a buffer. */ ++ ++-void *bget(requested_size) +++void *bget(requested_size, poolset) ++ bufsize requested_size; +++ struct bpoolset *poolset; ++ { ++ bufsize size = requested_size; ++ struct bfhead *b; ++@@ -574,12 +598,16 @@ void *bget(requested_size) ++ } ++ #ifdef SizeQuant ++ #if SizeQuant > 1 ++- size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1)); +++ if (ADD_OVERFLOW(size, SizeQuant - 1, &size)) +++ return NULL; +++ +++ size = ROUNDDOWN(size, SizeQuant); ++ #endif ++ #endif ++ ++- size += sizeof(struct bhead); /* Add overhead in allocated buffer ++- to size required. */ +++ /* Add overhead in allocated buffer to size required. */ +++ if (ADD_OVERFLOW(size, sizeof(struct bhead), &size)) +++ return NULL; ++ ++ #ifdef BECtl ++ /* If a compact function was provided in the call to bectl(), wrap ++@@ -588,9 +616,9 @@ void *bget(requested_size) ++ ++ while (1) { ++ #endif ++- b = freelist.ql.flink; +++ b = poolset->freelist.ql.flink; ++ #ifdef BestFit ++- best = &freelist; +++ best = &poolset->freelist; ++ #endif ++ ++ ++@@ -598,9 +626,10 @@ void *bget(requested_size) ++ to hold the requested size buffer. */ ++ ++ #ifdef BestFit ++- while (b != &freelist) { +++ while (b != &poolset->freelist) { ++ if (b->bh.bsize >= size) { ++- if ((best == &freelist) || (b->bh.bsize < best->bh.bsize)) { +++ if ((best == &poolset->freelist) || +++ (b->bh.bsize < best->bh.bsize)) { ++ best = b; ++ } ++ } ++@@ -609,7 +638,7 @@ void *bget(requested_size) ++ b = best; ++ #endif /* BestFit */ ++ ++- while (b != &freelist) { +++ while (b != &poolset->freelist) { ++ if ((bufsize) b->bh.bsize >= size) { ++ ++ /* Buffer is big enough to satisfy the request. Allocate it ++@@ -637,10 +666,11 @@ void *bget(requested_size) ++ bn->prevfree = 0; ++ ++ #ifdef BufStats ++- totalloc += size; ++- numget++; /* Increment number of bget() calls */ +++ poolset->totalloc += size; +++ poolset->numget++; /* Increment number of bget() calls */ ++ #endif ++ buf = (void *) ((((char *) ba) + sizeof(struct bhead))); +++ tag_asan_alloced(buf, size); ++ return buf; ++ } else { ++ struct bhead *ba; ++@@ -657,8 +687,8 @@ void *bget(requested_size) ++ b->ql.flink->ql.blink = b->ql.blink; ++ ++ #ifdef BufStats ++- totalloc += b->bh.bsize; ++- numget++; /* Increment number of bget() calls */ +++ poolset->totalloc += b->bh.bsize; +++ poolset->numget++; /* Increment number of bget() calls */ ++ #endif ++ /* Negate size to mark buffer allocated. */ ++ b->bh.bsize = -(b->bh.bsize); ++@@ -669,6 +699,7 @@ void *bget(requested_size) ++ ++ /* Give user buffer starting at queue links. */ ++ buf = (void *) &(b->ql); +++ tag_asan_alloced(buf, size); ++ return buf; ++ } ++ } ++@@ -680,7 +711,8 @@ void *bget(requested_size) ++ defined, notify it of the size requested. If it returns ++ TRUE, try the allocation again. */ ++ ++- if ((compfcn == NULL) || (!(*compfcn)(size, ++compactseq))) { +++ if ((poolset->compfcn == NULL) || +++ (!(poolset->compfcn)(size, ++compactseq))) { ++ break; ++ } ++ } ++@@ -689,7 +721,7 @@ void *bget(requested_size) ++ ++ /* Don't give up yet -- look in the reserve supply. */ ++ ++- if (acqfcn != NULL) { +++ if (poolset->acqfcn != NULL) { ++ if (size > exp_incr - sizeof(struct bhead)) { ++ ++ /* Request is too large to fit in a single expansion ++@@ -706,11 +738,12 @@ void *bget(requested_size) ++ bdh->bh.prevfree = 0; ++ bdh->tsize = size; ++ #ifdef BufStats ++- totalloc += size; ++- numget++; /* Increment number of bget() calls */ ++- numdget++; /* Direct bget() call count */ +++ poolset->totalloc += size; +++ poolset->numget++; /* Increment number of bget() calls */ +++ poolset->numdget++; /* Direct bget() call count */ ++ #endif ++ buf = (void *) (bdh + 1); +++ tag_asan_alloced(buf, size); ++ return buf; ++ } ++ ++@@ -720,10 +753,10 @@ void *bget(requested_size) ++ ++ void *newpool; ++ ++- if ((newpool = (*acqfcn)((bufsize) exp_incr)) != NULL) { ++- bpool(newpool, exp_incr); ++- buf = bget(requested_size); /* This can't, I say, can't ++- get into a loop. */ +++ if ((newpool = poolset->acqfcn((bufsize) exp_incr)) != NULL) { +++ bpool(newpool, exp_incr, poolset); +++ buf = bget(requested_size, pool); /* This can't, I say, can't +++ get into a loop. */ ++ return buf; ++ } ++ } ++@@ -740,10 +773,11 @@ void *bget(requested_size) ++ the entire contents of the buffer to zero, not just the ++ region requested by the caller. */ ++ ++-void *bgetz(size) +++void *bgetz(size, poolset) ++ bufsize size; +++ struct bpoolset *poolset; ++ { ++- char *buf = (char *) bget(size); +++ char *buf = (char *) bget(size, poolset); ++ ++ if (buf != NULL) { ++ struct bhead *b; ++@@ -760,7 +794,7 @@ void *bgetz(size) ++ rsize -= sizeof(struct bhead); ++ } ++ assert(rsize >= size); ++- V memset(buf, 0, (MemSize) rsize); +++ V memset_unchecked(buf, 0, (MemSize) rsize); ++ } ++ return ((void *) buf); ++ } ++@@ -770,15 +804,16 @@ void *bgetz(size) ++ enhanced to allow the buffer to grow into adjacent free ++ blocks and to avoid moving data unnecessarily. */ ++ ++-void *bgetr(buf, size) +++void *bgetr(buf, size, poolset) ++ void *buf; ++ bufsize size; +++ struct bpoolset *poolset; ++ { ++ void *nbuf; ++ bufsize osize; /* Old size of buffer */ ++ struct bhead *b; ++ ++- if ((nbuf = bget(size)) == NULL) { /* Acquire new buffer */ +++ if ((nbuf = bget(size, poolset)) == NULL) { /* Acquire new buffer */ ++ return NULL; ++ } ++ if (buf == NULL) { ++@@ -799,23 +834,34 @@ void *bgetr(buf, size) ++ assert(osize > 0); ++ V memcpy((char *) nbuf, (char *) buf, /* Copy the data */ ++ (MemSize) ((size < osize) ? size : osize)); ++- brel(buf); +++#ifndef __KERNEL__ +++ /* User space reallocations are always zeroed */ +++ if (size > osize) +++ V memset((char *) nbuf + osize, 0, size - osize); +++#endif +++ brel(buf, poolset, false /* !wipe */); ++ return nbuf; ++ } ++ ++ /* BREL -- Release a buffer. */ ++ ++-void brel(buf) +++void brel(buf, poolset, wipe) ++ void *buf; +++ struct bpoolset *poolset; +++ int wipe; ++ { ++ struct bfhead *b, *bn; +++ bufsize bs; ++ ++ b = BFH(((char *) buf) - sizeof(struct bhead)); ++ #ifdef BufStats ++- numrel++; /* Increment number of brel() calls */ +++ poolset->numrel++; /* Increment number of brel() calls */ ++ #endif ++ assert(buf != NULL); ++ +++#ifdef FreeWipe +++ wipe = true; +++#endif ++ #ifdef BECtl ++ if (b->bh.bsize == 0) { /* Directly-acquired buffer? */ ++ struct bdhead *bdh; ++@@ -823,16 +869,19 @@ void brel(buf) ++ bdh = BDH(((char *) buf) - sizeof(struct bdhead)); ++ assert(b->bh.prevfree == 0); ++ #ifdef BufStats ++- totalloc -= bdh->tsize; ++- assert(totalloc >= 0); ++- numdrel++; /* Number of direct releases */ +++ poolset->totalloc -= bdh->tsize; +++ assert(poolset->totalloc >= 0); +++ poolset->numdrel++; /* Number of direct releases */ ++ #endif /* BufStats */ ++-#ifdef FreeWipe ++- V memset((char *) buf, 0x55, ++- (MemSize) (bdh->tsize - sizeof(struct bdhead))); ++-#endif /* FreeWipe */ ++- assert(relfcn != NULL); ++- (*relfcn)((void *) bdh); /* Release it directly. */ +++ if (wipe) { +++ V memset_unchecked((char *) buf, 0x55, +++ (MemSize) (bdh->tsize - +++ sizeof(struct bdhead))); +++ } +++ bs = bdh->tsize - sizeof(struct bdhead); +++ assert(poolset->relfcn != NULL); +++ poolset->relfcn((void *) bdh); /* Release it directly. */ +++ tag_asan_free(buf, bs); ++ return; ++ } ++ #endif /* BECtl */ ++@@ -844,6 +893,7 @@ void brel(buf) ++ bn = NULL; ++ } ++ assert(b->bh.bsize < 0); +++ bs = -b->bh.bsize; ++ ++ /* Back pointer in next buffer must be zero, indicating the ++ same thing: */ ++@@ -851,8 +901,8 @@ void brel(buf) ++ assert(BH((char *) b - b->bh.bsize)->prevfree == 0); ++ ++ #ifdef BufStats ++- totalloc += b->bh.bsize; ++- assert(totalloc >= 0); +++ poolset->totalloc += b->bh.bsize; +++ assert(poolset->totalloc >= 0); ++ #endif ++ ++ /* If the back link is nonzero, the previous buffer is free. */ ++@@ -876,11 +926,11 @@ void brel(buf) ++ /* The previous buffer isn't allocated. Insert this buffer ++ on the free list as an isolated free block. */ ++ ++- assert(freelist.ql.blink->ql.flink == &freelist); ++- assert(freelist.ql.flink->ql.blink == &freelist); ++- b->ql.flink = &freelist; ++- b->ql.blink = freelist.ql.blink; ++- freelist.ql.blink = b; +++ assert(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); +++ assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); +++ b->ql.flink = &poolset->freelist; +++ b->ql.blink = poolset->freelist.ql.blink; +++ poolset->freelist.ql.blink = b; ++ b->ql.blink->ql.flink = b; ++ b->bh.bsize = -b->bh.bsize; ++ } ++@@ -912,10 +962,10 @@ void brel(buf) ++ ++ bn = BFH(((char *) b) + b->bh.bsize); ++ } ++-#ifdef FreeWipe ++- V memset(((char *) b) + sizeof(struct bfhead), 0x55, ++- (MemSize) (b->bh.bsize - sizeof(struct bfhead))); ++-#endif +++ if (wipe) { +++ V memset_unchecked(((char *) b) + sizeof(struct bfhead), 0x55, +++ (MemSize) (b->bh.bsize - sizeof(struct bfhead))); +++ } ++ assert(bn->bh.bsize < 0); ++ ++ /* The next buffer is allocated. Set the backpointer in it to point ++@@ -930,7 +980,7 @@ void brel(buf) ++ is defined in such a way that the test will fail unless all ++ pool blocks are the same size. */ ++ ++- if (relfcn != NULL && +++ if (poolset->relfcn != NULL && ++ ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) { ++ ++ assert(b->bh.prevfree == 0); ++@@ -940,38 +990,41 @@ void brel(buf) ++ b->ql.blink->ql.flink = b->ql.flink; ++ b->ql.flink->ql.blink = b->ql.blink; ++ ++- (*relfcn)(b); +++ poolset->relfcn(b); ++ #ifdef BufStats ++- numprel++; /* Nr of expansion block releases */ ++- numpblk--; /* Total number of blocks */ +++ poolset->numprel++; /* Nr of expansion block releases */ +++ poolset->numpblk--; /* Total number of blocks */ ++ assert(numpblk == numpget - numprel); ++ #endif /* BufStats */ ++ } ++ #endif /* BECtl */ +++ tag_asan_free(buf, bs); ++ } ++ ++ #ifdef BECtl ++ ++ /* BECTL -- Establish automatic pool expansion control */ ++ ++-void bectl(compact, acquire, release, pool_incr) +++void bectl(compact, acquire, release, pool_incr, poolset) ++ int (*compact) _((bufsize sizereq, int sequence)); ++ void *(*acquire) _((bufsize size)); ++ void (*release) _((void *buf)); ++ bufsize pool_incr; +++ struct bpoolset *poolset; ++ { ++- compfcn = compact; ++- acqfcn = acquire; ++- relfcn = release; ++- exp_incr = pool_incr; +++ poolset->compfcn = compact; +++ poolset->acqfcn = acquire; +++ poolset->relfcn = release; +++ poolset->exp_incr = pool_incr; ++ } ++ #endif ++ ++ /* BPOOL -- Add a region of memory to the buffer pool. */ ++ ++-void bpool(buf, len) +++void bpool(buf, len, poolset) ++ void *buf; ++ bufsize len; +++ struct bpoolset *poolset; ++ { ++ struct bfhead *b = BFH(buf); ++ struct bhead *bn; ++@@ -980,15 +1033,15 @@ void bpool(buf, len) ++ len &= ~(SizeQuant - 1); ++ #endif ++ #ifdef BECtl ++- if (pool_len == 0) { +++ if (poolset->pool_len == 0) { ++ pool_len = len; ++- } else if (len != pool_len) { ++- pool_len = -1; +++ } else if (len != poolset->pool_len) { +++ poolset->pool_len = -1; ++ } ++ #ifdef BufStats ++- numpget++; /* Number of block acquisitions */ ++- numpblk++; /* Number of blocks total */ ++- assert(numpblk == numpget - numprel); +++ poolset->numpget++; /* Number of block acquisitions */ +++ poolset->numpblk++; /* Number of blocks total */ +++ assert(poolset->numpblk == poolset->numpget - poolset->numprel); ++ #endif /* BufStats */ ++ #endif /* BECtl */ ++ ++@@ -1006,11 +1059,11 @@ void bpool(buf, len) ++ ++ /* Chain the new block to the free list. */ ++ ++- assert(freelist.ql.blink->ql.flink == &freelist); ++- assert(freelist.ql.flink->ql.blink == &freelist); ++- b->ql.flink = &freelist; ++- b->ql.blink = freelist.ql.blink; ++- freelist.ql.blink = b; +++ assert(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); +++ assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); +++ b->ql.flink = &poolset->freelist; +++ b->ql.blink = poolset->freelist.ql.blink; +++ poolset->freelist.ql.blink = b; ++ b->ql.blink->ql.flink = b; ++ ++ /* Create a dummy allocated buffer at the end of the pool. This dummy ++@@ -1024,8 +1077,8 @@ void bpool(buf, len) ++ len -= sizeof(struct bhead); ++ b->bh.bsize = (bufsize) len; ++ #ifdef FreeWipe ++- V memset(((char *) b) + sizeof(struct bfhead), 0x55, ++- (MemSize) (len - sizeof(struct bfhead))); +++ V memset_unchecked(((char *) b) + sizeof(struct bfhead), 0x55, +++ (MemSize) (len - sizeof(struct bfhead))); ++ #endif ++ bn = BH(((char *) b) + len); ++ bn->prevfree = (bufsize) len; ++@@ -1038,18 +1091,19 @@ void bpool(buf, len) ++ ++ /* BSTATS -- Return buffer allocation free space statistics. */ ++ ++-void bstats(curalloc, totfree, maxfree, nget, nrel) +++void bstats(curalloc, totfree, maxfree, nget, nrel, poolset) ++ bufsize *curalloc, *totfree, *maxfree; ++ long *nget, *nrel; +++ struct bpoolset *poolset; ++ { ++- struct bfhead *b = freelist.ql.flink; +++ struct bfhead *b = poolset->freelist.ql.flink; ++ ++- *nget = numget; ++- *nrel = numrel; ++- *curalloc = totalloc; +++ *nget = poolset->numget; +++ *nrel = poolset->numrel; +++ *curalloc = poolset->totalloc; ++ *totfree = 0; ++ *maxfree = -1; ++- while (b != &freelist) { +++ while (b != &poolset->freelist) { ++ assert(b->bh.bsize > 0); ++ *totfree += b->bh.bsize; ++ if (b->bh.bsize > *maxfree) { ++@@ -1063,16 +1117,18 @@ void bstats(curalloc, totfree, maxfree, nget, nrel) ++ ++ /* BSTATSE -- Return extended statistics */ ++ ++-void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel) +++void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel, poolset) ++ bufsize *pool_incr; ++ long *npool, *npget, *nprel, *ndget, *ndrel; +++ struct bpoolset *poolset; ++ { ++- *pool_incr = (pool_len < 0) ? -exp_incr : exp_incr; ++- *npool = numpblk; ++- *npget = numpget; ++- *nprel = numprel; ++- *ndget = numdget; ++- *ndrel = numdrel; +++ *pool_incr = (poolset->pool_len < 0) ? +++ -poolset->exp_incr : poolset->exp_incr; +++ *npool = poolset->numpblk; +++ *npget = poolset->numpget; +++ *nprel = poolset->numprel; +++ *ndget = poolset->numdget; +++ *ndrel = poolset->numdrel; ++ } ++ #endif /* BECtl */ ++ #endif /* BufStats */ ++@@ -1110,7 +1166,8 @@ void bufdump(buf) ++ } ++ ++ for (i = 0; i < l; i++) { ++- V sprintf(bhex + i * 3, "%02X ", bdump[i]); +++ V snprintf(bhex + i * 3, sizeof(bhex) - i * 3, "%02X ", +++ bdump[i]); ++ bascii[i] = isprint(bdump[i]) ? bdump[i] : ' '; ++ } ++ bascii[i] = 0; ++@@ -1203,7 +1260,7 @@ int bpoolv(buf) ++ if (bs < 0) { ++ bs = -bs; ++ } else { ++- char *lerr = ""; +++ const char *lerr = ""; ++ ++ assert(bs > 0); ++ if (bs <= 0) { +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0002-Change-instruction-access-permissions-of-shared-memo.patch b/meta-arm/recipes-security/trusted-services/files/0002-Change-instruction-access-permissions-of-shared-memo.patch new file mode 100644 index 00000000..c63aa8d8 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0002-Change-instruction-access-permissions-of-shared-memo.patch @@ -0,0 +1,41 @@ +From 5930446f09ab1df10ca70f47a3d1bb21a010effe Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Fri, 5 Feb 2021 12:29:37 +0530 +Subject: [PATCH 02/13] Change instruction access permissions of shared memory + +According to the FFA spec (Section 5.11.3 - Instruction Access Permissions Usage) +the instruction access permission of the memory that has to be shared should be +set as "Not specified and must be ignored" by the Lender in an invocation of +FFA_MEM_SHARE or FFA_MEM_LEND ABIs. + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Davidson K +Change-Id: I6d84c46da8c648f93673afd7cf06a88cd4de139e +Signed-off-by: Ben Horgan +--- + components/rpc/ffarpc/caller/sp/ffarpc_caller.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/components/rpc/ffarpc/caller/sp/ffarpc_caller.c b/components/rpc/ffarpc/caller/sp/ffarpc_caller.c +index 9d98512..269cbd4 100644 +--- a/components/rpc/ffarpc/caller/sp/ffarpc_caller.c ++++ b/components/rpc/ffarpc/caller/sp/ffarpc_caller.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -211,7 +211,7 @@ int ffarpc_caller_open(struct ffarpc_caller *s, uint16_t call_ep_id) + desc.mem_region_attr.normal_memory.shareability = sp_shareability_inner_shareable; + + acc_desc.data_access = sp_data_access_read_write; +- acc_desc.instruction_access = sp_instruction_access_not_executable; ++ acc_desc.instruction_access = sp_instruction_access_not_specified; + acc_desc.receiver_id = call_ep_id; + + region.address = shared_buffer; +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0003-Set-in_region_count-to-0-during-memory-retrieve.patch b/meta-arm/recipes-security/trusted-services/files/0003-Set-in_region_count-to-0-during-memory-retrieve.patch new file mode 100644 index 00000000..bdc5924c --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0003-Set-in_region_count-to-0-during-memory-retrieve.patch @@ -0,0 +1,39 @@ +From 6109a46678f147b6b617edf3805738f2f41b0f19 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Fri, 5 Feb 2021 18:27:05 +0530 +Subject: [PATCH 03/13] Set in_region_count to 0 during memory retrieve + +in_region_count will be used during the lend, donate and share memory +transactions and it is not needed for the retrieve request. + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Davidson K +Change-Id: Id9f805aa7b9e16878a1114f71cd465dc97cc5dfd +Signed-off-by: Ben Horgan +--- + components/rpc/ffarpc/endpoint/ffarpc_call_ep.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c +index bb40cf3..8109345 100644 +--- a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c ++++ b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -43,7 +43,7 @@ static void init_shmem_buf(struct ffa_call_ep *call_ep, uint16_t source_id, + struct sp_memory_descriptor desc = { }; + struct sp_memory_access_descriptor acc_desc = { }; + struct sp_memory_region region = { }; +- uint32_t in_region_count = 1; ++ uint32_t in_region_count = 0; + uint32_t out_region_count = 1; + uint64_t handle = 0; + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0004-Release-rx-buffer-after-memory-retrieve-request.patch b/meta-arm/recipes-security/trusted-services/files/0004-Release-rx-buffer-after-memory-retrieve-request.patch new file mode 100644 index 00000000..9f2a1e02 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0004-Release-rx-buffer-after-memory-retrieve-request.patch @@ -0,0 +1,44 @@ +From de8c7b4ba36606067f68799f63b1a6a7de2c1a70 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Fri, 19 Feb 2021 11:34:26 +0530 +Subject: [PATCH 04/13] Release rx buffer after memory retrieve request + +After the RX buffer is consumed by the SP, the ownership has to be +transferred to the SPM so that SPM can own it as a producer and write +to it whenever needed. + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Davidson K +Change-Id: Ib058e1ef8a4f5286d1618394de2a74c3b7431476 +Signed-off-by: Ben Horgan +--- + components/rpc/ffarpc/endpoint/ffarpc_call_ep.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c +index 8109345..f65398b 100644 +--- a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c ++++ b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c +@@ -40,6 +40,7 @@ static void init_shmem_buf(struct ffa_call_ep *call_ep, uint16_t source_id, + const uint32_t *req_args, uint32_t *resp_args) + { + sp_result sp_res = SP_RESULT_INTERNAL_ERROR; ++ ffa_result ffa_res; + struct sp_memory_descriptor desc = { }; + struct sp_memory_access_descriptor acc_desc = { }; + struct sp_memory_region region = { }; +@@ -68,6 +69,11 @@ static void init_shmem_buf(struct ffa_call_ep *call_ep, uint16_t source_id, + EMSG("memory retrieve error: %d", sp_res); + } + ++ ffa_res = ffa_rx_release(); ++ if (ffa_res != FFA_OK) { ++ EMSG("ffa_rx_release(): error %"PRId32, ffa_res); ++ } ++ + set_mgmt_resp_args(resp_args, req_args[FFA_CALL_ARGS_OPCODE], rpc_status); + } + +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch b/meta-arm/recipes-security/trusted-services/files/0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch new file mode 100644 index 00000000..538cf366 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch @@ -0,0 +1,364 @@ +From dfd02cb62a2dad931bb81ff7eeed0a116ccc50be Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Tue, 9 Mar 2021 17:53:03 +0530 +Subject: [PATCH 05/13] crypto-sp: Create a new deployment with the shim + environment + +The shim environment provides support for the trusted service to +run as secure partition at S-EL0 and a shim layer at S-EL1 with +Hafnium as SPMC running at S-EL2. + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Davidson K +Change-Id: Id3fdf50470e4b9df7388c00e445f75b7bc8362d8 +Signed-off-by: Ben Horgan +--- + deployments/crypto/shim/CMakeLists.txt | 121 +++++++++++++++++++++++++ + deployments/crypto/shim/crypto.dts | 32 +++++++ + deployments/crypto/shim/crypto_sp.c | 117 ++++++++++++++++++++++++ + deployments/crypto/shim/crypto_sp.h | 18 ++++ + deployments/crypto/shim/sp_def.h | 16 ++++ + 5 files changed, 304 insertions(+) + create mode 100644 deployments/crypto/shim/CMakeLists.txt + create mode 100644 deployments/crypto/shim/crypto.dts + create mode 100644 deployments/crypto/shim/crypto_sp.c + create mode 100644 deployments/crypto/shim/crypto_sp.h + create mode 100644 deployments/crypto/shim/sp_def.h + +diff --git a/deployments/crypto/shim/CMakeLists.txt b/deployments/crypto/shim/CMakeLists.txt +new file mode 100644 +index 0000000..65cc215 +--- /dev/null ++++ b/deployments/crypto/shim/CMakeLists.txt +@@ -0,0 +1,121 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++cmake_minimum_required(VERSION 3.16) ++include(../../deployment.cmake REQUIRED) ++ ++#------------------------------------------------------------------------------- ++# The CMakeLists.txt for building the crypto deployment with the shim layer ++# ++# Builds the Crypto service provider for running in an SEL0 secure partition ++# with the shim layer in SEL1 hosted by Hafnium in the role of SPM. ++#------------------------------------------------------------------------------- ++include(${TS_ROOT}/environments/shim/env.cmake) ++project(trusted-services LANGUAGES C ASM) ++add_executable(crypto-sp) ++target_include_directories(crypto-sp PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}") ++set(SP_UUID "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0") ++ ++ ++add_components(TARGET "crypto-sp" ++ BASE_DIR ${TS_ROOT} ++ COMPONENTS ++ "components/messaging/ffa/libsp" ++ "components/rpc/ffarpc/endpoint" ++ "components/rpc/ffarpc/caller/sp" ++ "components/rpc/common/caller" ++ "components/rpc/common/interface" ++ "components/rpc/dummy" ++ "components/service/common" ++ "components/service/common/serializer/protobuf" ++ "components/service/common/provider" ++ "components/service/crypto/provider/mbedcrypto" ++ "components/service/crypto/provider/mbedcrypto/entropy_source/mock" ++ "components/service/crypto/provider/serializer/protobuf" ++ "components/service/secure_storage/client/psa" ++ "protocols/rpc/common/packed-c" ++ "protocols/service/secure_storage/packed-c" ++ "protocols/service/crypto/protobuf" ++ "environments/shim" ++) ++ ++target_sources(crypto-sp PRIVATE ++ crypto_sp.c ++) ++ ++######################################################## Build protobuf files ++include(../../../external/nanopb/nanopb.cmake) ++target_link_libraries(crypto-sp PRIVATE nanopb::protobuf-nanopb-static) ++protobuf_generate_all(TGT "crypto-sp" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/protocols") ++ ++################################################################# mbedcrypto ++include(../../../external/mbed-crypto/mbedcrypto.cmake) ++target_link_libraries(crypto-sp PRIVATE mbedcrypto) ++ ++if(CMAKE_CROSSCOMPILING) ++ target_link_libraries(crypto-sp PRIVATE stdc++ gcc m) ++endif() ++ ++################################################################# ++ ++target_compile_definitions(crypto-sp PRIVATE ++ ARM64=1 ++ LOG_LEVEL=30 ++ CRYPTO=1 ++) ++ ++target_include_directories(crypto-sp PRIVATE ++ ${TS_ROOT}/deployments/crypto/shim ++) ++ ++if(CMAKE_C_COMPILER_ID STREQUAL "GNU") ++ target_compile_options(crypto-sp PRIVATE ++ -fdiagnostics-show-option ++ -fpic ++ -gdwarf-2 ++ -mstrict-align ++ -O0 ++ -std=gnu99 ++ -ffreestanding ++ -mgeneral-regs-only ++ ) ++ ++ # Options for GCC that control linking ++ target_link_options(crypto-sp PRIVATE ++ -fno-lto ++ -nostdlib ++ -pie ++ -zmax-page-size=4096 ++ ) ++ # Options directly for LD, these are not understood by GCC ++ target_link_options(crypto-sp PRIVATE ++ -Wl,--as-needed ++ -Wl,--sort-section=alignment ++ -T${CMAKE_BINARY_DIR}/crypto-sp.ld ++ -Wl,-Map=crypto.map ++ ) ++endif() ++ ++compiler_generate_stripped_elf(TARGET crypto-sp NAME "${SP_UUID}.stripped.elf" RES STRIPPED_ELF) ++compiler_generate_binary_output(TARGET crypto-sp RES STRIPPED_ELF) ++ ++######################################## install ++if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) ++ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "location to install build output to." FORCE) ++endif() ++#TODO: api headers ++install(TARGETS crypto-sp ++ PUBLIC_HEADER DESTINATION ${TS_ENV}/include ++ RUNTIME DESTINATION ${TS_ENV}/bin ++ ) ++install(FILES ${STRIPPED_ELF} DESTINATION ${TS_ENV}/bin) ++ ++get_property(_PROTO_FILES TARGET crypto-sp PROPERTY PROTOBUF_FILES) ++install(FILES ${_PROTO_FILES} DESTINATION ${TS_ENV}/lib/protobuf) ++ ++ ++set(EXPORT_SP_NAME "crypto") ++set(EXPORT_SP_UUID ${SP_UUID}) +diff --git a/deployments/crypto/shim/crypto.dts b/deployments/crypto/shim/crypto.dts +new file mode 100644 +index 0000000..23bd7a2 +--- /dev/null ++++ b/deployments/crypto/shim/crypto.dts +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * This file is a Partition Manifest (PM) for Crypto Trusted Service ++ * Secure Partition (SP). ++ */ ++ ++/dts-v1/; ++ ++/ { ++ compatible = "arm,ffa-manifest-1.0"; ++ ++ /* Properties */ ++ description = "crypto"; ++ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ ++ uuid = <0xd9df52d5 0x4bb216a2 0x6dd2a49a 0xc0e8843b>; ++ id = <3>; ++ execution-ctx-count = <1>; ++ exception-level = <2>; /* S-EL1 */ ++ execution-state = <0>; /* AARCH64 */ ++ load-address = <0xfec00000>; ++ entrypoint-offset = <0x00001000>; ++ xlat-granule = <0>; /* 4KiB */ ++ boot-order = <0>; ++ messaging-method = <0>; /* Direct messaging only */ ++ run-time-model = <1>; /* Run to completion */ ++ ++ /* Boot protocol */ ++ gp-register-num = <0x0>; ++}; +diff --git a/deployments/crypto/shim/crypto_sp.c b/deployments/crypto/shim/crypto_sp.c +new file mode 100644 +index 0000000..8b3eba5 +--- /dev/null ++++ b/deployments/crypto/shim/crypto_sp.c +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define SP_STORAGE_UUID_BYTES \ ++ { 0x48, 0xef, 0x1e, 0xdc, 0x7a, 0xb1, 0xcf, 0x4c, \ ++ 0xac, 0x8b, 0xdf, 0xcf, 0xf7, 0x71, 0x1b, 0x14, } ++ ++uint16_t own_id = 0; /* !!Needs refactoring as parameter to ffarpc_caller_init */ ++static const uint8_t storage_uuid[] = SP_STORAGE_UUID_BYTES; ++ ++ ++static int sp_init(uint16_t *own_sp_id); ++ ++uint8_t sp_heap[SP_HEAP_SIZE] __aligned(16); ++ ++void __noreturn sp_main(struct ffa_init_info *init_info) ++{ ++ struct mbed_crypto_provider crypto_provider; ++ struct ffa_call_ep ffarpc_call_ep; ++ struct call_ep *crypto_ep; ++ struct ffarpc_caller ffarpc_caller; ++ struct dummy_caller dummy_caller; ++ struct rpc_caller *storage_caller; ++ struct ffa_direct_msg req_msg; ++ uint16_t storage_sp_ids[1]; ++ ++ /* Beginning of the boot phase */ ++ (void) init_info; ++ ++ if (sp_init(&own_id) != 0) goto fatal_error; ++ ++ /* Establish RPC session with secure storage SP */ ++ storage_caller = ffarpc_caller_init(&ffarpc_caller); ++ ++ if (!ffarpc_caller_discover(storage_uuid, storage_sp_ids, sizeof(storage_sp_ids)/sizeof(storage_sp_ids[0])) || ++ ffarpc_caller_open(&ffarpc_caller, storage_sp_ids[0])) { ++ /* ++ * Failed to establish session. To allow the crypto service ++ * to still be initialized, albeit with no persistent storage, ++ * initialise a dummy_caller that will safely ++ * handle rpc requests but will report an error. ++ */ ++ storage_caller = dummy_caller_init(&dummy_caller, ++ TS_RPC_CALL_ACCEPTED, PSA_ERROR_STORAGE_FAILURE); ++ } ++ ++ /* Initialize the crypto service */ ++ crypto_ep = mbed_crypto_provider_init(&crypto_provider, storage_caller); ++ ffa_call_ep_init(&ffarpc_call_ep, crypto_ep); ++ ++ malloc_add_pool(sp_heap, SP_HEAP_SIZE); ++ ++ /* End of boot phase */ ++ ffa_msg_wait(&req_msg); ++ ++ while (1) { ++ if (req_msg.function_id == FFA_MSG_SEND_DIRECT_REQ_32) { ++ ++ struct ffa_direct_msg resp_msg; ++ ++ ffa_call_ep_receive(&ffarpc_call_ep, &req_msg, &resp_msg); ++ ++ ffa_msg_send_direct_resp(req_msg.destination_id, ++ req_msg.source_id, resp_msg.args[0], resp_msg.args[1], ++ resp_msg.args[2], resp_msg.args[3], resp_msg.args[4], ++ &req_msg); ++ } else { ++ EMSG("Received unexpected request"); ++ break; ++ } ++ } ++ ++fatal_error: ++ /* SP is not viable */ ++ EMSG("Crypto SP error"); ++ while (1) {} ++} ++ ++void sp_interrupt_handler(uint32_t interrupt_id) ++{ ++ (void)interrupt_id; ++} ++ ++static int sp_init(uint16_t *own_sp_id) ++{ ++ int status = -1; ++ sp_result sp_res; ++ static uint8_t tx_buffer[4096] __aligned(4096); ++ static uint8_t rx_buffer[4096] __aligned(4096); ++ ++ sp_res = sp_rxtx_buffer_map(tx_buffer, rx_buffer, sizeof(rx_buffer)); ++ if (sp_res == SP_RESULT_OK) { ++ ffa_result ffa_res; ++ ffa_res = ffa_id_get(own_sp_id); ++ if (ffa_res == FFA_OK) { ++ status = 0; ++ } ++ } ++ ++ return status; ++} +diff --git a/deployments/crypto/shim/crypto_sp.h b/deployments/crypto/shim/crypto_sp.h +new file mode 100644 +index 0000000..e3ee0c6 +--- /dev/null ++++ b/deployments/crypto/shim/crypto_sp.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef CRYPTO_SP_H ++#define CRYPTO_SP_H ++ ++#define CRYPTO_SP_UUID \ ++ {0xd9df52d5, 0x16a2, 0x4bb2, \ ++ {0x9a, 0xa4, 0xd2, 0x6d, 0x3b, 0x84, 0xe8, 0xc0}} ++ ++#define CRYPTO_SP_UUID_BYTES \ ++ {0xd9, 0xdf, 0x52, 0xd5, 0x16, 0xa2, 0x4b, 0xb2, \ ++ 0x9a, 0xa4, 0xd2, 0x6d, 0x3b, 0x84, 0xe8, 0xc0} ++ ++#endif /* CRYPTO_SP_H */ +diff --git a/deployments/crypto/shim/sp_def.h b/deployments/crypto/shim/sp_def.h +new file mode 100644 +index 0000000..c4eff67 +--- /dev/null ++++ b/deployments/crypto/shim/sp_def.h +@@ -0,0 +1,16 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SP_DEF_H ++#define SP_DEF_H ++ ++/* Memory reserved for stacks */ ++#define SP_STACKS_SIZE (32 * 1024) ++ ++/* Memory for heap */ ++#define SP_HEAP_SIZE (480 * 1024) ++ ++#endif /* SP_DEF_H */ +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0006-secure-storage-Create-a-new-deployment-with-the-shim.patch b/meta-arm/recipes-security/trusted-services/files/0006-secure-storage-Create-a-new-deployment-with-the-shim.patch new file mode 100644 index 00000000..46cba057 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0006-secure-storage-Create-a-new-deployment-with-the-shim.patch @@ -0,0 +1,268 @@ +From 47bd3e42cc7e33cd2f41c98112ed159b23149023 Mon Sep 17 00:00:00 2001 +From: Davidson K +Date: Tue, 9 Mar 2021 18:01:05 +0530 +Subject: [PATCH 06/13] secure-storage: Create a new deployment with the shim + environment + +The shim environment provides support for the trusted service to +run as secure partition at S-EL0 and a shim layer at S-EL1 with +Hafnium as SPMC running at S-EL2. + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Davidson K +Change-Id: I6fd23a100b5b1ab8d80742ee2f3a81bfb7595a51 +Signed-off-by: Ben Horgan +--- + .../secure-storage/shim/CMakeLists.txt | 93 +++++++++++++++++++ + .../secure-storage/shim/secure-storage.dts | 33 +++++++ + deployments/secure-storage/shim/sp.c | 74 +++++++++++++++ + deployments/secure-storage/shim/sp_def.h | 16 ++++ + 4 files changed, 216 insertions(+) + create mode 100644 deployments/secure-storage/shim/CMakeLists.txt + create mode 100644 deployments/secure-storage/shim/secure-storage.dts + create mode 100644 deployments/secure-storage/shim/sp.c + create mode 100644 deployments/secure-storage/shim/sp_def.h + +diff --git a/deployments/secure-storage/shim/CMakeLists.txt b/deployments/secure-storage/shim/CMakeLists.txt +new file mode 100644 +index 0000000..bcc3486 +--- /dev/null ++++ b/deployments/secure-storage/shim/CMakeLists.txt +@@ -0,0 +1,93 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++cmake_minimum_required(VERSION 3.16) ++include(../../deployment.cmake REQUIRED) ++ ++#------------------------------------------------------------------------------- ++# The CMakeLists.txt for building the secure-storage deployment for hafnium ++# ++# Builds the secure storage service provider for running in an SEL0 secure ++# partition with the shim layer in SEL1 hosted by Hafnium in the role of SPM. ++#------------------------------------------------------------------------------- ++include(${TS_ROOT}/environments/shim/env.cmake) ++project(trusted-services LANGUAGES C ASM) ++add_executable(secure-storage) ++target_include_directories(secure-storage PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}") ++set(SP_UUID "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14") ++ ++add_components(TARGET "secure-storage" ++ BASE_DIR ${TS_ROOT} ++ COMPONENTS ++ components/messaging/ffa/libsp ++ components/rpc/ffarpc/endpoint ++ components/rpc/common/interface ++ components/service/common/provider ++ components/service/secure_storage/provider/secure_flash_store ++ components/service/secure_storage/provider/secure_flash_store/flash_fs ++ components/service/secure_storage/provider/secure_flash_store/flash ++ protocols/rpc/common/packed-c ++ protocols/service/secure_storage/packed-c ++ environments/shim ++) ++ ++target_sources(secure-storage PRIVATE ++ sp.c ++) ++ ++target_compile_definitions(secure-storage PRIVATE ++ ARM64=1 ++ LOG_LEVEL=30 ++ SECURE_STORAGE=1 ++) ++ ++target_include_directories(secure-storage PRIVATE ++ ${TS_ROOT}/deployments/secure-storage/shim ++) ++ ++if(CMAKE_C_COMPILER_ID STREQUAL "GNU") ++ target_compile_options(secure-storage PRIVATE ++ -fdiagnostics-show-option ++ -fpic ++ -gdwarf-2 ++ -mstrict-align ++ -O0 ++ -std=gnu99 ++ -ffreestanding ++ -mgeneral-regs-only ++ ) ++ ++ # Options for GCC that control linking ++ target_link_options(secure-storage PRIVATE ++ -fno-lto ++ -nostdlib ++ -pie ++ -zmax-page-size=4096 ++ ) ++ # Options directly for LD, these are not understood by GCC ++ target_link_options(secure-storage PRIVATE ++ -Wl,--as-needed ++ -Wl,--sort-section=alignment ++ -T${CMAKE_BINARY_DIR}/secure-storage.ld ++ -Wl,-Map=secure-storage.map ++ ) ++endif() ++ ++compiler_generate_stripped_elf(TARGET secure-storage NAME "${SP_UUID}.stripped.elf" RES STRIPPED_ELF) ++compiler_generate_binary_output(TARGET secure-storage RES STRIPPED_ELF) ++ ++######################################## install ++if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) ++ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "location to install build output to." FORCE) ++endif() ++install(TARGETS secure-storage ++ PUBLIC_HEADER DESTINATION ${TS_ENV}/include ++ RUNTIME DESTINATION ${TS_ENV}/bin ++ ) ++install(FILES ${STRIPPED_ELF} DESTINATION ${TS_ENV}/bin) ++ ++set(EXPORT_SP_NAME "secure-storage") ++set(EXPORT_SP_UUID ${SP_UUID}) +diff --git a/deployments/secure-storage/shim/secure-storage.dts b/deployments/secure-storage/shim/secure-storage.dts +new file mode 100644 +index 0000000..5df3153 +--- /dev/null ++++ b/deployments/secure-storage/shim/secure-storage.dts +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * This file is a Partition Manifest (PM) for the secure-storage ++ * Secure Partition (SP) ++ */ ++ ++ ++/dts-v1/; ++ ++/ { ++ compatible = "arm,ffa-manifest-1.0"; ++ ++ /* Properties */ ++ description = "secure-storage"; ++ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ ++ uuid = <0xdc1eef48 0x4ccfb17a 0xcfdf8bac 0x141b71f7>; ++ id = <2>; ++ execution-ctx-count = <1>; ++ exception-level = <2>; /* S-EL1 */ ++ execution-state = <0>; /* AARCH64 */ ++ load-address = <0xfee00000>; ++ entrypoint-offset = <0x00001000>; ++ xlat-granule = <0>; /* 4KiB */ ++ boot-order = <0>; ++ messaging-method = <0>; /* Direct messaging only */ ++ run-time-model = <1>; /* Run to completion */ ++ ++ /* Boot protocol */ ++ gp-register-num = <0x0>; ++}; +diff --git a/deployments/secure-storage/shim/sp.c b/deployments/secure-storage/shim/sp.c +new file mode 100644 +index 0000000..2baec88 +--- /dev/null ++++ b/deployments/secure-storage/shim/sp.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++uint16_t own_id = 0; ++static uint8_t tx_buffer[4096] __aligned(4096); ++static uint8_t rx_buffer[4096] __aligned(4096); ++ ++uint8_t sp_heap[SP_HEAP_SIZE] __aligned(16); ++ ++void sp_main(struct ffa_init_info *init_info) ++{ ++ ffa_result ffa_res; ++ sp_result sp_res; ++ struct call_ep *sfs_ep; ++ struct ffa_call_ep ffa_call_ep; ++ struct ffa_direct_msg req_msg; ++ struct sfs_provider sfs_provider; ++ ++ /* Beginning of boot phase */ ++ (void) init_info; ++ ++ malloc_add_pool(sp_heap, SP_HEAP_SIZE); ++ ++ ffa_res = ffa_id_get(&own_id); ++ if (ffa_res != FFA_OK) { ++ EMSG("id get error: %d", ffa_res); ++ } ++ ++ sp_res = sp_rxtx_buffer_map(tx_buffer, rx_buffer, sizeof(rx_buffer)); ++ if (sp_res != SP_RESULT_OK) { ++ EMSG("rxtx map error: %d", sp_res); ++ } ++ ++ sfs_ep = sfs_provider_init(&sfs_provider); ++ ffa_call_ep_init(&ffa_call_ep, sfs_ep); ++ ++ /* End of boot phase */ ++ ffa_msg_wait(&req_msg); ++ ++ while (1) { ++ if (req_msg.function_id == FFA_MSG_SEND_DIRECT_REQ_32) { ++ struct ffa_direct_msg resp_msg; ++ ffa_call_ep_receive(&ffa_call_ep, &req_msg, &resp_msg); ++ ++ ffa_msg_send_direct_resp(req_msg.destination_id, ++ req_msg.source_id, resp_msg.args[0], resp_msg.args[1], ++ resp_msg.args[2], resp_msg.args[3], resp_msg.args[4], ++ &req_msg); ++ } else { ++ EMSG("Received unexpected request"); ++ break; ++ } ++ } ++} ++ ++void sp_interrupt_handler(uint32_t interrupt_id) ++{ ++ (void)interrupt_id; ++} +diff --git a/deployments/secure-storage/shim/sp_def.h b/deployments/secure-storage/shim/sp_def.h +new file mode 100644 +index 0000000..aaf045d +--- /dev/null ++++ b/deployments/secure-storage/shim/sp_def.h +@@ -0,0 +1,16 @@ ++/* ++ * Copyright (c) 2021, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef SP_DEF_H ++#define SP_DEF_H ++ ++/* Memory reserved for stacks */ ++#define SP_STACKS_SIZE ULL(0xa000) ++ ++/* Memory for heap */ ++#define SP_HEAP_SIZE (300 * 1024) ++ ++#endif /* SP_DEF_H */ +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch b/meta-arm/recipes-security/trusted-services/files/0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch new file mode 100644 index 00000000..356ed419 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch @@ -0,0 +1,30 @@ +From ab7c90b324371e8c0b49fb45b833d521eca3c06d Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Thu, 8 Apr 2021 09:49:13 +0000 +Subject: [PATCH 07/13] crypto: shim: Don't link against unrequired libraries + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: Ia1b5476d8a8d1ede0023092ddd86f079db4beb7d +Signed-off-by: Ben Horgan +--- + deployments/crypto/shim/CMakeLists.txt | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/deployments/crypto/shim/CMakeLists.txt b/deployments/crypto/shim/CMakeLists.txt +index 65cc215..b401d25 100644 +--- a/deployments/crypto/shim/CMakeLists.txt ++++ b/deployments/crypto/shim/CMakeLists.txt +@@ -55,10 +55,6 @@ protobuf_generate_all(TGT "crypto-sp" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/ + include(../../../external/mbed-crypto/mbedcrypto.cmake) + target_link_libraries(crypto-sp PRIVATE mbedcrypto) + +-if(CMAKE_CROSSCOMPILING) +- target_link_libraries(crypto-sp PRIVATE stdc++ gcc m) +-endif() +- + ################################################################# + + target_compile_definitions(crypto-sp PRIVATE +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0008-libts-arm-linux-Add-version-to-libts.so.patch b/meta-arm/recipes-security/trusted-services/files/0008-libts-arm-linux-Add-version-to-libts.so.patch new file mode 100644 index 00000000..d88810dc --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0008-libts-arm-linux-Add-version-to-libts.so.patch @@ -0,0 +1,34 @@ +From 611050d667ee7e4da0bed578b1a033315bc45ff4 Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Thu, 8 Apr 2021 09:51:25 +0000 +Subject: [PATCH 08/13] libts: arm-linux: Add version to libts.so + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: I6164b05ef49553a39252717d5622dc958ad65be4 +Signed-off-by: Ben Horgan +--- + deployments/libts/arm-linux/CMakeLists.txt | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/deployments/libts/arm-linux/CMakeLists.txt b/deployments/libts/arm-linux/CMakeLists.txt +index ab512d6..a87ed48 100644 +--- a/deployments/libts/arm-linux/CMakeLists.txt ++++ b/deployments/libts/arm-linux/CMakeLists.txt +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -45,4 +45,5 @@ include(../libts.cmake REQUIRED) + # + #------------------------------------------------------------------------------- + env_set_link_options(TGT ts) +-target_link_libraries(ts PRIVATE gcc) +\ No newline at end of file ++set_target_properties(ts PROPERTIES VERSION 1.0.0 SOVERSION 1) ++target_link_libraries(ts PRIVATE gcc) +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0009-libts-Add-option-to-use-installed-libts.patch b/meta-arm/recipes-security/trusted-services/files/0009-libts-Add-option-to-use-installed-libts.patch new file mode 100644 index 00000000..8f1077fa --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0009-libts-Add-option-to-use-installed-libts.patch @@ -0,0 +1,81 @@ +From 6eb38e38bc50655b659494b3ca4e53dc727f6c53 Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Thu, 8 Apr 2021 10:00:37 +0000 +Subject: [PATCH 09/13] libts: Add option to use installed libts + +Allows using libts as dependency of trusted service tests in yocto +Set LIBTS_USE_INSTALLED to use installed libts. The default is +unchanged. + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: Ied743afc80a490238361feea64a37faadacd8dda +Signed-off-by: Ben Horgan +--- + deployments/ts-demo/ts-demo.cmake | 14 ++++++++++++-- + deployments/ts-service-test/ts-service-test.cmake | 15 +++++++++++++-- + 2 files changed, 25 insertions(+), 4 deletions(-) + +diff --git a/deployments/ts-demo/ts-demo.cmake b/deployments/ts-demo/ts-demo.cmake +index 4c85a40..f968612 100644 +--- a/deployments/ts-demo/ts-demo.cmake ++++ b/deployments/ts-demo/ts-demo.cmake +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -16,7 +16,17 @@ + # libts will be imported for the enviroment in which service tests are + # deployed. + #------------------------------------------------------------------------------- +-include(${TS_ROOT}/deployments/libts/libts-import.cmake) ++ ++if (NOT LIBTS_USE_INSTALLED) ++ include(${TS_ROOT}/deployments/libts/libts-import.cmake) ++else() ++ find_library(libts_lib ts REQUIRED) ++ find_path(libts_inc rpc_status.h REQUIRED) ++ add_library(libts SHARED IMPORTED) ++ set_property(TARGET libts PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${libts_inc}") ++ set_property(TARGET libts PROPERTY IMPORTED_LOCATION "${libts_lib}") ++endif() ++ + target_link_libraries(ts-demo PRIVATE libts) + + #------------------------------------------------------------------------------- +diff --git a/deployments/ts-service-test/ts-service-test.cmake b/deployments/ts-service-test/ts-service-test.cmake +index 1593188..5f78b36 100644 +--- a/deployments/ts-service-test/ts-service-test.cmake ++++ b/deployments/ts-service-test/ts-service-test.cmake +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -16,7 +16,18 @@ + # libts will be imported for the enviroment in which service tests are + # deployed. + #------------------------------------------------------------------------------- +-include(${TS_ROOT}/deployments/libts/libts-import.cmake) ++ ++if (NOT LIBTS_USE_INSTALLED) ++ include(${TS_ROOT}/deployments/libts/libts-import.cmake) ++else() ++ find_library(libts_lib ts REQUIRED) ++ message("benhor01: ${libts_lib}") ++ find_path(libts_inc rpc_status.h REQUIRED) ++ add_library(libts SHARED IMPORTED) ++ set_property(TARGET libts PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${libts_inc}") ++ set_property(TARGET libts PROPERTY IMPORTED_LOCATION "${libts_lib}") ++endif() ++ + target_link_libraries(ts-service-test PRIVATE libts) + + #------------------------------------------------------------------------------- +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0010-external-Add-option-to-use-local-source-or-installed.patch b/meta-arm/recipes-security/trusted-services/files/0010-external-Add-option-to-use-local-source-or-installed.patch new file mode 100644 index 00000000..83aaf3de --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0010-external-Add-option-to-use-local-source-or-installed.patch @@ -0,0 +1,599 @@ +From 10b56be594b945c70af428116ae734660d8e11bb Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Thu, 8 Apr 2021 10:07:13 +0000 +Subject: [PATCH 10/13] external: Add option to use local source or installed + libs + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: I6bd466af8518a928f402f0d6474e607092c7340a +Signed-off-by: Ben Horgan +--- + external/CppUTest/CppUTest.cmake | 138 +++++++++--------- + external/mbed-crypto/mbedcrypto.cmake | 131 ++++++++++------- + external/nanopb/nanopb.cmake | 200 +++++++++++++++----------- + 3 files changed, 264 insertions(+), 205 deletions(-) + +diff --git a/external/CppUTest/CppUTest.cmake b/external/CppUTest/CppUTest.cmake +index c18f3e3..9b65ae5 100644 +--- a/external/CppUTest/CppUTest.cmake ++++ b/external/CppUTest/CppUTest.cmake +@@ -1,44 +1,47 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + #------------------------------------------------------------------------------- + +-set(CPPUTEST_URL "https://github.com/cpputest/cpputest.git" CACHE STRING "CppUTest repository URL") +-set(CPPUTEST_REFSPEC "v3.8" CACHE STRING "CppUTest git refspec") +-set(CPPUTEST_INSTALL_PATH ${CMAKE_CURRENT_BINARY_DIR}/CppUTest_install CACHE PATH "CppUTest installation directory") + +-include(FetchContent) ++if (NOT CPPUTEST_USE_INSTALLED) + +-# Checking git +-find_program(GIT_COMMAND "git") +-if (NOT GIT_COMMAND) +- message(FATAL_ERROR "Please install git") +-endif() ++ set(CPPUTEST_URL "https://github.com/cpputest/cpputest.git" CACHE STRING "CppUTest repository URL") ++ set(CPPUTEST_REFSPEC "v3.8" CACHE STRING "CppUTest git refspec") ++ set(CPPUTEST_INSTALL_PATH ${CMAKE_CURRENT_BINARY_DIR}/CppUTest_install CACHE PATH "CppUTest installation directory") ++ ++ include(FetchContent) ++ ++ # Checking git ++ find_program(GIT_COMMAND "git") ++ if (NOT GIT_COMMAND) ++ message(FATAL_ERROR "Please install git") ++ endif() + +-# Fetching CppUTest +-FetchContent_Declare( +- cpputest +- GIT_REPOSITORY ${CPPUTEST_URL} +- GIT_TAG ${CPPUTEST_REFSPEC} +- GIT_SHALLOW TRUE +- PATCH_COMMAND git stash ++ # Fetching CppUTest ++ FetchContent_Declare( ++ cpputest ++ GIT_REPOSITORY ${CPPUTEST_URL} ++ GIT_TAG ${CPPUTEST_REFSPEC} ++ GIT_SHALLOW TRUE ++ PATCH_COMMAND git stash + COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/cpputest-cmake-fix.patch +-) ++ ) + +-# FetchContent_GetProperties exports cpputest_SOURCE_DIR and cpputest_BINARY_DIR variables +-FetchContent_GetProperties(cpputest) +-if(NOT cpputest_POPULATED) +- message(STATUS "Fetching CppUTest") +- FetchContent_Populate(cpputest) +-endif() ++ # FetchContent_GetProperties exports cpputest_SOURCE_DIR and cpputest_BINARY_DIR variables ++ FetchContent_GetProperties(cpputest) ++ if(NOT cpputest_POPULATED) ++ message(STATUS "Fetching CppUTest") ++ FetchContent_Populate(cpputest) ++ endif() + +-# Build and install CppUTest configuration time. This makes us able to use CppUTest as a CMake package. +-# Memory leak detection is turned off to avoid conflict with memcheck. +-if(NOT CMAKE_CROSSCOMPILING) +- execute_process(COMMAND +- ${CMAKE_COMMAND} ++ # Build and install CppUTest configuration time. This makes us able to use CppUTest as a CMake package. ++ # Memory leak detection is turned off to avoid conflict with memcheck. ++ if(NOT CMAKE_CROSSCOMPILING) ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} + -DMEMORY_LEAK_DETECTION=OFF + -DLONGLONG=ON + -DC++11=ON +@@ -48,47 +51,54 @@ if(NOT CMAKE_CROSSCOMPILING) + ${cpputest_SOURCE_DIR} + WORKING_DIRECTORY + ${cpputest_BINARY_DIR} +- RESULT_VARIABLE +- _exec_error +- ) +-else() ++ RESULT_VARIABLE ++ _exec_error ++ ) ++ else() ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} ++ -DMEMORY_LEAK_DETECTION=OFF ++ -DLONGLONG=ON ++ -DC++11=ON ++ -DCMAKE_INSTALL_PREFIX=${CPPUTEST_INSTALL_PATH} ++ -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} ++ -DTESTS=OFF ++ -DEXTENSIONS=OFF ++ -DHAVE_FORK=OFF ++ -DCPP_PLATFORM=armcc ++ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY ++ -G${CMAKE_GENERATOR} ++ ${cpputest_SOURCE_DIR} ++ WORKING_DIRECTORY ++ ${cpputest_BINARY_DIR} ++ RESULT_VARIABLE ++ _exec_error ++ ) ++ endif() ++ if (NOT _exec_error EQUAL 0) ++ message(FATAL_ERROR "Configuriong CppUTest build failed.") ++ endif() + execute_process(COMMAND +- ${CMAKE_COMMAND} +- -DMEMORY_LEAK_DETECTION=OFF +- -DLONGLONG=ON +- -DC++11=ON +- -DCMAKE_INSTALL_PREFIX=${CPPUTEST_INSTALL_PATH} +- -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} +- -DTESTS=OFF +- -DEXTENSIONS=OFF +- -DHAVE_FORK=OFF +- -DCPP_PLATFORM=armcc +- -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY +- -G${CMAKE_GENERATOR} +- ${cpputest_SOURCE_DIR} +- WORKING_DIRECTORY +- ${cpputest_BINARY_DIR} +- RESULT_VARIABLE +- _exec_error +- ) +-endif() +-if (NOT _exec_error EQUAL 0) +- message(FATAL_ERROR "Configuriong CppUTest build failed.") +-endif() +-execute_process(COMMAND +- ${CMAKE_COMMAND} ++ ${CMAKE_COMMAND} + --build ${cpputest_BINARY_DIR} + -- install -j8 +- RESULT_VARIABLE ++ RESULT_VARIABLE + _exec_error +- ) +-if (NOT _exec_error EQUAL 0) +- message(FATAL_ERROR "Building CppUTest failed.") ++ ) ++ if (NOT _exec_error EQUAL 0) ++ message(FATAL_ERROR "Building CppUTest failed.") ++ endif() ++ ++ # Finding CppUTest package. CMake will check [package name]_DIR variable. ++ set(CppUTest_DIR ${CPPUTEST_INSTALL_PATH}/lib/CppUTest/cmake CACHE PATH "CppUTest package location" FORCE) ++ find_package(CppUTest CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${CppUTest_DIR}) ++ ++else() ++ ++ find_package(CppUTest REQUIRED) ++ + endif() + +-# Finding CppUTest package. CMake will check [package name]_DIR variable. +-set(CppUTest_DIR ${CPPUTEST_INSTALL_PATH}/lib/CppUTest/cmake CACHE PATH "CppUTest package location" FORCE) +-find_package(CppUTest CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${CppUTest_DIR}) + # CppUTest package files do not set include path properties on the targets. + # Fix this here. + foreach(_cpputest_target IN LISTS CppUTest_LIBRARIES) +diff --git a/external/mbed-crypto/mbedcrypto.cmake b/external/mbed-crypto/mbedcrypto.cmake +index bf00588..f681e74 100644 +--- a/external/mbed-crypto/mbedcrypto.cmake ++++ b/external/mbed-crypto/mbedcrypto.cmake +@@ -1,46 +1,59 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + #------------------------------------------------------------------------------- + +-set(MBEDCRYPTO_URL "https://github.com/ARMmbed/mbed-crypto.git" CACHE STRING "mbedcrypto repository URL") +-set(MBEDCRYPTO_REFSPEC "mbedcrypto-3.1.0" CACHE STRING "mbedcrypto git refspec") +-set(MBEDCRYPTO_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/mbedcrypto_install" CACHE PATH "mbedcrypto installation directory") +-set(MBEDCRYPTO_PACKAGE_PATH "${MBEDCRYPTO_INSTALL_PATH}/lib/mbedcrypto/cmake" CACHE PATH "mbedcrypto CMake package directory") ++if(NOT MBEDCRYPTO_USE_INSTALLED) + +-include(FetchContent) ++ include(FetchContent) + +-# Checking git +-find_program(GIT_COMMAND "git") +-if (NOT GIT_COMMAND) +- message(FATAL_ERROR "Please install git") +-endif() ++ if (NOT MBEDCRYPTO_SOURCE_PATH) + +-# Fetching mbedcrypto +-FetchContent_Declare( +- mbedcrypto +- GIT_REPOSITORY ${MBEDCRYPTO_URL} +- GIT_TAG ${MBEDCRYPTO_REFSPEC} +- GIT_SHALLOW TRUE +-) +- +-# FetchContent_GetProperties exports mbedcrypto_SOURCE_DIR and mbedcrypto_BINARY_DIR variables +-FetchContent_GetProperties(mbedcrypto) +-if(NOT mbedcrypto_POPULATED) +- message(STATUS "Fetching mbedcrypto") +- FetchContent_Populate(mbedcrypto) +-endif() ++ set(MBEDCRYPTO_URL "https://github.com/ARMmbed/mbed-crypto.git" CACHE STRING "mbedcrypto repository URL") ++ set(MBEDCRYPTO_REFSPEC "mbedcrypto-3.1.0" CACHE STRING "mbedcrypto git refspec") + +-# Convert the include path list to a string. Needed to make parameter passing to +-# mbedcrypto build work fine. +-string(REPLACE ";" "\\;" MBEDCRYPTO_EXTRA_INCLUDES "${MBEDCRYPTO_EXTRA_INCLUDES}") ++ # Checking git ++ find_program(GIT_COMMAND "git") ++ if (NOT GIT_COMMAND) ++ message(FATAL_ERROR "Please install git") ++ endif() + +-#Configure the library +-if(NOT CMAKE_CROSSCOMPILING) +- execute_process(COMMAND +- ${CMAKE_COMMAND} ++ # Fetching mbedcrypto ++ FetchContent_Declare( ++ mbedcrypto ++ GIT_REPOSITORY ${MBEDCRYPTO_URL} ++ GIT_TAG ${MBEDCRYPTO_REFSPEC} ++ GIT_SHALLOW TRUE ++ ) ++ ++ else() ++ ++ FetchContent_Declare( ++ mbedcrypto ++ SOURCE_DIR ${MBEDCRYPTO_SOURCE_PATH} ++ ) ++ ++ endif() ++ ++ # FetchContent_GetProperties exports mbedcrypto_SOURCE_DIR and mbedcrypto_BINARY_DIR variables ++ FetchContent_GetProperties(mbedcrypto) ++ ++ if(NOT mbedcrypto_POPULATED) ++ message(STATUS "Fetching mbedcrypto") ++ FetchContent_Populate(mbedcrypto) ++ endif() ++ ++ set(MBEDCRYPTO_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/mbedcrypto_install" CACHE PATH "mbedcrypto installation directory") ++ set(MBEDCRYPTO_PACKAGE_PATH "${MBEDCRYPTO_INSTALL_PATH}/lib/mbedcrypto/cmake" CACHE PATH "mbedcrypto CMake package directory") ++ # Convert the include path list to a string. Needed to make parameter passing to ++ # mbedcrypto build work fine. ++ string(REPLACE ";" "\\;" MBEDCRYPTO_EXTRA_INCLUDES "${MBEDCRYPTO_EXTRA_INCLUDES}") ++ #Configure the library ++ if(NOT CMAKE_CROSSCOMPILING) ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} + -DENABLE_PROGRAMS=OFF + -DENABLE_TESTING=OFF + -DCMAKE_INSTALL_PREFIX=${MBEDCRYPTO_INSTALL_PATH} +@@ -49,12 +62,12 @@ if(NOT CMAKE_CROSSCOMPILING) + -Dthirdparty_inc=${MBEDCRYPTO_EXTRA_INCLUDES} + -GUnix\ Makefiles + ${mbedcrypto_SOURCE_DIR} +- WORKING_DIRECTORY ++ WORKING_DIRECTORY + ${mbedcrypto_BINARY_DIR} +- ) +-else() +- execute_process(COMMAND +- ${CMAKE_COMMAND} ++ ) ++ else() ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} + -DENABLE_PROGRAMS=OFF + -DENABLE_TESTING=OFF + -DCMAKE_INSTALL_PREFIX=${MBEDCRYPTO_INSTALL_PATH} +@@ -64,30 +77,38 @@ else() + -Dthirdparty_inc=${MBEDCRYPTO_EXTRA_INCLUDES} + -GUnix\ Makefiles + ${mbedcrypto_SOURCE_DIR} +- WORKING_DIRECTORY ++ WORKING_DIRECTORY + ${mbedcrypto_BINARY_DIR} +- RESULT_VARIABLE _exec_error +- ) ++ RESULT_VARIABLE _exec_error ++ ) + +- if (_exec_error) +- message(FATAL_ERROR "Configuration step of mbedcrypto failed with ${_exec_error}.") ++ if (_exec_error) ++ message(FATAL_ERROR "Configuration step of mbedcrypto failed with ${_exec_error}.") ++ endif() + endif() +-endif() + +-#TODO: add dependnecy to generated project on this file! +-#TODO: add custom target to rebuild mbedcrypto ++ #TODO: add dependnecy to generated project on this file! ++ #TODO: add custom target to rebuild mbedcrypto + +-#Build the library +-execute_process(COMMAND ++ #Build the library ++ execute_process(COMMAND + ${CMAKE_COMMAND} --build ${mbedcrypto_BINARY_DIR} -- install -j8 + RESULT_VARIABLE _exec_error +- ) +-if (_exec_error) +- message(FATAL_ERROR "Build step of mbedcrypto failed with ${_exec_error}.") +-endif() ++ ) ++ if (_exec_error) ++ message(FATAL_ERROR "Build step of mbedcrypto failed with ${_exec_error}.") ++ endif() ++ ++ add_library(mbedcrypto STATIC IMPORTED) ++ set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION "${MBEDCRYPTO_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}") ++ set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MBEDCRYPTO_INSTALL_PATH}/include") + +-#Create an imported target to have clean abstraction in the build-system. +-add_library(mbedcrypto STATIC IMPORTED) +-set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION "${MBEDCRYPTO_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}") +-set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MBEDCRYPTO_INSTALL_PATH}/include") ++else() ++ ++ find_library(mbedcrypto_lib mbedcrypto REQUIRED) ++ find_path(mbedcrypto_inc mbedtls/version.h REQUIRED) ++ add_library(mbedcrypto STATIC IMPORTED) ++ set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION "${mbedcrypto_lib}") ++ set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${mbedcrypto_inc}") + ++endif() +diff --git a/external/nanopb/nanopb.cmake b/external/nanopb/nanopb.cmake +index eda00e4..f6ac047 100644 +--- a/external/nanopb/nanopb.cmake ++++ b/external/nanopb/nanopb.cmake +@@ -1,12 +1,12 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + #------------------------------------------------------------------------------- + + #[===[.rst: +-NonoPB integration for cmake ++NanoPB integration for cmake + ---------------------------- + + This module will: +@@ -26,107 +26,135 @@ running this module. + + #### Get the dependency + +-set(NANOPB_URL "https://github.com/nanopb/nanopb.git" CACHE STRING "nanopb repository URL") +-set(NANOPB_REFSPEC "nanopb-0.4.2" CACHE STRING "nanopb git refspec") +-set(NANOPB_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/nanopb_install" CACHE PATH "nanopb installation directory") +-set(NANOPB_PACKAGE_PATH "${NANOPB_INSTALL_PATH}/libnanopb/cmake" CACHE PATH "nanopb CMake package directory") ++if (NOT NANOPB_USE_INSTALLED) + +-include(FetchContent) ++ include(FetchContent) + +-# Checking git +-find_program(GIT_COMMAND "git") +-if (NOT GIT_COMMAND) +- message(FATAL_ERROR "Please install git") +-endif() ++ set(NANOPB_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/nanopb_install" CACHE PATH "nanopb installation directory") ++ set(NANOPB_PACKAGE_PATH "${NANOPB_INSTALL_PATH}/libnanopb/cmake" CACHE PATH "nanopb CMake package directory") + +-# Fetching nanopb +-FetchContent_Declare( +- nanopb +- GIT_REPOSITORY ${NANOPB_URL} +- GIT_TAG ${NANOPB_REFSPEC} +- GIT_SHALLOW TRUE +- #See the .patch file for details on why it is needed. +- PATCH_COMMAND git stash +- COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/fix-pyhon-name.patch +-) +- +-# FetchContent_GetProperties exports nanopb_SOURCE_DIR and nanopb_BINARY_DIR variables +-FetchContent_GetProperties(nanopb) +-if(NOT nanopb_POPULATED) +- message(STATUS "Fetching nanopb") +- FetchContent_Populate(nanopb) +-endif() ++ if (NOT NANOPB_SOURCE_PATH) + +-#### Build the runtime and the generator. +-if( NOT CMAKE_CROSSCOMPILING) +- execute_process(COMMAND +- ${CMAKE_COMMAND} +- -DBUILD_SHARED_LIBS=Off +- -DBUILD_STATIC_LIBS=On +- -Dnanopb_BUILD_RUNTIME=On +- -Dnanopb_BUILD_GENERATOR=On +- -Dnanopb_PROTOC_PATH=${nanopb_SOURCE_DIR}/generator/protoc +- -Dnanopb_MSVC_STATIC_RUNTIME=Off +- -DCMAKE_INSTALL_PREFIX=${NANOPB_INSTALL_PATH} +- -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} +- -GUnix\ Makefiles +- ${nanopb_SOURCE_DIR} +- WORKING_DIRECTORY +- ${nanopb_BINARY_DIR} +- RESULT_VARIABLE _exec_error +- ) +-else() +- execute_process(COMMAND +- ${CMAKE_COMMAND} +- -DBUILD_SHARED_LIBS=Off +- -DBUILD_STATIC_LIBS=On +- -Dnanopb_BUILD_RUNTIME=On +- -Dnanopb_BUILD_GENERATOR=On +- -Dnanopb_PROTOC_PATH=${nanopb_SOURCE_DIR}/generator/protoc +- -Dnanopb_MSVC_STATIC_RUNTIME=Off +- -DCMAKE_INSTALL_PREFIX=${NANOPB_INSTALL_PATH} +- -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} +- -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY +- -GUnix\ Makefiles +- ${nanopb_SOURCE_DIR} +- WORKING_DIRECTORY +- ${nanopb_BINARY_DIR} +- RESULT_VARIABLE _exec_error +- ) +-endif() ++ set(NANOPB_URL "https://github.com/nanopb/nanopb.git" CACHE STRING "nanopb repository URL") ++ set(NANOPB_REFSPEC "nanopb-0.4.2" CACHE STRING "nanopb git refspec") + +-if (_exec_error) +- message(FATAL_ERROR "Configuration step of nanopb runtime failed with ${_exec_error}.") +-endif() ++ # Checking git ++ find_program(GIT_COMMAND "git") ++ if (NOT GIT_COMMAND) ++ message(FATAL_ERROR "Please install git") ++ endif() ++ ++ # Fetching nanopb ++ FetchContent_Declare( ++ nanopb ++ GIT_REPOSITORY ${NANOPB_URL} ++ GIT_TAG ${NANOPB_REFSPEC} ++ GIT_SHALLOW TRUE ++ #See the .patch file for details on why it is needed. ++ PATCH_COMMAND git stash ++ COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/fix-pyhon-name.patch ++ ) ++ ++ else() + +-execute_process(COMMAND ++ FetchContent_Declare( ++ nanopb ++ SOURCE_DIR ${NANOPB_SOURCE_PATH} ++ ) ++ ++ endif() ++ ++ # FetchContent_GetProperties exports nanopb_SOURCE_DIR and nanopb_BINARY_DIR variables ++ FetchContent_GetProperties(nanopb) ++ if(NOT nanopb_POPULATED) ++ message(STATUS "Fetching nanopb") ++ FetchContent_Populate(nanopb) ++ endif() ++ ++ #### Build the runtime and the generator. ++ if( NOT CMAKE_CROSSCOMPILING) ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} ++ -DBUILD_SHARED_LIBS=Off ++ -DBUILD_STATIC_LIBS=On ++ -Dnanopb_BUILD_RUNTIME=On ++ -Dnanopb_BUILD_GENERATOR=On ++ -Dnanopb_PROTOC_PATH=${nanopb_SOURCE_DIR}/generator/protoc ++ -Dnanopb_MSVC_STATIC_RUNTIME=Off ++ -DCMAKE_INSTALL_PREFIX=${NANOPB_INSTALL_PATH} ++ -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} ++ -GUnix\ Makefiles ++ ${nanopb_SOURCE_DIR} ++ WORKING_DIRECTORY ++ ${nanopb_BINARY_DIR} ++ RESULT_VARIABLE _exec_error ++ ) ++ else() ++ execute_process(COMMAND ++ ${CMAKE_COMMAND} ++ -DBUILD_SHARED_LIBS=Off ++ -DBUILD_STATIC_LIBS=On ++ -Dnanopb_BUILD_RUNTIME=On ++ -Dnanopb_BUILD_GENERATOR=On ++ -Dnanopb_PROTOC_PATH=${nanopb_SOURCE_DIR}/generator/protoc ++ -Dnanopb_MSVC_STATIC_RUNTIME=Off ++ -DCMAKE_INSTALL_PREFIX=${NANOPB_INSTALL_PATH} ++ -DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE} ++ -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY ++ -GUnix\ Makefiles ++ ${nanopb_SOURCE_DIR} ++ WORKING_DIRECTORY ++ ${nanopb_BINARY_DIR} ++ RESULT_VARIABLE _exec_error ++ ) ++ endif() ++ ++ if (_exec_error) ++ message(FATAL_ERROR "Configuration step of nanopb runtime failed with ${_exec_error}.") ++ endif() ++ ++ execute_process(COMMAND + ${CMAKE_COMMAND} --build ${nanopb_BINARY_DIR} -- install -j8 + RESULT_VARIABLE _exec_error +- ) +-if (_exec_error) +- message(FATAL_ERROR "Build step of nanopb runtime failed with ${_exec_error}.") +-endif() ++ ) ++ if (_exec_error) ++ message(FATAL_ERROR "Build step of nanopb runtime failed with ${_exec_error}.") ++ endif() + +-#### Include Nanopb runtime in the build. +-find_package(Nanopb +- PATHS "${NANOPB_INSTALL_PATH}" +- NO_DEFAULT_PATH ++ #### Include Nanopb runtime in the build. ++ find_package(Nanopb ++ PATHS "${NANOPB_INSTALL_PATH}" ++ NO_DEFAULT_PATH + ) + +-#### Build access to the protobuf compiler +-#TODO: verify protoc dependencies: python3-protobuf +-find_package(Python3 COMPONENTS Interpreter) ++else() ++ ++ #### Build access to the protobuf compiler ++ #TODO: verify protoc dependencies: python3-protobuf ++ find_package(Nanopb REQUIRED) ++ ++endif() + ++find_package(Python3 COMPONENTS Interpreter) + if (NOT Python3_Interpreter_FOUND) + message(FATAL_ERROR "Failed to find python3 interpreter.") + endif() + +-find_file(NANOPB_GENERATOR_PATH +- NAMES nanopb_generator.py +- PATHS ${nanopb_SOURCE_DIR}/generator +- DOC "nanopb protobuf compiler" +- NO_DEFAULT_PATH ++if (NOT NANOPB_USE_INSTALLED) ++ find_file(NANOPB_GENERATOR_PATH ++ NAMES nanopb_generator.py ++ PATHS "${nanopb_SOURCE_DIR}/generator" ++ DOC "nanopb protobuf compiler" ++ REQUIRED ++ NO_DEFAULT_PATH ++ ) ++else() ++ find_file(NANOPB_GENERATOR_PATH ++ NAMES nanopb_generator.py ++ DOC "nanopb protobuf compiler" ++ REQUIRED + ) ++endif() + + if (NOT NANOPB_GENERATOR_PATH) + message(FATAL_ERROR "Nanopb generator was not found!") +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch b/meta-arm/recipes-security/trusted-services/files/0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch new file mode 100644 index 00000000..14b79d6f --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch @@ -0,0 +1,49 @@ +From 0075dc6cf30df6a2d91ab3870dabed4ac220a468 Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Mon, 22 Mar 2021 11:00:40 +0000 +Subject: [PATCH 11/13] aarch64: Allow the stack to be further than 1MB from + where it is set up + +Trusted-services crypto was previously building with the linaro 7.5 + aarch64-linux-gnu but not with arm 10.2 aarch64-none-linux-gnu. +Build error was: +aarch64/sp_entrypoint.S:22:(.text.sp_entrypoint+0x0): + relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.bss.stacks' + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Ben Horgan +Change-Id: Ia422722c986bce50543f026ccbad728e6938f2b0 +Signed-off-by: Ben Horgan +--- + environments/shim/aarch64/sp_entrypoint.S | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/environments/shim/aarch64/sp_entrypoint.S b/environments/shim/aarch64/sp_entrypoint.S +index 8ef330b..ee7f84d 100644 +--- a/environments/shim/aarch64/sp_entrypoint.S ++++ b/environments/shim/aarch64/sp_entrypoint.S +@@ -12,17 +12,18 @@ + .globl sp_entrypoint + + .section .bss.stacks +- .balign CACHE_WRITEBACK_GRANULE ++ .balign CACHE_WRITEBACK_GRANULE + .fill SP_STACKS_SIZE + stacks_end: + + func sp_entrypoint + + /* Setup the stack pointer. */ +- adr x0, stacks_end ++ adrp x0, stacks_end ++ add x0, x0, :lo12:stacks_end + mov sp, x0 + /* Mask FIQs */ +- msr daifset, #DAIF_FIQ_BIT ++ msr daifset, #DAIF_FIQ_BIT + isb + + /* And jump to the C entrypoint. */ +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0012-libc-Add-missing-libc-function-declarations.patch b/meta-arm/recipes-security/trusted-services/files/0012-libc-Add-missing-libc-function-declarations.patch new file mode 100644 index 00000000..500227be --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0012-libc-Add-missing-libc-function-declarations.patch @@ -0,0 +1,93 @@ +From 78ddf721076d2baca395f418973d5eb5d19ec4ab Mon Sep 17 00:00:00 2001 +From: Ben Horgan +Date: Tue, 30 Mar 2021 13:15:54 +0000 +Subject: [PATCH 12/13] libc: Add missing libc function declarations + +Upstream-Status: Pending [Not submitted to upstream yet] +Change-Id: I00e54db41b3226cc60a89bf4a81edea0a6fbb2a5 +Signed-off-by: Ben Horgan +--- + environments/shim/include/lib/libc/assert.h | 4 +--- + environments/shim/include/lib/libc/memory.h | 7 +++++++ + environments/shim/include/lib/libc/stdint.h | 18 +++++++++--------- + environments/shim/include/lib/libc/stdlib.h | 2 ++ + 4 files changed, 19 insertions(+), 12 deletions(-) + create mode 100644 environments/shim/include/lib/libc/memory.h + +diff --git a/environments/shim/include/lib/libc/assert.h b/environments/shim/include/lib/libc/assert.h +index ec28c26..e32259b 100644 +--- a/environments/shim/include/lib/libc/assert.h ++++ b/environments/shim/include/lib/libc/assert.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. ++ * Copyright (c) 2018 - 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -9,8 +9,6 @@ + + #include + +-#include +- + #if ENABLE_ASSERTIONS + #define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) + #else +diff --git a/environments/shim/include/lib/libc/memory.h b/environments/shim/include/lib/libc/memory.h +new file mode 100644 +index 0000000..823bf26 +--- /dev/null ++++ b/environments/shim/include/lib/libc/memory.h +@@ -0,0 +1,7 @@ ++/* ++ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include +diff --git a/environments/shim/include/lib/libc/stdint.h b/environments/shim/include/lib/libc/stdint.h +index d5dbfc4..b636299 100644 +--- a/environments/shim/include/lib/libc/stdint.h ++++ b/environments/shim/include/lib/libc/stdint.h +@@ -107,15 +107,15 @@ typedef unsigned short uint16_least_t; + typedef unsigned int uint32_least_t; + typedef unsigned long long uint64_least_t; + +-typedef int int8_fast_t; +-typedef int int16_fast_t; +-typedef int int32_fast_t; +-typedef long long int64_fast_t; +- +-typedef unsigned int uint8_fast_t; +-typedef unsigned int uint16_fast_t; +-typedef unsigned int uint32_fast_t; +-typedef unsigned long long uint64_fast_t; ++typedef int int_fast8_t; ++typedef int int_fast16_t; ++typedef int int_fast32_t; ++typedef long long int_fast64_t; ++ ++typedef unsigned int uint_fast8_t; ++typedef unsigned int uint_fast16_t; ++typedef unsigned int uint_fast32_t; ++typedef unsigned long long uint_fast64_t; + + typedef long intptr_t; + typedef unsigned long uintptr_t; +diff --git a/environments/shim/include/lib/libc/stdlib.h b/environments/shim/include/lib/libc/stdlib.h +index bbd6889..7f01cfb 100644 +--- a/environments/shim/include/lib/libc/stdlib.h ++++ b/environments/shim/include/lib/libc/stdlib.h +@@ -30,5 +30,7 @@ void srand(unsigned int seed); + void malloc_add_pool(void *buf, size_t len); + void *malloc(size_t size); + void free(void *ptr); ++void *calloc(size_t nmemb, size_t size); ++void *realloc(void *ptr, size_t size); + + #endif /* STDLIB_H */ +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/files/0013-libsp-modify-FFA-ABIs-with-supported-convention.patch b/meta-arm/recipes-security/trusted-services/files/0013-libsp-modify-FFA-ABIs-with-supported-convention.patch new file mode 100644 index 00000000..a0e23756 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/files/0013-libsp-modify-FFA-ABIs-with-supported-convention.patch @@ -0,0 +1,69 @@ +From 8603e07c95ec9c543c38181f60d0a3ead4a5f237 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy +Date: Mon, 12 Apr 2021 13:12:41 +0100 +Subject: [PATCH 13/13] libsp: modify FFA ABIs with supported convention + +SPMC at SEL2 (hafnium) only supports 64-bit variant of FFA_RXTX_MAP + +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Arunachalam Ganapathy +Change-Id: I17ba68bc298fd5d26dbead23dd0750b84319d9c6 +Signed-off-by: Ben Horgan +--- + components/messaging/ffa/libsp/ffa.c | 6 +++--- + components/messaging/ffa/libsp/sp_rxtx.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c +index 648d3c8..2bdd31b 100644 +--- a/components/messaging/ffa/libsp/ffa.c ++++ b/components/messaging/ffa/libsp/ffa.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-3-Clause + /* +- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + */ + + #include // for assert +@@ -133,14 +133,14 @@ ffa_result ffa_rxtx_map(const void *tx_buffer, const void *rx_buffer, + page_count = SHIFT_U32(page_count & FFA_RXTX_MAP_PAGE_COUNT_MASK, + FFA_RXTX_MAP_PAGE_COUNT_SHIFT); + +- ffa_svc(FFA_RXTX_MAP_32, (uintptr_t)tx_buffer, (uintptr_t)rx_buffer, ++ ffa_svc(FFA_RXTX_MAP_64, (uintptr_t)tx_buffer, (uintptr_t)rx_buffer, + page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, &result); + + if (result.a0 == FFA_ERROR) + return ffa_get_errorcode(&result); + +- assert(result.a0 == FFA_SUCCESS_32); ++ assert(result.a0 == FFA_SUCCESS_64); + return FFA_OK; + } + +diff --git a/components/messaging/ffa/libsp/sp_rxtx.c b/components/messaging/ffa/libsp/sp_rxtx.c +index a3de270..9468d83 100644 +--- a/components/messaging/ffa/libsp/sp_rxtx.c ++++ b/components/messaging/ffa/libsp/sp_rxtx.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-3-Clause + /* +- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + */ + + #include "sp_rxtx.h" +@@ -99,7 +99,7 @@ sp_result sp_rxtx_buffer_alignment_boundary_get(uintptr_t *alignment) + return SP_RESULT_INVALID_PARAMETERS; + + /* Querying FFX_RXTX_MAP features */ +- result = ffa_features(FFA_RXTX_MAP_32, &interface_props); ++ result = ffa_features(FFA_RXTX_MAP_64, &interface_props); + if (result != FFA_OK) { + *alignment = 0; + return SP_RESULT_FFA(result); +-- +2.29.2 + diff --git a/meta-arm/recipes-security/trusted-services/libts_git.bb b/meta-arm/recipes-security/trusted-services/libts_git.bb new file mode 100644 index 00000000..06a1bce8 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/libts_git.bb @@ -0,0 +1,41 @@ +SUMMARY = "Trusted services linux library" +HOMEPAGE = "https://trusted-services.readthedocs.io/en/latest/index.html" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://license.rst;md5=ea160bac7f690a069c608516b17997f4" + +SRC_URI = "git://git.trustedfirmware.org/TS/trusted-services.git;protocol=https;branch=integration \ + file://0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch \ + file://0002-Change-instruction-access-permissions-of-shared-memo.patch \ + file://0003-Set-in_region_count-to-0-during-memory-retrieve.patch \ + file://0004-Release-rx-buffer-after-memory-retrieve-request.patch \ + file://0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch \ + file://0006-secure-storage-Create-a-new-deployment-with-the-shim.patch \ + file://0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch \ + file://0008-libts-arm-linux-Add-version-to-libts.so.patch \ + file://0009-libts-Add-option-to-use-installed-libts.patch \ + file://0010-external-Add-option-to-use-local-source-or-installed.patch \ + file://0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch \ + file://0012-libc-Add-missing-libc-function-declarations.patch \ + file://0013-libsp-modify-FFA-ABIs-with-supported-convention.patch \ + " + +PV = "1.0+git${SRCPV}" +SRCREV = "eff4b28b6ae461defb2d8c0f614965439ed19386" + +S = "${WORKDIR}/git" + +inherit python3native cmake + +DEPENDS = "python3-pycryptodome-native python3-pycryptodomex-native \ + python3-pyelftools-native python3-grpcio-tools-native \ + python3-protobuf-native protobuf-native nanopb-native \ + ts-mbedcrypto \ + " + +OECMAKE_SOURCEPATH = "${S}/deployments/libts/arm-linux" +OECMAKE_GENERATOR = "Unix Makefiles" +EXTRA_OECMAKE = "-DCMAKE_POSITION_INDEPENDENT_CODE=True \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_SYSTEM_PROCESSOR=arm \ + " diff --git a/meta-arm/recipes-security/trusted-services/secure-storage_git.bb b/meta-arm/recipes-security/trusted-services/secure-storage_git.bb new file mode 100644 index 00000000..b93a80eb --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/secure-storage_git.bb @@ -0,0 +1,14 @@ +SUMMARY = "Secure storage secure partition" + +require sp.inc + +TS_DEPLOYMENT = "${S}/deployments/secure-storage/shim" + +do_install () { + install -d -m 755 ${D}/firmware + install -m 0644 "${B}/secure-storage.bin" "${D}/firmware/secure-storage.bin" + install -m 0644 "${S}/deployments/secure-storage/shim/secure-storage.dts" \ + "${D}/firmware/secure-storage.dts" +} + +FILES_${PN} = "/firmware/secure-storage.bin /firmware/secure-storage.dts" diff --git a/meta-arm/recipes-security/trusted-services/sp.inc b/meta-arm/recipes-security/trusted-services/sp.inc new file mode 100644 index 00000000..d3f5034a --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/sp.inc @@ -0,0 +1,68 @@ +HOMEPAGE = "https://trusted-services.readthedocs.io/en/latest/index.html" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +LICENSE = "Apache-2.0 & BSD-3-Clause & Zlib" +LIC_FILES_CHKSUM = "file://license.rst;md5=ea160bac7f690a069c608516b17997f4 \ + file://mbedcrypto/LICENSE;md5=302d50a6369f5f22efdb674db908167a \ + file://nanopb/LICENSE.txt;md5=9db4b73a55a3994384112efcdb37c01f \ + " +SRC_URI = "git://git.trustedfirmware.org/TS/trusted-services.git;protocol=https;branch=main;name=ts;destsuffix=git \ + git://github.com/ARMmbed/mbed-crypto.git;protocol=git;branch=development;name=mbed;destsuffix=git/mbedcrypto \ + git://github.com/nanopb/nanopb.git;name=nanopb;branch=master;destsuffix=git/nanopb \ + file://0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch \ + file://0002-Change-instruction-access-permissions-of-shared-memo.patch \ + file://0003-Set-in_region_count-to-0-during-memory-retrieve.patch \ + file://0004-Release-rx-buffer-after-memory-retrieve-request.patch \ + file://0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch \ + file://0006-secure-storage-Create-a-new-deployment-with-the-shim.patch \ + file://0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch \ + file://0008-libts-arm-linux-Add-version-to-libts.so.patch \ + file://0009-libts-Add-option-to-use-installed-libts.patch \ + file://0010-external-Add-option-to-use-local-source-or-installed.patch \ + file://0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch \ + file://0012-libc-Add-missing-libc-function-declarations.patch \ + file://0013-libsp-modify-FFA-ABIs-with-supported-convention.patch \ + " + +PV = "1.0+git${SRCPV}" + +SRCREV_FORMAT = "ts" +SRCREV_ts = "eff4b28b6ae461defb2d8c0f614965439ed19386" +SRCREV_mbed = "cf4a40ba0a3086cabb5a8227245191161fd26383" +SRCREV_nanopb = "df0e92f474f9cca704fe2b31483f0b4d1b1715a4" + +S = "${WORKDIR}/git" +TS_DEPLOYMENTS_DIR := "${S}/deployments/" + +inherit deploy python3native + +DEPENDS = "python3-pycryptodome-native python3-pycryptodomex-native \ + python3-pyelftools-native python3-grpcio-tools-native \ + python3-protobuf-native protobuf-native cmake-native \ + " + +# Baremetal, just need a compiler +DEPENDS_remove = "virtual/${TARGET_PREFIX}compilerlibs virtual/libc" + +export CROSS_COMPILE = "${TARGET_PREFIX}" + +B = "${WORKDIR}/build" + +do_configure() { + cmake \ + -DMBEDCRYPTO_SOURCE_PATH=${S}/mbedcrypto \ + -DNANOPB_SOURCE_PATH=${S}/nanopb \ + -S ${TS_DEPLOYMENT} -B ${B} +} + +do_compile() { + cmake --build ${B} +} + +SYSROOT_DIRS = "/firmware" + +do_deploy() { + cp -rf ${D}/firmware/* ${DEPLOYDIR}/ +} +addtask deploy after do_install diff --git a/meta-arm/recipes-security/trusted-services/ts-cpputest/cpputest-cmake-fix.patch b/meta-arm/recipes-security/trusted-services/ts-cpputest/cpputest-cmake-fix.patch new file mode 100644 index 00000000..fb589b74 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/ts-cpputest/cpputest-cmake-fix.patch @@ -0,0 +1,59 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b1900bb..d9ca865 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -116,8 +116,13 @@ if(PkgHelpers_AVAILABLE) + ${CMAKE_CURRENT_BINARY_DIR}/CppUTestConfig.cmake + INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR} + PATH_VARS INCLUDE_DIR CMAKE_CURRENT_BINARY_DIR) +- export(TARGETS CppUTest CppUTestExt ++ if(TARGET CppUTestExt) ++ export(TARGETS CppUTest + FILE "${CMAKE_CURRENT_BINARY_DIR}/CppUTestTargets.cmake") ++ else() ++ export(TARGETS CppUTest ++ FILE "${CMAKE_CURRENT_BINARY_DIR}/CppUTestTargets.cmake") ++ endif() + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/CppUTestConfigVersion.cmake + VERSION ${CppUTest_version_major}.${CppUTest_version_minor} +diff --git a/cmake/Modules/CppUTestConfigurationOptions.cmake b/cmake/Modules/CppUTestConfigurationOptions.cmake +index 634482c..a00b5eb 100644 +--- a/cmake/Modules/CppUTestConfigurationOptions.cmake ++++ b/cmake/Modules/CppUTestConfigurationOptions.cmake +@@ -1,19 +1,19 @@ + if (MSVC) +- set(CPP_PLATFORM VisualCpp) ++ set(CPP_PLATFORM VisualCpp CACHE STRING "CppUTest platform.") + include_directories(${CppUTestRootDirectory}/include/Platforms/${CPP_PLATFORM}) + option(STDC_WANT_SECURE_LIB "Use MSVC safe functions" ON) + if(STDC_WANT_SECURE_LIB) + ADD_DEFINITIONS(-DSTDC_WANT_SECURE_LIB) + endif(STDC_WANT_SECURE_LIB) + elseif (STD_C) +- set(CPP_PLATFORM Gcc) ++ set(CPP_PLATFORM Gcc CACHE STRING "CppUTest platform.") + else (MSVC) + set(STD_CPP False) + set(MEMORY_LEAK_DETECTION False) + set(CPPUTEST_CXX_FLAGS "${CPPUTEST_CXX_FLAGS} -nostdinc") + set(CPPUTEST_LD_FLAGS "${CPPUTEST_LD_FLAGS} -nostdinc") + set(CPPUTEST_STD_C_LIB_DISABLED 1) +- set(CPP_PLATFORM GccNoStdC) ++ set(CPP_PLATFORM GccNoStdC CACHE STRING "CppUTest platform.") + endif (MSVC) + + include("${CppUTestRootDirectory}/cmake/Modules/CppUTestWarningFlags.cmake") +diff --git a/src/CppUTest/CMakeLists.txt b/src/CppUTest/CMakeLists.txt +index 736777f..d9a592f 100644 +--- a/src/CppUTest/CMakeLists.txt ++++ b/src/CppUTest/CMakeLists.txt +@@ -50,7 +50,7 @@ set(CppUTest_headers + + add_library(CppUTest STATIC ${CppUTest_src} ${CppUTest_headers}) + if (WIN32) +- target_link_libraries(CppUTest winmm.lib) ++ target_link_libraries(CppUTest winmm) + endif (WIN32) + install(FILES ${CppUTest_headers} DESTINATION include/CppUTest) + install(TARGETS CppUTest diff --git a/meta-arm/recipes-security/trusted-services/ts-cpputest_3.8.bb b/meta-arm/recipes-security/trusted-services/ts-cpputest_3.8.bb new file mode 100644 index 00000000..393eea36 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/ts-cpputest_3.8.bb @@ -0,0 +1,30 @@ +SUMMARY = "CppUTest for trusted services" +DESCRIPTION = "CppUTest unit testing and mocking framework for C/C++" +HOMEPAGE = "http://cpputest.github.io/" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://COPYING;md5=ce5d5f1fe02bcd1343ced64a06fd4177" + +SRC_URI = "git://github.com/cpputest/cpputest.git \ + file://cpputest-cmake-fix.patch \ + " +SRCREV = "e25097614e1c4856036366877a02346c4b36bb5b" + +PV = "3.8+git${SRCPV}" + +S = "${WORKDIR}/git" + +inherit cmake + +OECMAKE_GENERATOR = "Unix Makefiles" +EXTRA_OECMAKE = "-DCMAKE_POSITION_INDEPENDENT_CODE=True \ + -DMEMORY_LEAK_DETECTION=OFF \ + -DLONGLONG=ON \ + -DC++11=ON \ + -DTESTS=OFF \ + -DEXTENSIONS=OFF \ + -DHAVE_FORK=OFF \ + -DCPP_PLATFORM=armcc \ + -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \ + " +FILES_${PN} += "/usr/lib/CppUTest/* /usr/lib/CppUTest/cmake/*" diff --git a/meta-arm/recipes-security/trusted-services/ts-demo_git.bb b/meta-arm/recipes-security/trusted-services/ts-demo_git.bb new file mode 100644 index 00000000..ad0a8b91 --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/ts-demo_git.bb @@ -0,0 +1,42 @@ +SUMMARY = "Trusted Services test application" +HOMEPAGE = "https://trusted-services.readthedocs.io/en/latest/index.html" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://license.rst;md5=ea160bac7f690a069c608516b17997f4" + +SRC_URI = "git://git.trustedfirmware.org/TS/trusted-services.git;protocol=ssh;branch=main \ + file://0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch \ + file://0002-Change-instruction-access-permissions-of-shared-memo.patch \ + file://0003-Set-in_region_count-to-0-during-memory-retrieve.patch \ + file://0004-Release-rx-buffer-after-memory-retrieve-request.patch \ + file://0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch \ + file://0006-secure-storage-Create-a-new-deployment-with-the-shim.patch \ + file://0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch \ + file://0008-libts-arm-linux-Add-version-to-libts.so.patch \ + file://0009-libts-Add-option-to-use-installed-libts.patch \ + file://0010-external-Add-option-to-use-local-source-or-installed.patch \ + file://0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch \ + file://0012-libc-Add-missing-libc-function-declarations.patch \ + file://0013-libsp-modify-FFA-ABIs-with-supported-convention.patch \ + " + +PV = "1.0+git${SRCPV}" +SRCREV = "eff4b28b6ae461defb2d8c0f614965439ed19386" + +S = "${WORKDIR}/git" + +inherit python3native cmake + +DEPENDS = "python3-pycryptodome-native python3-pycryptodomex-native \ + python3-pyelftools-native python3-grpcio-tools-native \ + python3-protobuf-native protobuf-native nanopb nanopb-native \ + ts-mbedcrypto libts \ + " + +OECMAKE_SOURCEPATH = "${S}/deployments/ts-demo/arm-linux" +OECMAKE_GENERATOR = "Unix Makefiles" +EXTRA_OECMAKE = "-DCMAKE_POSITION_INDEPENDENT_CODE=True \ + -DMBEDCRYPTO_USE_INSTALLED=True \ + -DNANOPB_USE_INSTALLED=True \ + -DLIBTS_USE_INSTALLED=True \ + " diff --git a/meta-arm/recipes-security/trusted-services/ts-mbedcrypto_3.1.0.bb b/meta-arm/recipes-security/trusted-services/ts-mbedcrypto_3.1.0.bb new file mode 100644 index 00000000..a6b8b76a --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/ts-mbedcrypto_3.1.0.bb @@ -0,0 +1,46 @@ +SUMMARY = "Mbedcrypto for trusted services" +DESCRIPTION = "A reference implementation of the cryptography \ +interface of the Arm Platform Security Architecture (PSA). Compiled \ +with the configuration for trusted services." +HOMEPAGE = "https://github.com/ARMmbed/mbed-crypto" + +LICENSE = "Apache-2.0 & BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=302d50a6369f5f22efdb674db908167a \ + file://ts/license.rst;md5=ea160bac7f690a069c608516b17997f4 \ + " +SRC_URI = "git://github.com/ARMmbed/mbed-crypto.git;protocol=git;branch=development;name=mbed;destsuffix=git \ + git://git.trustedfirmware.org/TS/trusted-services.git;protocol=https;branch=main;name=ts;destsuffix=git/ts \ + file://0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch;patchdir=${S}/ts \ + file://0002-Change-instruction-access-permissions-of-shared-memo.patch;patchdir=${S}/ts \ + file://0003-Set-in_region_count-to-0-during-memory-retrieve.patch;patchdir=${S}/ts \ + file://0004-Release-rx-buffer-after-memory-retrieve-request.patch;patchdir=${S}/ts \ + file://0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch;patchdir=${S}/ts \ + file://0006-secure-storage-Create-a-new-deployment-with-the-shim.patch;patchdir=${S}/ts \ + file://0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch;patchdir=${S}/ts \ + file://0008-libts-arm-linux-Add-version-to-libts.so.patch;patchdir=${S}/ts \ + file://0009-libts-Add-option-to-use-installed-libts.patch;patchdir=${S}/ts \ + file://0010-external-Add-option-to-use-local-source-or-installed.patch;patchdir=${S}/ts \ + file://0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch;patchdir=${S}/ts \ + file://0012-libc-Add-missing-libc-function-declarations.patch;patchdir=${S}/ts \ + file://0013-libsp-modify-FFA-ABIs-with-supported-convention.patch;patchdir=${S}/ts \ + " + +PV = "3.1.0+git" + +SRCREV_FORMAT = "mbed" +SRCREV_mbed = "cf4a40ba0a3086cabb5a8227245191161fd26383" +SRCREV_ts = "eff4b28b6ae461defb2d8c0f614965439ed19386" + +S = "${WORKDIR}/git" + +inherit cmake + +MBEDCRYPTO_CONFIG_FILE = "${S}/ts/components/service/crypto/client/cpp/config_mbed_crypto.h" + +OECMAKE_GENERATOR = "Unix Makefiles" +EXTRA_OECMAKE = "-DCMAKE_POSITION_INDEPENDENT_CODE=True \ + -DENABLE_PROGRAMS=OFF \ + -DENABLE_TESTING=OFF \ + -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \ + -Dthirdparty_def=-DMBEDTLS_CONFIG_FILE=\"${MBEDCRYPTO_CONFIG_FILE}\" \ + " diff --git a/meta-arm/recipes-security/trusted-services/ts-service-test_git.bb b/meta-arm/recipes-security/trusted-services/ts-service-test_git.bb new file mode 100644 index 00000000..4f1aa47c --- /dev/null +++ b/meta-arm/recipes-security/trusted-services/ts-service-test_git.bb @@ -0,0 +1,42 @@ +SUMMARY = "Trusted Services demo application" +HOMEPAGE = "https://trusted-services.readthedocs.io/en/latest/index.html" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://license.rst;md5=ea160bac7f690a069c608516b17997f4" + +SRC_URI = "git://git.trustedfirmware.org/TS/trusted-services.git;protocol=https;branch=main \ + file://0001-Add-a-new-environment-to-run-TS-with-a-shim-layer-in.patch \ + file://0002-Change-instruction-access-permissions-of-shared-memo.patch \ + file://0003-Set-in_region_count-to-0-during-memory-retrieve.patch \ + file://0004-Release-rx-buffer-after-memory-retrieve-request.patch \ + file://0005-crypto-sp-Create-a-new-deployment-with-the-shim-envi.patch \ + file://0006-secure-storage-Create-a-new-deployment-with-the-shim.patch \ + file://0007-crypto-shim-Don-t-link-against-unrequired-libraries.patch \ + file://0008-libts-arm-linux-Add-version-to-libts.so.patch \ + file://0009-libts-Add-option-to-use-installed-libts.patch \ + file://0010-external-Add-option-to-use-local-source-or-installed.patch \ + file://0011-aarch64-Allow-the-stack-to-be-further-than-1MB-from-.patch \ + file://0012-libc-Add-missing-libc-function-declarations.patch \ + file://0013-libsp-modify-FFA-ABIs-with-supported-convention.patch \ + " + +PV = "1.0+git${SRCPV}" +SRCREV = "eff4b28b6ae461defb2d8c0f614965439ed19386" + +S = "${WORKDIR}/git" + +inherit deploy python3native cmake + +DEPENDS = "python3-pycryptodome-native python3-pycryptodomex-native \ + python3-pyelftools-native python3-grpcio-tools-native \ + python3-protobuf-native protobuf-native nanopb nanopb-native \ + ts-mbedcrypto libts ts-cpputest" + +OECMAKE_SOURCEPATH = "${S}/deployments/ts-service-test/arm-linux" +OECMAKE_GENERATOR = "Unix Makefiles" +EXTRA_OECMAKE = "-DCMAKE_POSITION_INDEPENDENT_CODE=True \ + -DMBEDCRYPTO_USE_INSTALLED=True \ + -DNANOPB_USE_INSTALLED=True \ + -DLIBTS_USE_INSTALLED=True \ + -DCPPUTEST_USE_INSTALLED=True \ + "