Merge "fix(psa): increase psa-mbedtls heap size for rsa" into integration
diff --git a/Makefile b/Makefile
index 384c1e4..6e0e584 100644
--- a/Makefile
+++ b/Makefile
@@ -882,6 +882,10 @@
CRYPTO_SUPPORT := 0
endif #($(MEASURED_BOOT)-$(TRUSTED_BOARD_BOOT))
+ifneq ($(filter 1 2 3,$(CRYPTO_SUPPORT)),)
+CRYPTO_LIB := $(BUILD_PLAT)/lib/libmbedtls.a
+endif
+
# SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled.
ifeq ($(SDEI_SUPPORT)-$(SDEI_IN_FCONF),0-1)
$(error "SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled")
@@ -951,8 +955,21 @@
ifeq (${ENABLE_FEAT_RNG_TRAP},1)
$(error "ENABLE_FEAT_RNG_TRAP cannot be used with ARCH=aarch32")
endif
+
+ ifneq (${ENABLE_FEAT_FPMR},0)
+ $(error "ENABLE_FEAT_FPMR cannot be used with ARCH=aarch32")
+ endif
endif #(ARCH=aarch32)
+ifneq (${ENABLE_FEAT_FPMR},0)
+ ifeq (${ENABLE_FEAT_FGT},0)
+ $(error "ENABLE_FEAT_FPMR requires ENABLE_FEAT_FGT")
+ endif
+ ifeq (${ENABLE_FEAT_HCX},0)
+ $(error "ENABLE_FEAT_FPMR requires ENABLE_FEAT_HCX")
+ endif
+endif #(ENABLE_FEAT_FPMR)
+
ifneq (${ENABLE_SME_FOR_NS},0)
ifeq (${ENABLE_SVE_FOR_NS},0)
$(error "ENABLE_SME_FOR_NS requires ENABLE_SVE_FOR_NS")
@@ -1264,6 +1281,7 @@
ENABLE_FEAT_ECV \
ENABLE_FEAT_FGT \
ENABLE_FEAT_FGT2 \
+ ENABLE_FEAT_FPMR \
ENABLE_FEAT_HCX \
ENABLE_FEAT_LS64_ACCDATA \
ENABLE_FEAT_MTE2 \
@@ -1425,6 +1443,7 @@
ENABLE_MPMM_FCONF \
ENABLE_FEAT_FGT \
ENABLE_FEAT_FGT2 \
+ ENABLE_FEAT_FPMR \
ENABLE_FEAT_ECV \
ENABLE_FEAT_AMUv1p1 \
ENABLE_FEAT_SEL2 \
@@ -1741,8 +1760,8 @@
$(q)set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL))
endif #(UNIX_MK)
-$(BUILD_PLAT)/romlib/romlib.bin $(BUILD_PLAT)/lib/libwrappers.a $&: $(BUILD_PLAT)/lib/libmbedtls.a $(BUILD_PLAT)/lib/libfdt.a $(BUILD_PLAT)/lib/libc.a
- $(q)${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES=$(call escape-shell,$(INCLUDES)) DEFINES=$(call escape-shell,$(DEFINES)) --no-print-directory -C ${ROMLIBPATH} all
+$(BUILD_PLAT)/romlib/romlib.bin $(BUILD_PLAT)/lib/libwrappers.a $&: $(BUILD_PLAT)/lib/libfdt.a $(BUILD_PLAT)/lib/libc.a $(CRYPTO_LIB)
+ $(q)${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} CRYPTO_SUPPORT=${CRYPTO_SUPPORT} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES=$(call escape-shell,$(INCLUDES)) DEFINES=$(call escape-shell,$(DEFINES)) --no-print-directory -C ${ROMLIBPATH} all
memmap: all
ifdef UNIX_MK
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 336ad2b..2f9dc65 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -150,6 +150,10 @@
BL31_SOURCES += lib/extensions/trf/aarch64/trf.c
endif
+ifneq (${ENABLE_FEAT_FPMR},0)
+BL31_SOURCES += lib/extensions/fpmr/fpmr.c
+endif
+
ifeq (${WORKAROUND_CVE_2017_5715},1)
BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \
lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 8c03ab8..0f6be9f 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -280,6 +280,12 @@
ID_AA64MMFR3_EL1_D128_MASK);
}
+static unsigned int read_feat_fpmr_id_field(void)
+{
+ return ISOLATE_FIELD(read_id_aa64pfr2_el1(), ID_AA64PFR2_EL1_FPMR_SHIFT,
+ ID_AA64PFR2_EL1_FPMR_MASK);
+}
+
/***********************************************************************************
* TF-A supports many Arm architectural features starting from arch version
* (8.0 till 8.7+). These features are mostly enabled through build flags. This
@@ -405,6 +411,8 @@
"SME", 1, 2);
check_feature(ENABLE_SME2_FOR_NS, read_feat_sme_id_field(),
"SME2", 2, 2);
+ check_feature(ENABLE_FEAT_FPMR, read_feat_fpmr_id_field(),
+ "FPMR", 1, 1);
/* v9.3 features */
check_feature(ENABLE_FEAT_D128, read_feat_d128_id_field(),
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index fda43dc..f1cb73b 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -843,6 +843,9 @@
- ``ERRATA_X4_2897503``: This applies errata 2897503 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+- ``ERRATA_X4_2923985``: This applies errata 2923985 workaround to Cortex-X4
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+
- ``ERRATA_X4_3076789``: This applies errata 3076789 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 7d067c6..14eac5f 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -351,6 +351,12 @@
This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
+- ``ENABLE_FEAT_FPMR``: Numerical value to enable support for Floating Point
+ Mode Register feature, allowing access to the FPMR register. FPMR register
+ controls the behaviors of FP8 instructions. It is an optional architectural
+ feature from v9.2 and upwards. This flag can take value of 0 to 2, to align
+ with the ``FEATURE_DETECTION`` mechanism. Default value is ``0``.
+
- ``ENABLE_FEAT_FGT``: Numeric value to enable support for FGT (Fine Grain Traps)
feature allowing for access to the HDFGRTR_EL2 (Hypervisor Debug Fine-Grained
Read Trap Register) during EL2 to EL3 context save/restore operations.
@@ -708,6 +714,10 @@
invert this behavior. Lower addresses will be printed at the top and higher
addresses at the bottom.
+- ``INIT_UNUSED_NS_EL2``: This build flag guards code that disables EL2
+ safely in scenario where NS-EL2 is present but unused. This flag is set to 0
+ by default. Platforms without NS-EL2 in use must enable this flag.
+
- ``KEY_ALG``: This build flag enables the user to select the algorithm to be
used for generating the PKCS keys and subsequent signing of the certificate.
It accepts 5 values: ``rsa``, ``rsa_1_5``, ``ecdsa``, ``ecdsa-brainpool-regular``
diff --git a/docs/plat/qti.rst b/docs/plat/qti.rst
index 1d483e7..0f89500 100644
--- a/docs/plat/qti.rst
+++ b/docs/plat/qti.rst
@@ -2,7 +2,7 @@
===========================
Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180,
-SC7280.
+SC7280 and QCS615.
Boot Trace
-------------
@@ -30,7 +30,8 @@
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sc7180 COREBOOT=1
-update value of CROSS_COMPILE argument with your cross-compilation toolchain.
+Update value of CROSS_COMPILE argument with your cross-compilation toolchain.
+Update the value of PLAT to be either of sc7180, sc7280 or qcs615
Additional QTISECLIB_PATH=<path to qtiseclib> can be added in build command.
if QTISECLIB_PATH is not added in build command stub implementation of qtiseclib
@@ -41,3 +42,4 @@
`link <https://github.com/coreboot/qc_blobs/blob/master/sc7180/qtiseclib/libqtisec.a?raw=true>`__
QTISELIB for SC7280 is available at
`link <https://github.com/coreboot/qc_blobs/blob/master/sc7280/qtiseclib/libqtisec.a?raw=true>`__
+QTISECLIB for QCS615 is not available yet and currently compile with stubs only.
diff --git a/fdts/tc3-4-base.dtsi b/fdts/tc3-4-base.dtsi
index 2de5fd3..5ccfebb 100644
--- a/fdts/tc3-4-base.dtsi
+++ b/fdts/tc3-4-base.dtsi
@@ -52,6 +52,31 @@
};
};
+ rse_mbox_db_rx: mhu@RSE_MHU_RX_ADDR {
+ compatible = MHU_RX_COMPAT;
+ reg = <0x0 ADDRESSIFY(RSE_MHU_RX_ADDR) 0x0 MHU_OFFSET>;
+ clocks = <&soc_refclk>;
+ clock-names = "apb_pclk";
+ #mbox-cells = <MHU_MBOX_CELLS>;
+ interrupts = <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = MHU_RX_INT_NAME;
+#if TARGET_FLAVOUR_FPGA
+ status = "disabled";
+#endif
+ };
+
+ rse_mbox_db_tx: mhu@RSE_MHU_TX_ADDR {
+ compatible = MHU_TX_COMPAT;
+ reg = <0x0 ADDRESSIFY(RSE_MHU_TX_ADDR) 0x0 MHU_OFFSET>;
+ clocks = <&soc_refclk>;
+ clock-names = "apb_pclk";
+ #mbox-cells = <MHU_MBOX_CELLS>;
+ interrupt-names = MHU_TX_INT_NAME;
+#if TARGET_FLAVOUR_FPGA
+ status = "disabled";
+#endif
+ };
+
gic: interrupt-controller@GIC_CTRL_ADDR {
ppi-partitions {
ppi_partition_little: interrupt-partition-0 {
@@ -80,5 +105,19 @@
mboxes = <&mbox_db_tx 0 0 0 &mbox_db_rx 0 0 0 &mbox_db_rx 0 0 1>;
shmem = <&cpu_scp_scmi_a2p &cpu_scp_scmi_p2a>;
};
+
+ rse {
+ compatible = "arm,rse";
+ mbox-names = "tx", "rx";
+ mboxes = <&rse_mbox_db_tx 0 0 0>, <&rse_mbox_db_rx 0 0 0>;
+#if TARGET_FLAVOUR_FPGA
+ status = "disabled";
+#endif
+ };
+ };
+
+ dsu-pmu {
+ compatible = "arm,dsu-pmu";
+ cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
};
};
diff --git a/fdts/tc3.dts b/fdts/tc3.dts
index ffe3b6d..3b02f91 100644
--- a/fdts/tc3.dts
+++ b/fdts/tc3.dts
@@ -13,6 +13,9 @@
#define MHU_TX_ADDR 46040000 /* hex */
#define MHU_RX_ADDR 46140000 /* hex */
+#define RSE_MHU_TX_ADDR 49010000 /* hex */
+#define RSE_MHU_RX_ADDR 49110000 /* hex */
+
#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu"
#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a725-pmu"
#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x925-pmu"
@@ -74,11 +77,6 @@
status = "okay";
};
- dsu-pmu {
- compatible = "arm,dsu-pmu";
- cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
- };
-
ni-pmu {
compatible = "arm,ni-tower";
reg = <0x0 0x4f000000 0x0 0x4000000>;
diff --git a/fdts/tc4.dts b/fdts/tc4.dts
index 135d30a..8b73b49 100644
--- a/fdts/tc4.dts
+++ b/fdts/tc4.dts
@@ -17,6 +17,9 @@
#define MID_CPU_PMU_COMPATIBLE "arm,armv8-pmuv3"
#define BIG_CPU_PMU_COMPATIBLE "arm,armv8-pmuv3"
+#define RSE_MHU_TX_ADDR 49020000 /* hex */
+#define RSE_MHU_RX_ADDR 49030000 /* hex */
+
#define ETHERNET_ADDR 64000000
#define ETHERNET_INT 799
@@ -64,4 +67,8 @@
interrupt-names = "IRQAW";
iommus = <&smmu_700 0x200>;
};
+
+ dsu-pmu {
+ interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
};
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 737d07a..3a7e2eb 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -465,6 +465,11 @@
#define ID_AA64PFR2_EL1_MTEFAR_SHIFT U(8)
#define ID_AA64PFR2_EL1_MTEFAR_MASK ULL(0xf)
+#define ID_AA64PFR2_EL1_FPMR_SHIFT U(32)
+#define ID_AA64PFR2_EL1_FPMR_MASK ULL(0xf)
+
+#define FPMR_IMPLEMENTED ULL(0x1)
+
#define VDISR_EL2 S3_4_C12_C1_1
#define VSESR_EL2 S3_4_C5_C2_3
@@ -605,6 +610,7 @@
#define SCR_NSE_SHIFT U(62)
#define SCR_FGTEN2_BIT (UL(1) << 59)
#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT)
+#define SCR_EnFPM_BIT (ULL(1) << 50)
#define SCR_GPF_BIT (UL(1) << 48)
#define SCR_D128En_BIT (UL(1) << 47)
#define SCR_TWEDEL_SHIFT U(30)
@@ -1522,6 +1528,11 @@
******************************************************************************/
#define CLUSTERPWRDN_EL1 S3_0_c15_c3_6
+/*******************************************************************************
+ * FEAT_FPMR - Floating point Mode Register
+ ******************************************************************************/
+#define FPMR S3_3_C4_C4_2
+
/* CLUSTERPWRDN_EL1 register definitions */
#define DSU_CLUSTER_PWR_OFF 0
#define DSU_CLUSTER_PWR_ON 1
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 59188da..8bdc13c 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -142,6 +142,8 @@
* +----------------------------+
* | FEAT_LS64_ACCDATA |
* +----------------------------+
+ * | FEAT_FPMR |
+ * +----------------------------+
*/
__attribute__((always_inline))
@@ -284,6 +286,12 @@
ID_AA64MMFR3_EL1_D128_MASK, D128_IMPLEMENTED,
ENABLE_FEAT_D128)
+/* FEAT_FPMR */
+CREATE_FEATURE_FUNCS(feat_fpmr, id_aa64pfr2_el1, ID_AA64PFR2_EL1_FPMR_SHIFT,
+ ID_AA64PFR2_EL1_FPMR_MASK, FPMR_IMPLEMENTED,
+ ENABLE_FEAT_FPMR)
+
+
__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void)
{
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 119c428..3f3f14d 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -718,6 +718,8 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(fpmr, FPMR)
+
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
diff --git a/include/lib/el3_runtime/context_el1.h b/include/lib/el3_runtime/context_el1.h
index 7bc0235..7fe43c7 100644
--- a/include/lib/el3_runtime/context_el1.h
+++ b/include/lib/el3_runtime/context_el1.h
@@ -194,6 +194,9 @@
#define write_el1_ctx_common(ctx, reg, val) ((((ctx)->common).reg) \
= (uint64_t) (val))
+#define write_el1_ctx_common_sysreg128(ctx, reg, val) ((((ctx)->common).reg) \
+ = (sysreg_t) (val))
+
#if NS_TIMER_SWITCH
#define read_el1_ctx_arch_timer(ctx, reg) (((ctx)->arch_timer).reg)
#define write_el1_ctx_arch_timer(ctx, reg, val) ((((ctx)->arch_timer).reg) \
@@ -295,11 +298,11 @@
#if ENABLE_FEAT_THE
#define read_el1_ctx_the(ctx, reg) (((ctx)->the).reg)
-#define write_el1_ctx_the(ctx, reg, val) ((((ctx)->the).reg) \
- = (uint64_t) (val))
+#define write_el1_ctx_the_sysreg128(ctx, reg, val) ((((ctx)->the).reg) \
+ = (sysreg_t) (val))
#else
#define read_el1_ctx_the(ctx, reg) ULL(0)
-#define write_el1_ctx_the(ctx, reg, val)
+#define write_el1_ctx_the_sysreg128(ctx, reg, val)
#endif /* ENABLE_FEAT_THE */
#if ENABLE_FEAT_SCTLR2
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index 7374e39..f35a091 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -225,7 +225,7 @@
#define write_el2_ctx_common(ctx, reg, val) ((((ctx)->common).reg) \
= (uint64_t) (val))
-#define write_el2_ctx_sysreg128(ctx, reg, val) ((((ctx)->common).reg) \
+#define write_el2_ctx_common_sysreg128(ctx, reg, val) ((((ctx)->common).reg) \
= (sysreg_t) (val))
#if ENABLE_FEAT_MTE2
@@ -268,12 +268,12 @@
#define read_el2_ctx_vhe(ctx, reg) (((ctx)->vhe).reg)
#define write_el2_ctx_vhe(ctx, reg, val) ((((ctx)->vhe).reg) \
= (uint64_t) (val))
-
#define write_el2_ctx_vhe_sysreg128(ctx, reg, val) ((((ctx)->vhe).reg) \
- = (sysreg_t) (val))
+ = (sysreg_t) (val))
#else
#define read_el2_ctx_vhe(ctx, reg) ULL(0)
#define write_el2_ctx_vhe(ctx, reg, val)
+#define write_el2_ctx_vhe_sysreg128(ctx, reg, val)
#endif /* ENABLE_FEAT_VHE */
#if ENABLE_FEAT_RAS
diff --git a/include/lib/extensions/fpmr.h b/include/lib/extensions/fpmr.h
new file mode 100644
index 0000000..bc3ee9e
--- /dev/null
+++ b/include/lib/extensions/fpmr.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FPMR_H
+#define FPMR_H
+
+#include <context.h>
+
+#if ENABLE_FEAT_FPMR
+void fpmr_enable_per_world(per_world_context_t *per_world_ctx);
+#else
+static inline void fpmr_enable_per_world(per_world_context_t *per_world_ctx)
+{
+}
+#endif /* ENABLE_FEAT_FPMR */
+
+#endif /* FPMR_H */
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index 320fd90..4ff0ea5 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -75,6 +75,12 @@
check_erratum_ls cortex_x4, ERRATUM(2897503), CPU_REV(0, 1)
+workaround_reset_start cortex_x4, ERRATUM(2923985), ERRATA_X4_2923985
+ sysreg_bit_set CORTEX_X4_CPUACTLR4_EL1, (BIT(11) | BIT(10))
+workaround_reset_end cortex_x4, ERRATUM(2923985)
+
+check_erratum_ls cortex_x4, ERRATUM(2923985), CPU_REV(0, 1)
+
workaround_reset_start cortex_x4, ERRATUM(3076789), ERRATA_X4_3076789
sysreg_bit_set CORTEX_X4_CPUACTLR3_EL1, BIT(14)
sysreg_bit_set CORTEX_X4_CPUACTLR3_EL1, BIT(13)
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 4c20785..4a04a9d 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -843,6 +843,10 @@
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_2897503
+# Flag to apply erratum 2923985 workaround on reset. This erratum applies
+# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_X4_2923985
+
# Flag to apply erratum 3076789 workaround on reset. This erratum applies
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_3076789
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 4ae1306..ca5e047 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -28,6 +28,7 @@
#include <lib/extensions/brbe.h>
#include <lib/extensions/debug_v8p9.h>
#include <lib/extensions/fgt2.h>
+#include <lib/extensions/fpmr.h>
#include <lib/extensions/mpam.h>
#include <lib/extensions/pmuv3.h>
#include <lib/extensions/sme.h>
@@ -291,6 +292,13 @@
scr_el3 |= SCR_D128En_BIT;
}
+ if (is_feat_fpmr_supported()) {
+ /* Set the EnFPM bit in SCR_EL3 to enable access to FPMR
+ * register.
+ */
+ scr_el3 |= SCR_EnFPM_BIT;
+ }
+
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
/* Initialize EL2 context registers */
@@ -714,6 +722,10 @@
if (is_feat_mpam_supported()) {
mpam_enable_per_world(&per_world_context[CPU_CONTEXT_NS]);
}
+
+ if (is_feat_fpmr_supported()) {
+ fpmr_enable_per_world(&per_world_context[CPU_CONTEXT_NS]);
+ }
}
#endif /* IMAGE_BL31 */
@@ -1352,8 +1364,8 @@
write_el2_ctx_common(ctx, vpidr_el2, read_vpidr_el2());
write_el2_ctx_common(ctx, vtcr_el2, read_vtcr_el2());
- write_el2_ctx_sysreg128(ctx, ttbr0_el2, read_ttbr0_el2());
- write_el2_ctx_sysreg128(ctx, vttbr_el2, read_vttbr_el2());
+ write_el2_ctx_common_sysreg128(ctx, ttbr0_el2, read_ttbr0_el2());
+ write_el2_ctx_common_sysreg128(ctx, vttbr_el2, read_vttbr_el2());
}
static void el2_sysregs_context_restore_common(el2_sysregs_t *ctx)
@@ -1679,15 +1691,12 @@
write_el1_ctx_common(ctx, csselr_el1, read_csselr_el1());
write_el1_ctx_common(ctx, sp_el1, read_sp_el1());
write_el1_ctx_common(ctx, esr_el1, read_esr_el1());
- write_el1_ctx_common(ctx, ttbr0_el1, read_ttbr0_el1());
- write_el1_ctx_common(ctx, ttbr1_el1, read_ttbr1_el1());
write_el1_ctx_common(ctx, mair_el1, read_mair_el1());
write_el1_ctx_common(ctx, amair_el1, read_amair_el1());
write_el1_ctx_common(ctx, actlr_el1, read_actlr_el1());
write_el1_ctx_common(ctx, tpidr_el1, read_tpidr_el1());
write_el1_ctx_common(ctx, tpidr_el0, read_tpidr_el0());
write_el1_ctx_common(ctx, tpidrro_el0, read_tpidrro_el0());
- write_el1_ctx_common(ctx, par_el1, read_par_el1());
write_el1_ctx_common(ctx, far_el1, read_far_el1());
write_el1_ctx_common(ctx, afsr0_el1, read_afsr0_el1());
write_el1_ctx_common(ctx, afsr1_el1, read_afsr1_el1());
@@ -1696,6 +1705,10 @@
write_el1_ctx_common(ctx, mdccint_el1, read_mdccint_el1());
write_el1_ctx_common(ctx, mdscr_el1, read_mdscr_el1());
+ write_el1_ctx_common_sysreg128(ctx, par_el1, read_par_el1());
+ write_el1_ctx_common_sysreg128(ctx, ttbr0_el1, read_ttbr0_el1());
+ write_el1_ctx_common_sysreg128(ctx, ttbr1_el1, read_ttbr1_el1());
+
if (CTX_INCLUDE_AARCH32_REGS) {
/* Save Aarch32 registers */
write_el1_ctx_aarch32(ctx, spsr_abt, read_spsr_abt());
@@ -1760,8 +1773,8 @@
}
if (is_feat_the_supported()) {
- write_el1_ctx_the(ctx, rcwmask_el1, read_rcwmask_el1());
- write_el1_ctx_the(ctx, rcwsmask_el1, read_rcwsmask_el1());
+ write_el1_ctx_the_sysreg128(ctx, rcwmask_el1, read_rcwmask_el1());
+ write_el1_ctx_the_sysreg128(ctx, rcwsmask_el1, read_rcwsmask_el1());
}
if (is_feat_sctlr2_supported()) {
diff --git a/lib/extensions/fpmr/fpmr.c b/lib/extensions/fpmr/fpmr.c
new file mode 100644
index 0000000..8e37e7a
--- /dev/null
+++ b/lib/extensions/fpmr/fpmr.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/extensions/fpmr.h>
+
+void fpmr_enable_per_world(per_world_context_t *per_world_ctx)
+{
+ u_register_t reg;
+
+ /* Disable Floating point Trap in CPTR_EL3. */
+ reg = per_world_ctx->ctx_cptr_el3;
+ reg &= ~TFP_BIT;
+ per_world_ctx->ctx_cptr_el3 = reg;
+}
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index bc31a2f..01a0395 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -12,17 +12,26 @@
BUILD_DIR = $(BUILD_PLAT)/romlib
LIB_DIR = $(BUILD_PLAT)/lib
WRAPPER_DIR = $(BUILD_PLAT)/libwrapper
-LIBS = $(LIB_DIR)/libmbedtls.a $(LIB_DIR)/libfdt.a $(LIB_DIR)/libc.a
+LIBS = $(LIB_DIR)/libfdt.a $(LIB_DIR)/libc.a
INC = $(INCLUDES:-I%=-I../../%)
PPFLAGS = $(INC) $(DEFINES) -P -x assembler-with-cpp -D__LINKER__ -MD -MP -MT $(BUILD_DIR)/romlib.ld
OBJS = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o
MAPFILE = $(BUILD_PLAT)/romlib/romlib.map
-ifneq ($(PLAT_DIR),)
- WRAPPER_SOURCES = $(sort $(shell $(ROMLIB_GEN) genwrappers -b $\
- $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i))
+PROCESSED_JMPTBL = ../../$(PLAT_DIR)/jmptbl.i
+
+# Determine if mbedtls is needed
+ifneq ($(filter $(CRYPTO_SUPPORT),1 2 3),)
+ PROCESSED_JMPTBL = $(BUILD_DIR)/jmptbl_processed.i
+ $(shell mkdir -p $(BUILD_DIR) && cat ../../$(PLAT_DIR)/jmptbl.i ../../$(PLAT_DIR)/jmptbl_mbedtls.i > $(BUILD_DIR)/jmptbl_processed.i)
+ LIBS += $(LIB_DIR)/libmbedtls.a
+endif
- WRAPPER_OBJS = $(WRAPPER_SOURCES:.s=.o)
+ifneq ($(PLAT_DIR),)
+ # Generate wrapper sources and objects
+ WRAPPER_SOURCES = $(sort $(shell $(ROMLIB_GEN) genwrappers -b $\
+ $(WRAPPER_DIR) --list $(PROCESSED_JMPTBL)))
+ WRAPPER_OBJS = $(WRAPPER_SOURCES:.s=.o)
endif
LDFLAGS := -Wl,--gc-sections -nostdlib
@@ -69,21 +78,21 @@
$(s)echo " AR $@"
$(q)$(aarch64-ar) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
-$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i | $$(@D)/
+$(BUILD_DIR)/jmptbl.i: $(PROCESSED_JMPTBL) | $$(@D)/
$(s)echo " PRE $@"
$(q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $<
-$(WRAPPER_SOURCES) $&: $(BUILD_DIR)/jmptbl.i | $$(@D)/
+$(WRAPPER_SOURCES) $&: $(PROCESSED_JMPTBL) | $$(@D)/
$(s)echo " WRP $<"
$(q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $<
$(WRAPPER_OBJS): $(WRAPPER_DIR)/%.o: $(WRAPPER_DIR)/%.s | $$(@D)/
-$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i | $$(@D)/
+$(BUILD_DIR)/jmptbl.s: $(PROCESSED_JMPTBL) | $$(@D)/
$(s)echo " TBL $@"
$(q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $<
-$(BUILD_DIR)/romlib.ldflags: ../../$(PLAT_DIR)/jmptbl.i | $$(@D)/
+$(BUILD_DIR)/romlib.ldflags: $(PROCESSED_JMPTBL) | $$(@D)/
$(s)echo " LDFLAGS $@"
$(q)$(ROMLIB_GEN) link-flags $< > $@
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 57609d5..a1db0b8 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -408,6 +408,9 @@
# if FEAT_BRBE is implemented.
ENABLE_BRBE_FOR_NS ?= 0
+# Flag to enable Floating point exception Mode Register Feature (FEAT_FPMR)
+ENABLE_FEAT_FPMR ?= 0
+
#----
# 9.3
#----
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index 077283e..a23de73 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -37,28 +37,5 @@
fdt fdt_get_alias
fdt fdt_node_offset_by_phandle
fdt fdt_add_subnode
-mbedtls mbedtls_asn1_get_alg
-mbedtls mbedtls_asn1_get_alg_null
-mbedtls mbedtls_asn1_get_bitstring_null
-mbedtls mbedtls_asn1_get_bool
-mbedtls mbedtls_asn1_get_int
-mbedtls mbedtls_asn1_get_len
-mbedtls mbedtls_asn1_get_tag
-mbedtls mbedtls_free
-mbedtls mbedtls_md
-mbedtls mbedtls_md_get_size
-mbedtls mbedtls_memory_buffer_alloc_init
-mbedtls mbedtls_oid_get_md_alg
-mbedtls mbedtls_oid_get_numeric_string
-mbedtls mbedtls_oid_get_pk_alg
-mbedtls mbedtls_oid_get_sig_alg
-mbedtls mbedtls_pk_free
-mbedtls mbedtls_pk_init
-mbedtls mbedtls_pk_parse_subpubkey
-mbedtls mbedtls_pk_verify_ext
-mbedtls mbedtls_platform_set_snprintf
-mbedtls mbedtls_x509_get_rsassa_pss_params
-mbedtls mbedtls_x509_get_sig_alg
-mbedtls mbedtls_md_info_from_type
c exit
c atexit
diff --git a/plat/arm/board/fvp/jmptbl_mbedtls.i b/plat/arm/board/fvp/jmptbl_mbedtls.i
new file mode 100644
index 0000000..6e1f017
--- /dev/null
+++ b/plat/arm/board/fvp/jmptbl_mbedtls.i
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform-specific ROMLIB MbedTLS functions can be added here.
+# During the build process, this file is appended to jmptbl.i
+# if MbedTLS support is required.
+#
+# Format:
+# lib function [patch]
+# Example:
+# mbedtls mbedtls_asn1_get_alg
+# mbedtls mbedtls_asn1_get_alg_null patch
+
+mbedtls mbedtls_asn1_get_alg
+mbedtls mbedtls_asn1_get_alg_null
+mbedtls mbedtls_asn1_get_bitstring_null
+mbedtls mbedtls_asn1_get_bool
+mbedtls mbedtls_asn1_get_int
+mbedtls mbedtls_asn1_get_len
+mbedtls mbedtls_asn1_get_tag
+mbedtls mbedtls_free
+mbedtls mbedtls_md
+mbedtls mbedtls_md_get_size
+mbedtls mbedtls_memory_buffer_alloc_init
+mbedtls mbedtls_oid_get_md_alg
+mbedtls mbedtls_oid_get_numeric_string
+mbedtls mbedtls_oid_get_pk_alg
+mbedtls mbedtls_oid_get_sig_alg
+mbedtls mbedtls_pk_free
+mbedtls mbedtls_pk_init
+mbedtls mbedtls_pk_parse_subpubkey
+mbedtls mbedtls_pk_verify_ext
+mbedtls mbedtls_platform_set_snprintf
+mbedtls mbedtls_x509_get_rsassa_pss_params
+mbedtls mbedtls_x509_get_sig_alg
+mbedtls mbedtls_md_info_from_type
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 1340a65..3b638e4 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -57,6 +57,7 @@
ENABLE_BRBE_FOR_NS := 2
ENABLE_TRBE_FOR_NS := 2
ENABLE_FEAT_D128 := 2
+ ENABLE_FEAT_FPMR := 2
endif
ENABLE_SYS_REG_TRACE_FOR_NS := 2
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 327a345..a62661d 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -36,28 +36,5 @@
fdt fdt_node_offset_by_phandle
fdt fdt_subnode_offset
fdt fdt_add_subnode
-mbedtls mbedtls_asn1_get_alg
-mbedtls mbedtls_asn1_get_alg_null
-mbedtls mbedtls_asn1_get_bitstring_null
-mbedtls mbedtls_asn1_get_bool
-mbedtls mbedtls_asn1_get_int
-mbedtls mbedtls_asn1_get_len
-mbedtls mbedtls_asn1_get_tag
-mbedtls mbedtls_free
-mbedtls mbedtls_md
-mbedtls mbedtls_md_get_size
-mbedtls mbedtls_memory_buffer_alloc_init
-mbedtls mbedtls_oid_get_md_alg
-mbedtls mbedtls_oid_get_numeric_string
-mbedtls mbedtls_oid_get_pk_alg
-mbedtls mbedtls_oid_get_sig_alg
-mbedtls mbedtls_pk_free
-mbedtls mbedtls_pk_init
-mbedtls mbedtls_pk_parse_subpubkey
-mbedtls mbedtls_pk_verify_ext
-mbedtls mbedtls_platform_set_snprintf
-mbedtls mbedtls_x509_get_rsassa_pss_params
-mbedtls mbedtls_x509_get_sig_alg
-mbedtls mbedtls_md_info_from_type
c exit
c atexit
diff --git a/plat/arm/board/juno/jmptbl_mbedtls.i b/plat/arm/board/juno/jmptbl_mbedtls.i
new file mode 100644
index 0000000..6e1f017
--- /dev/null
+++ b/plat/arm/board/juno/jmptbl_mbedtls.i
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform-specific ROMLIB MbedTLS functions can be added here.
+# During the build process, this file is appended to jmptbl.i
+# if MbedTLS support is required.
+#
+# Format:
+# lib function [patch]
+# Example:
+# mbedtls mbedtls_asn1_get_alg
+# mbedtls mbedtls_asn1_get_alg_null patch
+
+mbedtls mbedtls_asn1_get_alg
+mbedtls mbedtls_asn1_get_alg_null
+mbedtls mbedtls_asn1_get_bitstring_null
+mbedtls mbedtls_asn1_get_bool
+mbedtls mbedtls_asn1_get_int
+mbedtls mbedtls_asn1_get_len
+mbedtls mbedtls_asn1_get_tag
+mbedtls mbedtls_free
+mbedtls mbedtls_md
+mbedtls mbedtls_md_get_size
+mbedtls mbedtls_memory_buffer_alloc_init
+mbedtls mbedtls_oid_get_md_alg
+mbedtls mbedtls_oid_get_numeric_string
+mbedtls mbedtls_oid_get_pk_alg
+mbedtls mbedtls_oid_get_sig_alg
+mbedtls mbedtls_pk_free
+mbedtls mbedtls_pk_init
+mbedtls mbedtls_pk_parse_subpubkey
+mbedtls mbedtls_pk_verify_ext
+mbedtls mbedtls_platform_set_snprintf
+mbedtls mbedtls_x509_get_rsassa_pss_params
+mbedtls mbedtls_x509_get_sig_alg
+mbedtls mbedtls_md_info_from_type
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
index 9adf09a..48ca16c 100644
--- a/plat/arm/board/tc/include/tc_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -82,6 +82,9 @@
endfunc TC_HANDLER(3)
func TC_HANDLER(4)
+ mov x9, lr
+ bl enable_dsu_pmu_el1_access
+ mov lr, x9
ret
endfunc TC_HANDLER(4)
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 3178c06..759c85d 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -230,18 +230,17 @@
# Add the HW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG}))
+$(info Including rse_comms.mk)
+include drivers/arm/rse/rse_comms.mk
+
+BL1_SOURCES += ${RSE_COMMS_SOURCES}
+BL2_SOURCES += ${RSE_COMMS_SOURCES}
+BL31_SOURCES += ${RSE_COMMS_SOURCES}
+
# Include Measured Boot makefile before any Crypto library makefile.
# Crypto library makefile may need default definitions of Measured Boot build
# flags present in Measured Boot makefile.
-$(info Including rse_comms.mk)
ifeq (${MEASURED_BOOT},1)
- $(info Including rse_comms.mk)
- include drivers/arm/rse/rse_comms.mk
-
- BL1_SOURCES += ${RSE_COMMS_SOURCES}
- BL2_SOURCES += ${RSE_COMMS_SOURCES}
- PLAT_INCLUDES += -Iinclude/lib/psa
-
ifeq (${DICE_PROTECTION_ENVIRONMENT},1)
$(info Including qcbor.mk)
include drivers/measured_boot/rse/qcbor.mk
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 801872a..3fb0214 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -25,6 +25,10 @@
#include <psa/crypto_types.h>
#include <psa/crypto_values.h>
#endif /* PLATFORM_TEST_TFM_TESTSUITE */
+#include <psa/error.h>
+
+#include <drivers/arm/rse_comms.h>
+#include <plat/common/platform.h>
#ifdef PLATFORM_TEST_TFM_TESTSUITE
/*
@@ -190,6 +194,12 @@
plat_arm_secure_wdt_start();
arm_bl31_plat_runtime_setup();
+
+ /* Initialise RSE communication channel */
+ status = rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE, PLAT_RSE_AP_RCV_MHU_BASE);
+ if (status != PSA_SUCCESS) {
+ ERROR("Failed to initialize RSE communication channel - psa_status = %d\n", status);
+ }
}
void bl31_plat_runtime_setup(void)
diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
index fed14f7..1ecfdb9 100644
--- a/plat/arm/board/tc/tc_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -40,6 +40,7 @@
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
TC_FLASH0_RO,
+ ARM_V2M_MAP_MEM_PROTECT,
TC_MAP_DEVICE,
TC_MAP_NS_DRAM1,
#if defined(SPD_spmd)
@@ -65,6 +66,7 @@
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
V2M_MAP_IOFPGA,
+ ARM_V2M_MAP_MEM_PROTECT,
TC_MAP_DEVICE,
PLAT_DTB_DRAM_NS,
#if SPM_MM
diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h
index 5b45d92..630a3f0 100644
--- a/plat/mediatek/mt8196/include/platform_def.h
+++ b/plat/mediatek/mt8196/include/platform_def.h
@@ -128,6 +128,14 @@
#define VDOSYS1_BASE (IO_PHYS + 0x0C100000)
/*******************************************************************************
+ * DP related constants
+ ******************************************************************************/
+#define EDP_SEC_BASE (IO_PHYS + 0x2EC50000)
+#define DP_SEC_BASE (IO_PHYS + 0x2EC10000)
+#define EDP_SEC_SIZE (0x1000)
+#define DP_SEC_SIZE (0x1000)
+
+/*******************************************************************************
* EMI MPU related constants
*******************************************************************************/
#define EMI_MPU_BASE (IO_PHYS + 0x00428000)
diff --git a/plat/mediatek/mt8196/plat_mmap.c b/plat/mediatek/mt8196/plat_mmap.c
index f7f819a..3d7be87 100644
--- a/plat/mediatek/mt8196/plat_mmap.c
+++ b/plat/mediatek/mt8196/plat_mmap.c
@@ -17,6 +17,10 @@
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(CPU_IDLE_SRAM_BASE, CPU_IDLE_SRAM_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DP_SEC_BASE, DP_SEC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(EDP_SEC_BASE, EDP_SEC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
{ 0 }
};
DECLARE_MTK_MMAP_REGIONS(plat_mmap);
diff --git a/plat/mediatek/mt8196/platform.mk b/plat/mediatek/mt8196/platform.mk
index fede717..062735b 100644
--- a/plat/mediatek/mt8196/platform.mk
+++ b/plat/mediatek/mt8196/platform.mk
@@ -25,6 +25,7 @@
MODULES-y += $(MTK_PLAT)/common
MODULES-y += $(MTK_PLAT)/lib/mtk_init
MODULES-y += $(MTK_PLAT)/lib/pm
+MODULES-y += $(MTK_PLAT)/drivers/dp
MODULES-y += $(MTK_PLAT)/drivers/mcusys
MODULES-y += $(MTK_PLAT)/drivers/timer
MODULES-y += $(MTK_PLAT)/helpers
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index ed95bc6..51497bd 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -8,6 +8,7 @@
include common/fdt_wrappers.mk
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -I${PLAT_QEMU_COMMON_PATH}/ \
-I${PLAT_QEMU_COMMON_PATH}/include \
-I${PLAT_QEMU_PATH}/include \
-Iinclude/common/tbbr
@@ -65,7 +66,8 @@
${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \
common/desc_image_load.c \
- common/fdt_fixup.c
+ common/fdt_fixup.c \
+ ${FDT_WRAPPERS_SOURCES}
BL31_SOURCES += ${QEMU_CPU_LIBS} \
lib/semihosting/semihosting.c \
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index c96e4b9..71f9cf7 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -22,9 +22,6 @@
#include <lib/transfer_list.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
-#if ENABLE_RME
-#include <qemu_pas_def.h>
-#endif
#include "qemu_private.h"
@@ -84,8 +81,9 @@
#endif
int ret;
void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
+ void *dst = plat_qemu_dt_runtime_address();
- ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
+ ret = fdt_open_into(fdt, dst, PLAT_QEMU_DT_MAX_SIZE);
if (ret < 0) {
ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
return;
@@ -150,54 +148,6 @@
#endif
}
-#if ENABLE_RME
-static void bl2_plat_gpt_setup(void)
-{
- /*
- * The GPT library might modify the gpt regions structure to optimize
- * the layout, so the array cannot be constant.
- */
- pas_region_t pas_regions[] = {
- QEMU_PAS_ROOT,
- QEMU_PAS_SECURE,
- QEMU_PAS_GPTS,
- QEMU_PAS_NS0,
- QEMU_PAS_REALM,
- QEMU_PAS_NS1,
- };
-
- /*
- * Initialize entire protected space to GPT_GPI_ANY. With each L0 entry
- * covering 1GB (currently the only supported option), then covering
- * 256TB of RAM (48-bit PA) would require a 2MB L0 region. At the
- * moment we use a 8KB table, which covers 1TB of RAM (40-bit PA).
- */
- if (gpt_init_l0_tables(GPCCR_PPS_1TB, PLAT_QEMU_L0_GPT_BASE,
- PLAT_QEMU_L0_GPT_SIZE +
- PLAT_QEMU_GPT_BITLOCK_SIZE) < 0) {
- ERROR("gpt_init_l0_tables() failed!\n");
- panic();
- }
-
- /* Carve out defined PAS ranges. */
- if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
- PLAT_QEMU_L1_GPT_BASE,
- PLAT_QEMU_L1_GPT_SIZE,
- pas_regions,
- (unsigned int)(sizeof(pas_regions) /
- sizeof(pas_region_t))) < 0) {
- ERROR("gpt_init_pas_l1_tables() failed!\n");
- panic();
- }
-
- INFO("Enabling Granule Protection Checks\n");
- if (gpt_enable() < 0) {
- ERROR("gpt_enable() failed!\n");
- panic();
- }
-}
-#endif
-
void bl2_plat_arch_setup(void)
{
const mmap_region_t bl_regions[] = {
@@ -220,9 +170,6 @@
/* BL2 runs in EL3 when RME enabled. */
assert(is_feat_rme_present());
enable_mmu_el3(0);
-
- /* Initialise and enable granule protection after MMU. */
- bl2_plat_gpt_setup();
#else /* ENABLE_RME */
#ifdef __aarch64__
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index 0a70cc2..e502e7b 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -11,6 +11,16 @@
#include <lib/gpt_rme/gpt_rme.h>
#include <lib/transfer_list.h>
#include <plat/common/platform.h>
+#if ENABLE_RME
+#ifdef PLAT_qemu
+#include <qemu_pas_def.h>
+#elif PLAT_qemu_sbsa
+#include <qemu_sbsa_pas_def.h>
+#endif /* PLAT_qemu */
+#endif /* ENABLE_RME */
+#ifdef PLAT_qemu_sbsa
+#include <sbsa_platform.h>
+#endif
#include "qemu_private.h"
@@ -63,7 +73,7 @@
/* Platform names have to be lowercase. */
#ifdef PLAT_qemu_sbsa
- sip_svc_init();
+ sbsa_platform_init();
#endif
/*
@@ -110,6 +120,100 @@
}
}
+#if ENABLE_RME
+#if PLAT_qemu
+/*
+ * The GPT library might modify the gpt regions structure to optimize
+ * the layout, so the array cannot be constant.
+ */
+static pas_region_t pas_regions[] = {
+ QEMU_PAS_ROOT,
+ QEMU_PAS_SECURE,
+ QEMU_PAS_GPTS,
+ QEMU_PAS_NS0,
+ QEMU_PAS_REALM,
+ QEMU_PAS_NS1,
+};
+
+static inline void bl31_adjust_pas_regions(void) {}
+#elif PLAT_qemu_sbsa
+/*
+ * The GPT library might modify the gpt regions structure to optimize
+ * the layout, so the array cannot be constant.
+ */
+static pas_region_t pas_regions[] = {
+ QEMU_PAS_ROOT,
+ QEMU_PAS_SECURE,
+ QEMU_PAS_GPTS,
+ QEMU_PAS_REALM,
+ QEMU_PAS_NS0,
+};
+
+static void bl31_adjust_pas_regions(void)
+{
+ uint64_t base_addr = 0, total_size = 0;
+ struct platform_memory_data data;
+ uint32_t node;
+
+ /*
+ * The amount of memory supported by the SBSA platform is dynamic
+ * and dependent on user input. Since the configuration of the GPT
+ * needs to reflect the system memory, QEMU_PAS_NS0 needs to be set
+ * based on the information found in the device tree.
+ */
+
+ for (node = 0; node < sbsa_platform_num_memnodes(); node++) {
+ data = sbsa_platform_memory_node(node);
+
+ if (data.nodeid == 0) {
+ base_addr = data.addr_base;
+ }
+
+ total_size += data.addr_size;
+ }
+
+ /* Index '4' correspond to QEMU_PAS_NS0, see pas_regions[] above */
+ pas_regions[4].base_pa = base_addr;
+ pas_regions[4].size = total_size;
+}
+#endif /* PLAT_qemu */
+
+static void bl31_plat_gpt_setup(void)
+{
+ /*
+ * Initialize entire protected space to GPT_GPI_ANY. With each L0 entry
+ * covering 1GB (currently the only supported option), then covering
+ * 256TB of RAM (48-bit PA) would require a 2MB L0 region. At the
+ * moment we use a 8KB table, which covers 1TB of RAM (40-bit PA).
+ */
+ if (gpt_init_l0_tables(PLATFORM_GPCCR_PPS, PLAT_QEMU_L0_GPT_BASE,
+ PLAT_QEMU_L0_GPT_SIZE +
+ PLAT_QEMU_GPT_BITLOCK_SIZE) < 0) {
+ ERROR("gpt_init_l0_tables() failed!\n");
+ panic();
+ }
+
+ bl31_adjust_pas_regions();
+
+ /* Carve out defined PAS ranges. */
+ if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
+ PLAT_QEMU_L1_GPT_BASE,
+ PLAT_QEMU_L1_GPT_SIZE,
+ pas_regions,
+ (unsigned int)(sizeof(pas_regions) /
+ sizeof(pas_region_t))) < 0) {
+ ERROR("gpt_init_pas_l1_tables() failed!\n");
+ panic();
+ }
+
+ INFO("Enabling Granule Protection Checks\n");
+ if (gpt_enable() < 0) {
+ ERROR("gpt_enable() failed!\n");
+ panic();
+ }
+}
+#endif
+
void bl31_plat_arch_setup(void)
{
const mmap_region_t bl_regions[] = {
@@ -131,6 +235,9 @@
enable_mmu_el3(0);
#if ENABLE_RME
+ /* Initialise and enable granule protection after MMU. */
+ bl31_plat_gpt_setup();
+
/*
* Initialise Granule Protection library and enable GPC for the primary
* processor. The tables have already been initialized by a previous BL
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 9ccb2c8..0bfb126 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -16,6 +16,9 @@
#if ENABLE_RME
#include <services/rmm_core_manifest.h>
#endif
+#ifdef PLAT_qemu_sbsa
+#include <sbsa_platform.h>
+#endif
#include <plat/common/platform.h>
#include "qemu_private.h"
@@ -224,12 +227,42 @@
return (size_t)RMM_SHARED_SIZE;
}
+#ifdef PLAT_qemu
+static uint32_t plat_get_num_memnodes(void)
+{
+ return 1;
+}
+
+static void plat_get_memory_node(int index, struct ns_dram_bank *bank_ptr)
+{
+ (void) index;
+ bank_ptr->base = NS_DRAM0_BASE;
+ bank_ptr->size = NS_DRAM0_SIZE;
+}
+#elif PLAT_qemu_sbsa
+static uint32_t plat_get_num_memnodes(void)
+{
+ return sbsa_platform_num_memnodes();
+}
+
+static void plat_get_memory_node(int index, struct ns_dram_bank *bank_ptr)
+{
+ struct platform_memory_data data = {0, 0, 0};
+
+ if (index < sbsa_platform_num_memnodes()) {
+ data = sbsa_platform_memory_node(index);
+ }
+
+ bank_ptr->base = data.addr_base;
+ bank_ptr->size = data.addr_size;
+}
+#endif /* PLAT_qemu */
+
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
+ int i, last;
uint64_t checksum;
- uintptr_t base;
- uint64_t size;
- size_t num_banks = 1;
+ size_t num_banks = plat_get_num_memnodes();
size_t num_consoles = 1;
struct ns_dram_bank *bank_ptr;
struct console_info *console_ptr;
@@ -300,11 +333,28 @@
/* Calculate checksum of plat_dram structure */
checksum = num_banks + (uint64_t)bank_ptr;
- base = NS_DRAM0_BASE;
- size = NS_DRAM0_SIZE;
- bank_ptr[0].base = base;
- bank_ptr[0].size = size;
- checksum += base + size;
+ /*
+ * In the TF-A, NUMA nodes (if present) are stored in descending
+ * order, i.e:
+ *
+ * INFO: RAM 0: node-id: 1, address: 0x10080000000 - 0x101ffffffff
+ * INFO: RAM 1: node-id: 0, address: 0x10043000000 - 0x1007fffffff
+ *
+ * The RMM expects the memory banks to be presented in ascending order:
+ *
+ * INFO: RAM 1: node-id: 0, address: 0x10043000000 - 0x1007fffffff
+ * INFO: RAM 0: node-id: 1, address: 0x10080000000 - 0x101ffffffff
+ *
+ * As such, go through the NUMA nodes one by one and fill out
+ * @bank_ptr[] starting from the end. When NUMA nodes are not present
+ * there is only one memory bank and none of the above matters.
+ */
+ last = num_banks - 1;
+ for (i = 0; i < num_banks; i++) {
+ plat_get_memory_node(i, &bank_ptr[last]);
+ checksum += bank_ptr[last].base + bank_ptr[last].size;
+ last--;
+ }
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;
@@ -332,3 +382,25 @@
return 0;
}
#endif /* ENABLE_RME */
+
+/**
+ * plat_qemu_dt_runtime_address() - Get the final DT location in RAM
+ *
+ * When support is enabled on SBSA, the device tree is relocated from its
+ * original place at the beginning of the NS RAM to after the RMM. This
+ * function returns the address of the final location in RAM of the device
+ * tree. See function update_dt() in qemu_bl2_setup.c
+ *
+ * Return: The address of the final location in RAM of the device tree
+ */
+#if (ENABLE_RME && PLAT_qemu_sbsa)
+void *plat_qemu_dt_runtime_address(void)
+{
+ return (void *)(uintptr_t)PLAT_QEMU_DT_BASE;
+}
+#else
+void *plat_qemu_dt_runtime_address(void)
+{
+ return (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
+}
+#endif /* (ENABLE_RME && PLAT_qemu_sbsa) */
diff --git a/plat/qemu/common/qemu_private.h b/plat/qemu/common/qemu_private.h
index 25b14e2..046cb78 100644
--- a/plat/qemu/common/qemu_private.h
+++ b/plat/qemu/common/qemu_private.h
@@ -16,11 +16,9 @@
uintptr_t load_addr);
unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
const mmap_region_t *plat_qemu_get_mmap(void);
+void *plat_qemu_dt_runtime_address(void);
void qemu_console_init(void);
-#ifdef PLAT_qemu_sbsa
-void sip_svc_init(void);
-#endif
void plat_qemu_gic_init(void);
void qemu_pwr_gic_on_finish(void);
diff --git a/plat/qemu/qemu/include/qemu_pas_def.h b/plat/qemu/qemu/include/qemu_pas_def.h
index bcbea21..30934f0 100644
--- a/plat/qemu/qemu/include/qemu_pas_def.h
+++ b/plat/qemu/qemu/include/qemu_pas_def.h
@@ -102,6 +102,9 @@
QEMU_PAS_RMM_SHARED_SIZE, \
GPT_GPI_REALM)
+/* Cover 1TB with L0GTP */
+#define PLATFORM_GPCCR_PPS GPCCR_PPS_1TB
+
/* GPT Configuration options */
#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 0d4cdb8..70e9faf 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -115,8 +115,7 @@
include drivers/auth/mbedtls/mbedtls_crypto.mk
endif
-BL2_SOURCES += ${FDT_WRAPPERS_SOURCES} \
- common/uuid.c
+BL2_SOURCES += common/uuid.c
ifeq ($(add-lib-optee),yes)
BL2_SOURCES += lib/optee/optee_utils.c
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index d230095..06e8abf 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -66,6 +66,9 @@
*/
#define PLAT_MAX_MEM_NODES 128
+/* Where QEMU starts the NS RAM */
+#define PLAT_QEMU_DRAM0_BASE 0x10000000000ULL
+
/*
* Partition memory into secure ROM, non-secure DRAM, secure "SRAM",
* and secure DRAM.
@@ -73,7 +76,12 @@
#define SEC_ROM_BASE 0x00000000
#define SEC_ROM_SIZE 0x00020000
-#define NS_DRAM0_BASE 0x10000000000ULL
+/*
+ * When the RME extension is enabled, the base of the NS RAM is shifted after
+ * RMM.
+ */
+#define NS_DRAM0_BASE (PLAT_QEMU_DRAM0_BASE + \
+ NS_DRAM0_BASE_OFFSET)
#define NS_DRAM0_SIZE 0x00020000000
#define SEC_SRAM_BASE 0x20000000
@@ -121,7 +129,8 @@
#define BL1_RO_BASE SEC_ROM_BASE
#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
#define BL1_RW_BASE (BL1_RW_LIMIT - BL1_SIZE)
-#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE - \
+ RME_GPT_DRAM_SIZE)
/*
* BL2 specific defines.
@@ -139,7 +148,7 @@
* Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
* current BL3-1 debug size plus a little space for growth.
*/
-#define BL31_SIZE 0x300000
+#define BL31_SIZE 0x400000
#define BL31_BASE (BL31_LIMIT - BL31_SIZE)
#define BL31_LIMIT (BL1_RW_BASE)
#define BL31_PROGBITS_LIMIT BL1_RW_BASE
@@ -154,8 +163,8 @@
#define BL32_SRAM_LIMIT BL2_BASE
#define BL32_MEM_BASE BL_RAM_BASE
-#define BL32_MEM_SIZE (BL_RAM_SIZE - BL1_SIZE - \
- BL2_SIZE - BL31_SIZE)
+#define BL32_MEM_SIZE (BL_RAM_SIZE - RME_GPT_DRAM_SIZE - \
+ BL1_SIZE - BL2_SIZE - BL31_SIZE)
#define BL32_BASE BL32_SRAM_BASE
#define BL32_LIMIT BL32_SRAM_LIMIT
@@ -167,6 +176,9 @@
#if SPM_MM
#define MAX_MMAP_REGIONS 12
#define MAX_XLAT_TABLES 12
+#elif ENABLE_RME
+#define MAX_MMAP_REGIONS 14
+#define MAX_XLAT_TABLES 14
#else
#define MAX_MMAP_REGIONS 11
#define MAX_XLAT_TABLES 11
@@ -205,7 +217,7 @@
#define QEMU_FLASH1_SIZE 0x10000000
#define PLAT_QEMU_FIP_BASE BL1_SIZE
-#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
+#define PLAT_QEMU_FIP_MAX_SIZE (QEMU_FLASH0_SIZE - BL1_SIZE)
/* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */
#define DEVICE0_BASE 0x40000000
@@ -377,4 +389,105 @@
#define QEMU_PRI_BITS 2
#define PLAT_SP_PRI 0x20
+#if !ENABLE_RME
+#define RME_GPT_DRAM_SIZE 0
+#define NS_DRAM0_BASE_OFFSET 0
+#else /* !ENABLE_RME */
+/*
+ * SBSA RAM starts at 1TB and we support up to 1TB of RAM. As such we
+ * have 2TB of physical address space to cover. Since the GPT size can be
+ * 4GB, 64GB, 1TB, 4TB and so on, we need to select 4GB. Note that it is
+ * possible to support more than 1TB of RAM but that will take more room in
+ * secure memory due to the L1 GPTES. See PLAT_QEMU_L1_GPT_SIZE for details.
+ *
+ * 4TB / 1GB == 4096 GPTEs
+ * 4096 * 8 (bytes per GPTE) == 32768 i.e 8 pages
+ */
+#define PLAT_QEMU_L0_GPT_SIZE (8 * PAGE_SIZE)
+#define PLAT_QEMU_L0_GPT_BASE (PLAT_QEMU_L1_GPT_BASE - \
+ (PLAT_QEMU_L0_GPT_SIZE + \
+ PLAT_QEMU_GPT_BITLOCK_SIZE + \
+ PLAT_QEMU_GPT_ALIGNMENT))
+
+#if RME_GPT_BITLOCK_BLOCK
+/*
+ * 4TB / (RME_GPT_BITLOCK_BLOCK * 512M * 8) == 1024
+ */
+#define PLAT_QEMU_GPT_BITLOCK_SIZE (1 * PAGE_SIZE)
+/*
+ * PLAT_QEMU_L0_GPT_SIZE is 8 pages and PLAT_QEMU_GPT_BITLOCK_SIZE
+ * is 1 page. As such we need 7 pages to have an 8 page alignment.
+ */
+#define PLAT_QEMU_GPT_ALIGNMENT (7 * PAGE_SIZE)
+#else /* RME_GPT_BITLOCK_BLOCK */
+#define PLAT_QEMU_GPT_BITLOCK_SIZE 0
+#define PLAT_QEMU_GPT_ALIGNMENT 0
+#endif /* RME_GPT_BITLOCK_BLOCK */
+
+/*
+ * If we have 1TB of RAM and each L1GPT covers 1GB, we need 1024 L1GPTs. With
+ * one more L1GPT to cover the other physical address spaces (see pas_regions[]
+ * in qemu_bl31_setup.c), we need a total of 1025 L1GPTs. Each L1GPT is 131072
+ * bytes, so we need 1025 * 131072 bytes = 0x8020000 of RAM to hold the L1GPTS.
+ */
+#define PLAT_QEMU_L1_GPT_SIZE UL(0x08020000)
+#define PLAT_QEMU_L1_GPT_BASE (BL_RAM_BASE + BL_RAM_SIZE - \
+ PLAT_QEMU_L1_GPT_SIZE)
+#define PLAT_QEMU_L1_GPT_END (PLAT_QEMU_L1_GPT_BASE + \
+ PLAT_QEMU_L1_GPT_SIZE - 1U)
+
+#define RME_GPT_DRAM_BASE PLAT_QEMU_L0_GPT_BASE
+#define RME_GPT_DRAM_SIZE (PLAT_QEMU_L1_GPT_SIZE + \
+ PLAT_QEMU_L0_GPT_SIZE + \
+ PLAT_QEMU_GPT_BITLOCK_SIZE + \
+ PLAT_QEMU_GPT_ALIGNMENT)
+
+#ifndef __ASSEMBLER__
+/* L0 table greater than 4KB must be naturally aligned */
+CASSERT((PLAT_QEMU_L0_GPT_BASE & (PLAT_QEMU_L0_GPT_SIZE - 1)) == 0,
+ assert_l0_gpt_naturally_aligned);
+#endif
+
+/* Reserved some DRAM space for RMM (1072MB) */
+#define REALM_DRAM_BASE PLAT_QEMU_DRAM0_BASE
+#define REALM_DRAM_SIZE 0x43000000
+
+#define PLAT_QEMU_RMM_SIZE (REALM_DRAM_SIZE - RMM_SHARED_SIZE)
+#define PLAT_QEMU_RMM_SHARED_SIZE (PAGE_SIZE) /* 4KB */
+
+#define RMM_BASE (REALM_DRAM_BASE)
+#define RMM_LIMIT (RMM_BASE + PLAT_QEMU_RMM_SIZE)
+#define RMM_SHARED_BASE (RMM_LIMIT)
+#define RMM_SHARED_SIZE PLAT_QEMU_RMM_SHARED_SIZE
+
+#define MAP_GPT_L0_REGION MAP_REGION_FLAT( \
+ PLAT_QEMU_L0_GPT_BASE, \
+ (PLAT_QEMU_L0_GPT_SIZE + \
+ PLAT_QEMU_GPT_BITLOCK_SIZE + \
+ PLAT_QEMU_GPT_ALIGNMENT), \
+ MT_MEMORY | MT_RW | EL3_PAS)
+
+#define MAP_GPT_L1_REGION MAP_REGION_FLAT( \
+ PLAT_QEMU_L1_GPT_BASE, \
+ PLAT_QEMU_L1_GPT_SIZE, \
+ MT_MEMORY | MT_RW | EL3_PAS)
+/*
+ * We add the RMM_SHARED size to RMM mapping to map the region as a block.
+ * Else we end up requiring more pagetables in BL2 for ROMLIB build.
+ */
+#define MAP_RMM_DRAM MAP_REGION_FLAT( \
+ RMM_BASE, \
+ (PLAT_QEMU_RMM_SIZE + \
+ RMM_SHARED_SIZE), \
+ MT_MEMORY | MT_RW | MT_REALM)
+
+#define MAP_RMM_SHARED_MEM MAP_REGION_FLAT( \
+ RMM_SHARED_BASE, \
+ RMM_SHARED_SIZE, \
+ MT_MEMORY | MT_RW | MT_REALM)
+
+/* When RME is enabled, the base of NS DRAM is moved forward after the RMM */
+#define NS_DRAM0_BASE_OFFSET REALM_DRAM_SIZE
+#endif /* !ENABLE_RME */
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h b/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h
new file mode 100644
index 0000000..c73a162
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024-2025, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QEMU_PAS_DEF_H
+#define QEMU_PAS_DEF_H
+
+#include <lib/gpt_rme/gpt_rme.h>
+#include "platform_def.h"
+
+/*****************************************************************************
+ * PAS regions used to initialize the Granule Protection Table (GPT)
+ ****************************************************************************/
+
+/* EL3 SRAM */
+#define QEMU_PAS_ROOT_BASE (BL32_MEM_BASE + BL32_MEM_SIZE)
+#define QEMU_PAS_ROOT_SIZE (BL_RAM_SIZE - \
+ (BL32_MEM_SIZE + RME_GPT_DRAM_SIZE))
+
+/* Secure DRAM */
+#define QEMU_PAS_SEC_BASE BL32_MEM_BASE /* BL32_SRAM_BASE */
+#define QEMU_PAS_SEC_SIZE BL32_MEM_SIZE
+
+/* GPTs */
+#define QEMU_PAS_GPT_BASE RME_GPT_DRAM_BASE /* PLAT_QEMU_L0_GPT_BASE */
+#define QEMU_PAS_GPT_SIZE RME_GPT_DRAM_SIZE
+
+/* RMM */
+#define QEMU_PAS_RMM_BASE RMM_BASE
+#define QEMU_PAS_RMM_SIZE PLAT_QEMU_RMM_SIZE
+
+/* Shared area between EL3 and RMM */
+#define QEMU_PAS_RMM_SHARED_BASE RMM_SHARED_BASE
+#define QEMU_PAS_RMM_SHARED_SIZE RMM_SHARED_SIZE
+
+#define QEMU_PAS_ROOT GPT_MAP_REGION_GRANULE(QEMU_PAS_ROOT_BASE, \
+ QEMU_PAS_ROOT_SIZE, \
+ GPT_GPI_ROOT)
+
+#define QEMU_PAS_SECURE GPT_MAP_REGION_GRANULE(QEMU_PAS_SEC_BASE, \
+ QEMU_PAS_SEC_SIZE, \
+ GPT_GPI_SECURE)
+
+#define QEMU_PAS_GPTS GPT_MAP_REGION_GRANULE(QEMU_PAS_GPT_BASE, \
+ QEMU_PAS_GPT_SIZE, \
+ GPT_GPI_ROOT)
+
+/*
+ * NS0 base address and size are fetched from the DT at runtime.
+ * See bl31_adjust_pas_regions() for details
+ */
+#define QEMU_PAS_NS0 GPT_MAP_REGION_GRANULE(0, 0, GPT_GPI_NS)
+
+#define QEMU_PAS_REALM GPT_MAP_REGION_GRANULE(QEMU_PAS_RMM_BASE, \
+ QEMU_PAS_RMM_SIZE + \
+ QEMU_PAS_RMM_SHARED_SIZE, \
+ GPT_GPI_REALM)
+
+/* Cover 4TB with L0GTP */
+#define PLATFORM_GPCCR_PPS GPCCR_PPS_4TB
+
+/* GPT Configuration options */
+#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
+
+#endif /* QEMU_PAS_DEF_H */
diff --git a/plat/qemu/qemu_sbsa/include/sbsa_platform.h b/plat/qemu/qemu_sbsa/include/sbsa_platform.h
new file mode 100644
index 0000000..a3b3ea1
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/include/sbsa_platform.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024-2025, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SBSA_PLATFORM_H
+#define SBSA_PLATFORM_H
+
+#include <stdint.h>
+
+#include <platform_def.h>
+
+struct platform_cpu_data {
+ uint32_t nodeid;
+ uint32_t mpidr;
+};
+
+struct platform_memory_data {
+ uint32_t nodeid;
+ uint64_t addr_base;
+ uint64_t addr_size;
+};
+
+/*
+ * sockets: the number of sockets on sbsa-ref platform.
+ * clusters: the number of clusters in one socket.
+ * cores: the number of cores in one cluster.
+ * threads: the number of threads in one core.
+ */
+struct platform_cpu_topology {
+ uint32_t sockets;
+ uint32_t clusters;
+ uint32_t cores;
+ uint32_t threads;
+};
+
+struct qemu_platform_info {
+ uint32_t num_cpus;
+ uint32_t num_memnodes;
+ struct platform_cpu_data cpu[PLATFORM_CORE_COUNT];
+ struct platform_cpu_topology cpu_topo;
+ struct platform_memory_data memory[PLAT_MAX_MEM_NODES];
+};
+
+void sbsa_platform_init(void);
+int sbsa_platform_version_major(void);
+int sbsa_platform_version_minor(void);
+uint32_t sbsa_platform_num_cpus(void);
+uint32_t sbsa_platform_num_memnodes(void);
+uint64_t sbsa_platform_gic_its_addr(void);
+struct platform_cpu_data sbsa_platform_cpu_node(uint64_t index);
+struct platform_memory_data sbsa_platform_memory_node(uint64_t index);
+struct platform_cpu_topology sbsa_platform_cpu_topology(void);
+
+#endif /* SBSA_PLATFORM_H */
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index 528e093..8ec3a82 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -29,8 +29,6 @@
$(eval $(call add_define,QEMU_LOAD_BL32))
endif
-BL2_SOURCES += $(LIBFDT_SRCS)
-
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
@@ -38,6 +36,7 @@
plat/common/plat_gicv3.c
BL31_SOURCES += ${PLAT_QEMU_PATH}/sbsa_gic.c \
+ ${PLAT_QEMU_PATH}/sbsa_platform.c \
${PLAT_QEMU_PATH}/sbsa_pm.c \
${PLAT_QEMU_PATH}/sbsa_sip_svc.c \
${PLAT_QEMU_PATH}/sbsa_topology.c
@@ -61,5 +60,5 @@
$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
-ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
+ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DRAM0_BASE
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
diff --git a/plat/qemu/qemu_sbsa/sbsa_platform.c b/plat/qemu/qemu_sbsa/sbsa_platform.c
new file mode 100644
index 0000000..8c8d632
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/sbsa_platform.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2024-2025, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+
+#include <sbsa_platform.h>
+
+#include "qemu_private.h"
+
+/* default platform version is 0.0 */
+static int platform_version_major;
+static int platform_version_minor;
+
+static uint64_t gic_its_addr;
+static struct qemu_platform_info dynamic_platform_info;
+
+void sbsa_set_gic_bases(const uintptr_t gicd_base, const uintptr_t gicr_base);
+
+/*
+ * QEMU provides us with minimal information about hardware platform using
+ * minimalistic DeviceTree. This is not a Linux DeviceTree. It is not even
+ * a firmware DeviceTree.
+ *
+ * It is information passed from QEMU to describe the information a hardware
+ * platform would have other mechanisms to discover at runtime, that are
+ * affected by the QEMU command line.
+ *
+ * Ultimately this device tree will be replaced by IPC calls to an emulated SCP.
+ * And when we do that, we won't then have to rewrite Normal world firmware to
+ * cope.
+ */
+
+static void read_cpu_topology_from_dt(void *dtb)
+{
+ int node;
+
+ /*
+ * QEMU gives us this DeviceTree node when we config:
+ * -smp 16,sockets=2,clusters=2,cores=2,threads=2
+ *
+ * topology {
+ * threads = <0x02>;
+ * cores = <0x02>;
+ * clusters = <0x02>;
+ * sockets = <0x02>;
+ * };
+ */
+
+ node = fdt_path_offset(dtb, "/cpus/topology");
+ if (node > 0) {
+ dynamic_platform_info.cpu_topo.sockets =
+ fdt_read_uint32_default(dtb, node, "sockets", 0);
+ dynamic_platform_info.cpu_topo.clusters =
+ fdt_read_uint32_default(dtb, node, "clusters", 0);
+ dynamic_platform_info.cpu_topo.cores =
+ fdt_read_uint32_default(dtb, node, "cores", 0);
+ dynamic_platform_info.cpu_topo.threads =
+ fdt_read_uint32_default(dtb, node, "threads", 0);
+ }
+
+ INFO("Cpu topology: sockets: %d, clusters: %d, cores: %d, threads: %d\n",
+ dynamic_platform_info.cpu_topo.sockets,
+ dynamic_platform_info.cpu_topo.clusters,
+ dynamic_platform_info.cpu_topo.cores,
+ dynamic_platform_info.cpu_topo.threads);
+}
+
+static void read_cpuinfo_from_dt(void *dtb)
+{
+ int node;
+ int prev;
+ int cpu = 0;
+ uintptr_t mpidr;
+
+ /*
+ * QEMU gives us this DeviceTree node:
+ * numa-node-id entries are only when NUMA config is used
+ *
+ * cpus {
+ * #size-cells = <0x00>;
+ * #address-cells = <0x02>;
+ *
+ * cpu@0 {
+ * numa-node-id = <0x00>;
+ * reg = <0x00 0x00>;
+ * };
+ *
+ * cpu@1 {
+ * numa-node-id = <0x03>;
+ * reg = <0x00 0x01>;
+ * };
+ * };
+ */
+ node = fdt_path_offset(dtb, "/cpus");
+ if (node < 0) {
+ ERROR("No information about cpus in DeviceTree.\n");
+ panic();
+ }
+
+ /*
+ * QEMU numbers cpus from 0 and there can be /cpus/cpu-map present so we
+ * cannot use fdt_first_subnode() here
+ */
+ node = fdt_path_offset(dtb, "/cpus/cpu@0");
+
+ while (node > 0) {
+ if (fdt_getprop(dtb, node, "reg", NULL)) {
+ fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL);
+ } else {
+ ERROR("Incomplete information for cpu %d in DeviceTree.\n", cpu);
+ panic();
+ }
+
+ dynamic_platform_info.cpu[cpu].mpidr = mpidr;
+ dynamic_platform_info.cpu[cpu].nodeid =
+ fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
+
+ INFO("CPU %d: node-id: %d, mpidr: %ld\n", cpu,
+ dynamic_platform_info.cpu[cpu].nodeid, mpidr);
+
+ cpu++;
+
+ prev = node;
+ node = fdt_next_subnode(dtb, prev);
+ }
+
+ dynamic_platform_info.num_cpus = cpu;
+ INFO("Found %d cpus\n", dynamic_platform_info.num_cpus);
+
+ read_cpu_topology_from_dt(dtb);
+}
+
+static void read_meminfo_from_dt(void *dtb)
+{
+ const fdt32_t *prop;
+ const char *type;
+ int prev, node;
+ int len;
+ uint32_t memnode = 0;
+ uint32_t higher_value, lower_value;
+ uint64_t cur_base, cur_size;
+
+ /*
+ * QEMU gives us this DeviceTree node:
+ *
+ * memory@100c0000000 {
+ * numa-node-id = <0x01>;
+ * reg = <0x100 0xc0000000 0x00 0x40000000>;
+ * device_type = "memory";
+ * };
+ *
+ * memory@10000000000 {
+ * numa-node-id = <0x00>;
+ * reg = <0x100 0x00 0x00 0xc0000000>;
+ * device_type = "memory";
+ * }
+ */
+
+ for (prev = 0;; prev = node) {
+ node = fdt_next_node(dtb, prev, NULL);
+ if (node < 0) {
+ break;
+ }
+
+ type = fdt_getprop(dtb, node, "device_type", &len);
+ if (type && strncmp(type, "memory", len) == 0) {
+ dynamic_platform_info.memory[memnode].nodeid =
+ fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
+
+ /*
+ * Get the 'reg' property of this node and
+ * assume two 8 bytes for base and size.
+ */
+ prop = fdt_getprop(dtb, node, "reg", &len);
+ if (prop != 0 && len == (2 * sizeof(int64_t))) {
+ higher_value = fdt32_to_cpu(*prop);
+ lower_value = fdt32_to_cpu(*(prop + 1));
+ cur_base = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
+
+ higher_value = fdt32_to_cpu(*(prop + 2));
+ lower_value = fdt32_to_cpu(*(prop + 3));
+ cur_size = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
+
+ dynamic_platform_info.memory[memnode].addr_base = cur_base;
+ dynamic_platform_info.memory[memnode].addr_size = cur_size;
+
+ INFO("RAM %d: node-id: %d, address: 0x%lx - 0x%lx\n",
+ memnode,
+ dynamic_platform_info.memory[memnode].nodeid,
+ dynamic_platform_info.memory[memnode].addr_base,
+ dynamic_platform_info.memory[memnode].addr_base +
+ dynamic_platform_info.memory[memnode].addr_size - 1);
+ }
+
+ memnode++;
+ }
+ }
+
+ dynamic_platform_info.num_memnodes = memnode;
+}
+
+static void read_platform_config_from_dt(void *dtb)
+{
+ int node;
+ const fdt64_t *data;
+ int err;
+ uintptr_t gicd_base;
+ uintptr_t gicr_base;
+
+ /*
+ * QEMU gives us this DeviceTree node:
+ *
+ * intc {
+ * reg = < 0x00 0x40060000 0x00 0x10000
+ * 0x00 0x40080000 0x00 0x4000000>;
+ * its {
+ * reg = <0x00 0x44081000 0x00 0x20000>;
+ * };
+ * };
+ */
+ node = fdt_path_offset(dtb, "/intc");
+ if (node < 0) {
+ return;
+ }
+
+ data = fdt_getprop(dtb, node, "reg", NULL);
+ if (data == NULL) {
+ return;
+ }
+
+ err = fdt_get_reg_props_by_index(dtb, node, 0, &gicd_base, NULL);
+ if (err < 0) {
+ ERROR("Failed to read GICD reg property of GIC node\n");
+ return;
+ }
+ INFO("GICD base = 0x%lx\n", gicd_base);
+
+ err = fdt_get_reg_props_by_index(dtb, node, 1, &gicr_base, NULL);
+ if (err < 0) {
+ ERROR("Failed to read GICR reg property of GIC node\n");
+ return;
+ }
+ INFO("GICR base = 0x%lx\n", gicr_base);
+
+ sbsa_set_gic_bases(gicd_base, gicr_base);
+
+ node = fdt_path_offset(dtb, "/intc/its");
+ if (node < 0) {
+ return;
+ }
+
+ err = fdt_get_reg_props_by_index(dtb, node, 0, &gic_its_addr, NULL);
+ if (err < 0) {
+ ERROR("Failed to read GICI reg property of GIC node\n");
+ return;
+ }
+ INFO("GICI base = 0x%lx\n", gic_its_addr);
+}
+
+static void read_platform_version(void *dtb)
+{
+ int node;
+
+ node = fdt_path_offset(dtb, "/");
+ if (node >= 0) {
+ platform_version_major =
+ fdt_read_uint32_default(dtb, node, "machine-version-major", 0);
+ platform_version_minor =
+ fdt_read_uint32_default(dtb, node, "machine-version-minor", 0);
+ }
+}
+
+#if !ENABLE_RME
+static int set_system_memory_base(void *dtb, uintptr_t new_base)
+{
+ (void)dtb;
+ (void)new_base;
+
+ return 0;
+}
+#else /* !ENABLE_RME */
+static int set_system_memory_base(void *dtb, uintptr_t new_base)
+{
+ uint64_t cur_base, cur_size, new_size, delta;
+ int len, prev, node, ret;
+ const fdt32_t *prop;
+ uint32_t node_id;
+ const char *type;
+ fdt64_t new[2];
+
+ /*
+ * QEMU gives us this DeviceTree node:
+ *
+ * memory@100c0000000 {
+ * numa-node-id = <0x01>;
+ * reg = <0x100 0xc0000000 0x00 0x40000000>;
+ * device_type = "memory";
+ * };
+ *
+ * memory@10000000000 {
+ * numa-node-id = <0x00>;
+ * reg = <0x100 0x00 0x00 0xc0000000>;
+ * device_type = "memory";
+ * }
+ */
+
+ for (prev = 0;; prev = node) {
+ node = fdt_next_node(dtb, prev, NULL);
+ if (node < 0) {
+ return node;
+ }
+
+ type = fdt_getprop(dtb, node, "device_type", &len);
+ if (type && strncmp(type, "memory", len) == 0) {
+
+ /*
+ * We are looking for numa node 0, i.e the start of the
+ * system memory. If a "numa-node-id" doesn't exists we
+ * take the first one.
+ */
+ node_id = fdt_read_uint32_default(dtb, node,
+ "numa-node-id", 0);
+
+ if (node_id == 0) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Get the 'reg' property of this node and
+ * assume two 8 bytes for base and size.
+ */
+ prop = fdt_getprop(dtb, node, "reg", &len);
+ if (!prop || len < 0) {
+ return len;
+ }
+
+ if (len != (2 * sizeof(uint64_t))) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ ret = fdt_get_reg_props_by_index(dtb, node, 0, &cur_base, &cur_size);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * @cur_base is the base of the NS RAM given to us by QEMU, we can't
+ * go lower than that.
+ */
+ if (new_base < cur_base) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ if (new_base == cur_base) {
+ return 0;
+ }
+
+ /*
+ * The new base is higher than the base set by QEMU, i.e we are moving
+ * the base memory up and shrinking the size.
+ */
+ delta = (size_t)(new_base - cur_base);
+
+ /*
+ * Make sure the new base is still within the base memory node, i.e
+ * the base memory node is big enough for the RMM.
+ */
+ if (delta >= cur_size) {
+ ERROR("Not enough space in base memory node for RMM\n");
+ return -FDT_ERR_BADVALUE;
+ }
+
+ new_size = cur_size - delta;
+
+ new[0] = cpu_to_fdt64(new_base);
+ new[1] = cpu_to_fdt64(new_size);
+
+ ret = fdt_setprop(dtb, node, "reg", new, len);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return fdt_pack(dtb);
+}
+#endif /* !ENABLE_RME */
+
+void sbsa_platform_init(void)
+{
+ /* Read DeviceTree data before MMU is enabled */
+
+ void *dtb = plat_qemu_dt_runtime_address();
+ int err;
+
+ err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE);
+ if (err < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
+ return;
+ }
+
+ err = fdt_check_header(dtb);
+ if (err < 0) {
+ ERROR("Invalid DTB file passed\n");
+ return;
+ }
+
+ read_platform_version(dtb);
+ INFO("Platform version: %d.%d\n", platform_version_major, platform_version_minor);
+
+ if (set_system_memory_base(dtb, NS_DRAM0_BASE)) {
+ ERROR("Failed to set system memory in Device Tree\n");
+ return;
+ }
+
+ read_platform_config_from_dt(dtb);
+ read_cpuinfo_from_dt(dtb);
+ read_meminfo_from_dt(dtb);
+}
+
+int sbsa_platform_version_major(void)
+{
+ return platform_version_major;
+}
+
+int sbsa_platform_version_minor(void)
+{
+ return platform_version_minor;
+}
+
+uint32_t sbsa_platform_num_cpus(void)
+{
+ return dynamic_platform_info.num_cpus;
+}
+
+uint32_t sbsa_platform_num_memnodes(void)
+{
+ return dynamic_platform_info.num_memnodes;
+}
+
+uint64_t sbsa_platform_gic_its_addr(void)
+{
+ return gic_its_addr;
+}
+
+struct platform_cpu_data sbsa_platform_cpu_node(uint64_t index)
+{
+ return dynamic_platform_info.cpu[index];
+}
+
+struct platform_memory_data sbsa_platform_memory_node(uint64_t index)
+{
+ return dynamic_platform_info.memory[index];
+}
+
+struct platform_cpu_topology sbsa_platform_cpu_topology(void)
+{
+ return dynamic_platform_info.cpu_topo;
+}
diff --git a/plat/qemu/qemu_sbsa/sbsa_sip_svc.c b/plat/qemu/qemu_sbsa/sbsa_sip_svc.c
index 83e66f3..839bb1c 100644
--- a/plat/qemu/qemu_sbsa/sbsa_sip_svc.c
+++ b/plat/qemu/qemu_sbsa/sbsa_sip_svc.c
@@ -6,14 +6,10 @@
#include <assert.h>
-#include <common/fdt_wrappers.h>
#include <common/runtime_svc.h>
-#include <libfdt.h>
#include <smccc_helpers.h>
-/* default platform version is 0.0 */
-static int platform_version_major;
-static int platform_version_minor;
+#include <sbsa_platform.h>
#define SMC_FASTCALL 0x80000000
#define SMC64_FUNCTION (SMC_FASTCALL | 0x40000000)
@@ -34,326 +30,10 @@
#define SIP_SVC_GET_MEMORY_NODE_COUNT SIP_FUNCTION_ID(300)
#define SIP_SVC_GET_MEMORY_NODE SIP_FUNCTION_ID(301)
-static uint64_t gic_its_addr;
-
-typedef struct {
- uint32_t nodeid;
- uint32_t mpidr;
-} cpu_data;
-
-typedef struct{
- uint32_t nodeid;
- uint64_t addr_base;
- uint64_t addr_size;
-} memory_data;
-
-/*
- * sockets: the number of sockets on sbsa-ref platform.
- * clusters: the number of clusters in one socket.
- * cores: the number of cores in one cluster.
- * threads: the number of threads in one core.
- */
-typedef struct {
- uint32_t sockets;
- uint32_t clusters;
- uint32_t cores;
- uint32_t threads;
-} cpu_topology;
-
-static struct {
- uint32_t num_cpus;
- uint32_t num_memnodes;
- cpu_data cpu[PLATFORM_CORE_COUNT];
- cpu_topology cpu_topo;
- memory_data memory[PLAT_MAX_MEM_NODES];
-} dynamic_platform_info;
-
-void sbsa_set_gic_bases(const uintptr_t gicd_base, const uintptr_t gicr_base);
uintptr_t sbsa_get_gicd(void);
uintptr_t sbsa_get_gicr(void);
/*
- * QEMU provides us with minimal information about hardware platform using
- * minimalistic DeviceTree. This is not a Linux DeviceTree. It is not even
- * a firmware DeviceTree.
- *
- * It is information passed from QEMU to describe the information a hardware
- * platform would have other mechanisms to discover at runtime, that are
- * affected by the QEMU command line.
- *
- * Ultimately this device tree will be replaced by IPC calls to an emulated SCP.
- * And when we do that, we won't then have to rewrite Normal world firmware to
- * cope.
- */
-
-static void read_cpu_topology_from_dt(void *dtb)
-{
- int node;
-
- /*
- * QEMU gives us this DeviceTree node when we config:
- * -smp 16,sockets=2,clusters=2,cores=2,threads=2
- *
- * topology {
- * threads = <0x02>;
- * cores = <0x02>;
- * clusters = <0x02>;
- * sockets = <0x02>;
- * };
- */
-
- node = fdt_path_offset(dtb, "/cpus/topology");
- if (node > 0) {
- dynamic_platform_info.cpu_topo.sockets =
- fdt_read_uint32_default(dtb, node, "sockets", 0);
- dynamic_platform_info.cpu_topo.clusters =
- fdt_read_uint32_default(dtb, node, "clusters", 0);
- dynamic_platform_info.cpu_topo.cores =
- fdt_read_uint32_default(dtb, node, "cores", 0);
- dynamic_platform_info.cpu_topo.threads =
- fdt_read_uint32_default(dtb, node, "threads", 0);
- }
-
- INFO("Cpu topology: sockets: %d, clusters: %d, cores: %d, threads: %d\n",
- dynamic_platform_info.cpu_topo.sockets,
- dynamic_platform_info.cpu_topo.clusters,
- dynamic_platform_info.cpu_topo.cores,
- dynamic_platform_info.cpu_topo.threads);
-}
-
-void read_cpuinfo_from_dt(void *dtb)
-{
- int node;
- int prev;
- int cpu = 0;
- uintptr_t mpidr;
-
- /*
- * QEMU gives us this DeviceTree node:
- * numa-node-id entries are only when NUMA config is used
- *
- * cpus {
- * #size-cells = <0x00>;
- * #address-cells = <0x02>;
- *
- * cpu@0 {
- * numa-node-id = <0x00>;
- * reg = <0x00 0x00>;
- * };
- *
- * cpu@1 {
- * numa-node-id = <0x03>;
- * reg = <0x00 0x01>;
- * };
- * };
- */
- node = fdt_path_offset(dtb, "/cpus");
- if (node < 0) {
- ERROR("No information about cpus in DeviceTree.\n");
- panic();
- }
-
- /*
- * QEMU numbers cpus from 0 and there can be /cpus/cpu-map present so we
- * cannot use fdt_first_subnode() here
- */
- node = fdt_path_offset(dtb, "/cpus/cpu@0");
-
- while (node > 0) {
- if (fdt_getprop(dtb, node, "reg", NULL)) {
- fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL);
- } else {
- ERROR("Incomplete information for cpu %d in DeviceTree.\n", cpu);
- panic();
- }
-
- dynamic_platform_info.cpu[cpu].mpidr = mpidr;
- dynamic_platform_info.cpu[cpu].nodeid =
- fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
-
- INFO("CPU %d: node-id: %d, mpidr: %ld\n", cpu,
- dynamic_platform_info.cpu[cpu].nodeid, mpidr);
-
- cpu++;
-
- prev = node;
- node = fdt_next_subnode(dtb, prev);
- }
-
- dynamic_platform_info.num_cpus = cpu;
- INFO("Found %d cpus\n", dynamic_platform_info.num_cpus);
-
- read_cpu_topology_from_dt(dtb);
-}
-
-void read_meminfo_from_dt(void *dtb)
-{
- const fdt32_t *prop;
- const char *type;
- int prev, node;
- int len;
- uint32_t memnode = 0;
- uint32_t higher_value, lower_value;
- uint64_t cur_base, cur_size;
-
- /*
- * QEMU gives us this DeviceTree node:
- *
- * memory@100c0000000 {
- * numa-node-id = <0x01>;
- * reg = <0x100 0xc0000000 0x00 0x40000000>;
- * device_type = "memory";
- * };
- *
- * memory@10000000000 {
- * numa-node-id = <0x00>;
- * reg = <0x100 0x00 0x00 0xc0000000>;
- * device_type = "memory";
- * }
- */
-
- for (prev = 0;; prev = node) {
- node = fdt_next_node(dtb, prev, NULL);
- if (node < 0) {
- break;
- }
-
- type = fdt_getprop(dtb, node, "device_type", &len);
- if (type && strncmp(type, "memory", len) == 0) {
- dynamic_platform_info.memory[memnode].nodeid =
- fdt_read_uint32_default(dtb, node, "numa-node-id", 0);
-
- /*
- * Get the 'reg' property of this node and
- * assume two 8 bytes for base and size.
- */
- prop = fdt_getprop(dtb, node, "reg", &len);
- if (prop != 0 && len == (2 * sizeof(int64_t))) {
- higher_value = fdt32_to_cpu(*prop);
- lower_value = fdt32_to_cpu(*(prop + 1));
- cur_base = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
-
- higher_value = fdt32_to_cpu(*(prop + 2));
- lower_value = fdt32_to_cpu(*(prop + 3));
- cur_size = (uint64_t)(lower_value | ((uint64_t)higher_value) << 32);
-
- dynamic_platform_info.memory[memnode].addr_base = cur_base;
- dynamic_platform_info.memory[memnode].addr_size = cur_size;
-
- INFO("RAM %d: node-id: %d, address: 0x%lx - 0x%lx\n",
- memnode,
- dynamic_platform_info.memory[memnode].nodeid,
- dynamic_platform_info.memory[memnode].addr_base,
- dynamic_platform_info.memory[memnode].addr_base +
- dynamic_platform_info.memory[memnode].addr_size - 1);
- }
-
- memnode++;
- }
- }
-
- dynamic_platform_info.num_memnodes = memnode;
-}
-
-void read_platform_config_from_dt(void *dtb)
-{
- int node;
- const fdt64_t *data;
- int err;
- uintptr_t gicd_base;
- uintptr_t gicr_base;
-
- /*
- * QEMU gives us this DeviceTree node:
- *
- * intc {
- * reg = < 0x00 0x40060000 0x00 0x10000
- * 0x00 0x40080000 0x00 0x4000000>;
- * its {
- * reg = <0x00 0x44081000 0x00 0x20000>;
- * };
- * };
- */
- node = fdt_path_offset(dtb, "/intc");
- if (node < 0) {
- return;
- }
-
- data = fdt_getprop(dtb, node, "reg", NULL);
- if (data == NULL) {
- return;
- }
-
- err = fdt_get_reg_props_by_index(dtb, node, 0, &gicd_base, NULL);
- if (err < 0) {
- ERROR("Failed to read GICD reg property of GIC node\n");
- return;
- }
- INFO("GICD base = 0x%lx\n", gicd_base);
-
- err = fdt_get_reg_props_by_index(dtb, node, 1, &gicr_base, NULL);
- if (err < 0) {
- ERROR("Failed to read GICR reg property of GIC node\n");
- return;
- }
- INFO("GICR base = 0x%lx\n", gicr_base);
-
- sbsa_set_gic_bases(gicd_base, gicr_base);
-
- node = fdt_path_offset(dtb, "/intc/its");
- if (node < 0) {
- return;
- }
-
- err = fdt_get_reg_props_by_index(dtb, node, 0, &gic_its_addr, NULL);
- if (err < 0) {
- ERROR("Failed to read GICI reg property of GIC node\n");
- return;
- }
- INFO("GICI base = 0x%lx\n", gic_its_addr);
-}
-
-void read_platform_version(void *dtb)
-{
- int node;
-
- node = fdt_path_offset(dtb, "/");
- if (node >= 0) {
- platform_version_major =
- fdt_read_uint32_default(dtb, node, "machine-version-major", 0);
- platform_version_minor =
- fdt_read_uint32_default(dtb, node, "machine-version-minor", 0);
- }
-}
-
-void sip_svc_init(void)
-{
- /* Read DeviceTree data before MMU is enabled */
-
- void *dtb = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
- int err;
-
- err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE);
- if (err < 0) {
- ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
- return;
- }
-
- err = fdt_check_header(dtb);
- if (err < 0) {
- ERROR("Invalid DTB file passed\n");
- return;
- }
-
- read_platform_version(dtb);
- INFO("Platform version: %d.%d\n", platform_version_major, platform_version_minor);
-
- read_platform_config_from_dt(dtb);
- read_cpuinfo_from_dt(dtb);
- read_meminfo_from_dt(dtb);
-}
-
-/*
* This function is responsible for handling all SiP calls from the NS world
*/
uintptr_t sbsa_sip_smc_handler(uint32_t smc_fid,
@@ -378,49 +58,56 @@
switch (smc_fid) {
case SIP_SVC_VERSION:
INFO("Platform version requested\n");
- SMC_RET3(handle, NULL, platform_version_major, platform_version_minor);
+ SMC_RET3(handle, NULL, sbsa_platform_version_major(),
+ sbsa_platform_version_minor());
case SIP_SVC_GET_GIC:
SMC_RET3(handle, NULL, sbsa_get_gicd(), sbsa_get_gicr());
case SIP_SVC_GET_GIC_ITS:
- SMC_RET2(handle, NULL, gic_its_addr);
+ SMC_RET2(handle, NULL, sbsa_platform_gic_its_addr());
case SIP_SVC_GET_CPU_COUNT:
- SMC_RET2(handle, NULL, dynamic_platform_info.num_cpus);
+ SMC_RET2(handle, NULL, sbsa_platform_num_cpus());
case SIP_SVC_GET_CPU_NODE:
index = x1;
if (index < PLATFORM_CORE_COUNT) {
- SMC_RET3(handle, NULL,
- dynamic_platform_info.cpu[index].nodeid,
- dynamic_platform_info.cpu[index].mpidr);
+ struct platform_cpu_data data;
+
+ data = sbsa_platform_cpu_node(index);
+
+ SMC_RET3(handle, NULL, data.nodeid, data.mpidr);
} else {
SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM);
}
case SIP_SVC_GET_CPU_TOPOLOGY:
- if (dynamic_platform_info.cpu_topo.cores > 0) {
- SMC_RET5(handle, NULL,
- dynamic_platform_info.cpu_topo.sockets,
- dynamic_platform_info.cpu_topo.clusters,
- dynamic_platform_info.cpu_topo.cores,
- dynamic_platform_info.cpu_topo.threads);
+ struct platform_cpu_topology topology;
+
+ topology = sbsa_platform_cpu_topology();
+
+ if (topology.cores > 0) {
+ SMC_RET5(handle, NULL, topology.sockets,
+ topology.clusters, topology.cores,
+ topology.threads);
} else {
/* we do not know topology so we report SMC as unknown */
SMC_RET1(handle, SMC_UNK);
}
case SIP_SVC_GET_MEMORY_NODE_COUNT:
- SMC_RET2(handle, NULL, dynamic_platform_info.num_memnodes);
+ SMC_RET2(handle, NULL, sbsa_platform_num_memnodes());
case SIP_SVC_GET_MEMORY_NODE:
index = x1;
if (index < PLAT_MAX_MEM_NODES) {
- SMC_RET4(handle, NULL,
- dynamic_platform_info.memory[index].nodeid,
- dynamic_platform_info.memory[index].addr_base,
- dynamic_platform_info.memory[index].addr_size);
+ struct platform_memory_data data;
+
+ data = sbsa_platform_memory_node(index);
+
+ SMC_RET4(handle, NULL, data.nodeid,
+ data.addr_base, data.addr_size);
} else {
SMC_RET1(handle, SMC_ARCH_CALL_INVAL_PARAM);
}
diff --git a/plat/qemu/qemu_sbsa/trp/trp-qemu_sbsa.mk b/plat/qemu/qemu_sbsa/trp/trp-qemu_sbsa.mk
new file mode 100644
index 0000000..07ccac0
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/trp/trp-qemu_sbsa.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2024-2025, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/qemu/common/trp/trp-qemu-common.mk
+
diff --git a/plat/qti/common/src/qti_gic_v3.c b/plat/qti/common/src/qti_gic_v3.c
index f00267a..746c6f1 100644
--- a/plat/qti/common/src/qti_gic_v3.c
+++ b/plat/qti/common/src/qti_gic_v3.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2024, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, The Linux Foundation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,24 +54,36 @@
INTR_GROUP0,
GIC_INTR_CFG_EDGE),
#endif
+#ifdef QTISECLIB_INT_ID_A2_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_A2_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_CONFIG_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_CONFIG_NOC_ERROR,
GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_DC_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_DC_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_MEM_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_MEM_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_SYSTEM_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_SYSTEM_NOC_ERROR,
GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_MMSS_NOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_MMSS_NOC_ERROR,
GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
GIC_INTR_CFG_EDGE),
+#endif
#ifdef QTISECLIB_INT_ID_LPASS_AGNOC_ERROR
INTR_PROP_DESC(QTISECLIB_INT_ID_LPASS_AGNOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP0,
diff --git a/plat/qti/qcs615/inc/platform_def.h b/plat/qti/qcs615/inc/platform_def.h
new file mode 100644
index 0000000..5b8ff7d
--- /dev/null
+++ b/plat/qti/qcs615/inc/platform_def.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Enable the dynamic translation tables library. */
+#define PLAT_XLAT_TABLES_DYNAMIC 1
+
+#include <common_def.h>
+
+#include <qti_board_def.h>
+#include <qtiseclib_defs_plat.h>
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*
+ * MPIDR_PRIMARY_CPU
+ * You just need to have the correct core_affinity_val i.e. [7:0]
+ * and cluster_affinity_val i.e. [15:8]
+ * the other bits will be ignored
+ */
+/*----------------------------------------------------------------------------*/
+#define MPIDR_PRIMARY_CPU 0x0000
+/*----------------------------------------------------------------------------*/
+
+#define QTI_PWR_LVL0 MPIDR_AFFLVL0
+#define QTI_PWR_LVL1 MPIDR_AFFLVL1
+#define QTI_PWR_LVL2 MPIDR_AFFLVL2
+#define QTI_PWR_LVL3 MPIDR_AFFLVL3
+
+/*
+ * Macros for local power states encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define QTI_LOCAL_STATE_RUN 0
+/*
+ * Local power state for clock-gating. Valid only for CPU and not cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_STB 1
+/*
+ * Local power state for retention. Valid for CPU and cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_RET 2
+/*
+ * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_OFF 3
+/*
+ * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_DEEPOFF 4
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE QTI_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE QTI_LOCAL_STATE_DEEPOFF
+
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+/*
+ * Platform specific page table and MMU setup constants.
+ */
+#define MAX_MMAP_REGIONS (PLAT_QTI_MMAP_ENTRIES)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36)
+
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * Some data must be aligned 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_GRANULE (1 << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+/*----------------------------------------------------------------------------*/
+/* PSCI power domain topology definitions */
+/*----------------------------------------------------------------------------*/
+/* One domain each to represent RSC and PDC level */
+#define PLAT_PDC_COUNT 1
+#define PLAT_RSC_COUNT 1
+
+/* There is one top-level FCM cluster */
+#define PLAT_CLUSTER_COUNT 1
+
+/* No. of cores in the FCM cluster */
+#define PLAT_CLUSTER0_CORE_COUNT 8
+
+#define PLATFORM_CORE_COUNT (PLAT_CLUSTER0_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS (PLAT_PDC_COUNT +\
+ PLAT_RSC_COUNT +\
+ PLAT_CLUSTER_COUNT +\
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL 3
+
+/*****************************************************************************/
+/* Memory mapped Generic timer interfaces */
+/*****************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* GIC-600 constants */
+/*----------------------------------------------------------------------------*/
+#define BASE_GICD_BASE 0x17A00000
+#define BASE_GICR_BASE 0x17A60000
+#define BASE_GICC_BASE 0x0
+#define BASE_GICH_BASE 0x0
+#define BASE_GICV_BASE 0x0
+
+#define QTI_GICD_BASE BASE_GICD_BASE
+#define QTI_GICR_BASE BASE_GICR_BASE
+#define QTI_GICC_BASE BASE_GICC_BASE
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UART related constants. */
+/*----------------------------------------------------------------------------*/
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+#define GENI4_CFG 0x0
+#define GENI4_IMAGE_REGS 0x100
+#define GENI4_DATA 0x600
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+#define GENI_STATUS_REG (GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK (0x1)
+#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170)
+/* MASTER/TX ENGINE REGISTERS */
+#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000)
+/* FIFO, STATUS REGISTERS AND MASKS */
+#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100)
+
+#define GENI_M_CMD_TX (0x08000000)
+
+/*----------------------------------------------------------------------------*/
+/* Device address space for mapping. Excluding starting 4K */
+/*----------------------------------------------------------------------------*/
+#define QTI_DEVICE_BASE 0x1000
+#define QTI_DEVICE_SIZE (0x80000000 - QTI_DEVICE_BASE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/*----------------------------------------------------------------------------*/
+/* AOSS registers */
+/*----------------------------------------------------------------------------*/
+#define QTI_PS_HOLD_REG 0x0C264000
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE 0x85F20000
+#define QTI_AOP_CMD_DB_SIZE 0x00020000
+/*----------------------------------------------------------------------------*/
+/* SOC hw version register */
+/*----------------------------------------------------------------------------*/
+#define QTI_SOC_VERSION_MASK U(0xFFFF)
+#define QTI_SOC_REVISION_REG 0x1FC8000
+#define QTI_SOC_REVISION_MASK U(0xFFFF)
+/*----------------------------------------------------------------------------*/
+/* LC PON register offsets */
+/*----------------------------------------------------------------------------*/
+#define PON_PS_HOLD_RESET_CTL 0x85a
+#define PON_PS_HOLD_RESET_CTL2 0x85b
+/*----------------------------------------------------------------------------*/
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/qcs615/inc/qti_map_chipinfo.h b/plat/qti/qcs615/inc/qti_map_chipinfo.h
new file mode 100644
index 0000000..6092ea0
--- /dev/null
+++ b/plat/qti/qcs615/inc/qti_map_chipinfo.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_MAP_CHIPINFO_H
+#define QTI_MAP_CHIPINFO_H
+
+#include <stdint.h>
+
+#include <qti_plat.h>
+
+#define QTI_JTAG_ID_REG 0x786130
+#define QTI_JTAG_ID_SHIFT 12
+#define QTI_JTAG_ID_QCS615 U(0x02E9)
+#define QTI_JTAG_ID_SA6155P U(0x00EE)
+#define QTI_CHIPINFO_ID_QCS615 U(0x01E7)
+#define QTI_CHIPINFO_ID_SA6155P U(0x0179)
+#define QTI_DEFAULT_CHIPINFO_ID U(0xFFFF)
+
+static const chip_id_info_t g_map_jtag_chipinfo_id[] = {
+ {QTI_JTAG_ID_QCS615, QTI_CHIPINFO_ID_QCS615},
+ {QTI_JTAG_ID_SA6155P, QTI_CHIPINFO_ID_SA6155P},
+};
+
+#endif /* QTI_MAP_CHIPINFO_H */
diff --git a/plat/qti/qcs615/inc/qti_rng_io.h b/plat/qti/qcs615/inc/qti_rng_io.h
new file mode 100644
index 0000000..b5e521e
--- /dev/null
+++ b/plat/qti/qcs615/inc/qti_rng_io.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef QTI_RNG_IO_H
+#define QTI_RNG_IO_H
+
+#define SEC_PRNG_STATUS 0x791004
+#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1
+#define SEC_PRNG_DATA_OUT 0x791000
+
+#endif /* QTI_RNG_IO_H */
+
diff --git a/plat/qti/qcs615/inc/qti_secure_io_cfg.h b/plat/qti/qcs615/inc/qti_secure_io_cfg.h
new file mode 100644
index 0000000..a78583e
--- /dev/null
+++ b/plat/qti/qcs615/inc/qti_secure_io_cfg.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_SECURE_IO_CFG_H
+#define QTI_SECURE_IO_CFG_H
+
+#include <stdint.h>
+
+/*
+ * List of peripheral/IO memory areas that are protected from
+ * non-secure world but not required to be secure.
+ */
+#define APPS_SMMU_TBU_PWR_STATUS 0x15002204
+#define APPS_SMMU_CUSTOM_CFG 0x15002300
+#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK 0x150025DC
+#define APPS_SMMU_SAFE_SEC_CFG 0x15002644
+#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002648
+
+static const uintptr_t qti_secure_io_allowed_regs[] = {
+ APPS_SMMU_TBU_PWR_STATUS,
+ APPS_SMMU_CUSTOM_CFG,
+ APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
+ APPS_SMMU_SAFE_SEC_CFG,
+ APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
+};
+
+static const uintptr_t qti_secure_io_debug_allowed_regs[] = {
+};
+
+
+#endif /* QTI_SECURE_IO_CFG_H */
diff --git a/plat/qti/qcs615/platform.mk b/plat/qti/qcs615/platform.mk
new file mode 100644
index 0000000..a3136cb
--- /dev/null
+++ b/plat/qti/qcs615/platform.mk
@@ -0,0 +1,142 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024, The Linux Foundation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Makefile for QCS615 QTI platform.
+
+QTI_PLAT_PATH := plat/qti
+CHIPSET := ${PLAT}
+
+# Turn On Separate code & data.
+SEPARATE_CODE_AND_RODATA := 1
+USE_COHERENT_MEM := 0
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+HW_ASSISTED_COHERENCY := 1
+
+# Enable errata configs for cortex_a76 and cortex_a55
+# QCS615 CPU core revisions are r1p0
+ERRATA_A55_1221012 := 1
+ERRATA_A55_1530923 := 1
+ERRATA_A76_1073348 := 1
+ERRATA_A76_1130799 := 1
+ERRATA_A76_1220197 := 1
+ERRATA_A76_1257314 := 1
+ERRATA_A76_1262606 := 1
+ERRATA_A76_1262888 := 1
+ERRATA_A76_1275112 := 1
+ERRATA_A76_1791580 := 1
+ERRATA_A76_1165522 := 1
+ERRATA_A76_1868343 := 1
+ERRATA_A76_1946160 := 1
+ERRATA_A76_2743102 := 1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID := 1
+ARM_RECOM_STATE_ID_ENC := 1
+PSCI_OS_INIT_MODE := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+RESET_TO_BL31 := 0
+
+QTI_SDI_BUILD := 0
+$(eval $(call assert_boolean,QTI_SDI_BUILD))
+$(eval $(call add_define,QTI_SDI_BUILD))
+
+#disable CTX_INCLUDE_AARCH32_REGS to support QCS615 gold cores
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+# Set dynamic CVE_2018_3639 explicitly as it defaults to 0.
+# Others which are applicable: CVE_2017_5715 & CVE_2022_23960 default to 1
+DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
+
+# Enable stack protector.
+ENABLE_STACK_PROTECTOR := strong
+
+
+QTI_EXTERNAL_INCLUDES := -I${QTI_PLAT_PATH}/${CHIPSET}/inc \
+ -I${QTI_PLAT_PATH}/common/inc \
+ -I${QTI_PLAT_PATH}/common/inc/$(ARCH) \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET} \
+
+QTI_BL31_SOURCES := $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_silver.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_gold.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S \
+ $(QTI_PLAT_PATH)/common/src/pm_ps_hold.c \
+ $(QTI_PLAT_PATH)/common/src/qti_stack_protector.c \
+ $(QTI_PLAT_PATH)/common/src/qti_common.c \
+ $(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c \
+ $(QTI_PLAT_PATH)/common/src/qti_gic_v3.c \
+ $(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c \
+ $(QTI_PLAT_PATH)/common/src/qti_syscall.c \
+ $(QTI_PLAT_PATH)/common/src/qti_topology.c \
+ $(QTI_PLAT_PATH)/common/src/qti_pm.c \
+ $(QTI_PLAT_PATH)/common/src/qti_rng.c \
+ $(QTI_PLAT_PATH)/common/src/spmi_arb.c \
+ $(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c \
+
+
+PLAT_INCLUDES := -Iinclude/plat/common/ \
+ ${QTI_EXTERNAL_INCLUDES}
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+
+include lib/coreboot/coreboot.mk
+
+#PSCI Sources.
+PSCI_SOURCES := plat/common/plat_psci_common.c \
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+#Timer sources
+TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+
+#GIC sources.
+GIC_SOURCES := plat/common/plat_gicv3.c \
+ ${GICV3_SOURCES} \
+
+CPU_SOURCES := lib/cpus/aarch64/cortex_a76.S \
+ lib/cpus/aarch64/cortex_a55.S \
+
+BL31_SOURCES += ${QTI_BL31_SOURCES} \
+ ${PSCI_SOURCES} \
+ ${GIC_SOURCES} \
+ ${TIMER_SOURCES} \
+ ${CPU_SOURCES} \
+
+LIB_QTI_PATH := ${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET}
+
+
+# Override this on the command line to point to the qtiseclib library which
+# will be available in coreboot.org
+QTISECLIB_PATH ?=
+
+ifeq ($(QTISECLIB_PATH),)
+# if No lib then use stub implementation for qtiseclib interface
+$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \
+ Please refer docs/plat/qti.rst for more details \
+ THIS FIRMWARE WILL NOT BOOT!)
+BL31_SOURCES += plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
+else
+# use library provided by QTISECLIB_PATH
+LDFLAGS += -L $(dir $(QTISECLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH)))
+endif
+
diff --git a/plat/qti/qtiseclib/inc/qcs615/qtiseclib_defs_plat.h b/plat/qti/qtiseclib/inc/qcs615/qtiseclib_defs_plat.h
new file mode 100644
index 0000000..2dbcc83
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/qcs615/qtiseclib_defs_plat.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __QTISECLIB_DEFS_PLAT_H__
+#define __QTISECLIB_DEFS_PLAT_H__
+
+#define QTISECLIB_PLAT_CLUSTER_COUNT 1
+#define QTISECLIB_PLAT_CORE_COUNT 8
+
+#define BL31_BASE 0x86200000
+#define BL31_SIZE 0x00100000
+
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE 0x85F20000
+#define QTI_AOP_CMD_DB_SIZE 0x00020000
+
+/* Chipset specific secure interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_SEC_WDOG_BARK (0x204)
+#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE (0x21)
+
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC (0xE6)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC (0xE7)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC (0xE8)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC (0xE9)
+
+#define QTISECLIB_INT_ID_XPU_SEC (0xE3)
+#define QTISECLIB_INT_ID_XPU_NON_SEC (0xE4)
+
+//NOC INterrupt
+#define QTISECLIB_INT_ID_A1_NOC_ERROR (0x18B)
+#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR (0xE2)
+#define QTISECLIB_INT_ID_DC_NOC_ERROR (0x122)
+#define QTISECLIB_INT_ID_MEM_NOC_ERROR (0x6C) //GEM_NOC
+#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR (0xC6)
+#define QTISECLIB_INT_ID_MMSS_NOC_ERROR (0xBA)
+
+#endif /* __QTISECLIB_DEFS_PLAT_H__ */
diff --git a/plat/rockchip/common/drivers/pmu/pmu_com.h b/plat/rockchip/common/drivers/pmu/pmu_com.h
index 022bb02..84f9421 100644
--- a/plat/rockchip/common/drivers/pmu/pmu_com.h
+++ b/plat/rockchip/common/drivers/pmu/pmu_com.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,8 +32,6 @@
};
#pragma weak plat_ic_get_pending_interrupt_id
-#pragma weak pmu_power_domain_ctr
-#pragma weak check_cpu_wfie
static inline uint32_t pmu_power_domain_st(uint32_t pd)
{
diff --git a/plat/rockchip/px30/drivers/pmu/pmu.c b/plat/rockchip/px30/drivers/pmu/pmu.c
index 8770b2e..0d8e8b6 100644
--- a/plat/rockchip/px30/drivers/pmu/pmu.c
+++ b/plat/rockchip/px30/drivers/pmu/pmu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -867,18 +867,6 @@
ERROR("Can't wait pll:%d lock\n", pll_id);
}
-static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd)
-{
- mmio_write_32(pll_base + PLL_CON(1),
- BITS_WITH_WMASK(1, 1U, 15));
- if (pd)
- mmio_write_32(pll_base + PLL_CON(1),
- BITS_WITH_WMASK(1, 1, 14));
- else
- mmio_write_32(pll_base + PLL_CON(1),
- BITS_WITH_WMASK(0, 1, 14));
-}
-
static inline void pll_set_mode(uint32_t pll_id, uint32_t mode)
{
uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id));
diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.c b/plat/rockchip/rk3288/drivers/pmu/pmu.c
index 085976c..9e17cff 100644
--- a/plat/rockchip/rk3288/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3288/drivers/pmu/pmu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -36,90 +36,6 @@
ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
};
-static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle)
-{
- uint32_t mask = BIT(req);
- uint32_t idle_mask = 0;
- uint32_t idle_target = 0;
- uint32_t val;
- uint32_t wait_cnt = 0;
-
- switch (req) {
- case bus_ide_req_gpu:
- idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
- idle_target = (idle << pmu_idle_ack_gpu) |
- (idle << pmu_idle_gpu);
- break;
- case bus_ide_req_core:
- idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
- idle_target = (idle << pmu_idle_ack_core) |
- (idle << pmu_idle_core);
- break;
- case bus_ide_req_cpup:
- idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup);
- idle_target = (idle << pmu_idle_ack_cpup) |
- (idle << pmu_idle_cpup);
- break;
- case bus_ide_req_bus:
- idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
- idle_target = (idle << pmu_idle_ack_bus) |
- (idle << pmu_idle_bus);
- break;
- case bus_ide_req_dma:
- idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
- idle_target = (idle << pmu_idle_ack_dma) |
- (idle << pmu_idle_dma);
- break;
- case bus_ide_req_peri:
- idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
- idle_target = (idle << pmu_idle_ack_peri) |
- (idle << pmu_idle_peri);
- break;
- case bus_ide_req_video:
- idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
- idle_target = (idle << pmu_idle_ack_video) |
- (idle << pmu_idle_video);
- break;
- case bus_ide_req_hevc:
- idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc);
- idle_target = (idle << pmu_idle_ack_hevc) |
- (idle << pmu_idle_hevc);
- break;
- case bus_ide_req_vio:
- idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
- idle_target = (pmu_idle_ack_vio) |
- (idle << pmu_idle_vio);
- break;
- case bus_ide_req_alive:
- idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
- idle_target = (idle << pmu_idle_ack_alive) |
- (idle << pmu_idle_alive);
- break;
- default:
- ERROR("%s: Unsupported the idle request\n", __func__);
- break;
- }
-
- val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
- if (idle)
- val |= mask;
- else
- val &= ~mask;
-
- mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
-
- while ((mmio_read_32(PMU_BASE +
- PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
- wait_cnt++;
- if (!(wait_cnt % MAX_WAIT_CONUT))
- WARN("%s:st=%x(%x)\n", __func__,
- mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
- idle_mask);
- }
-
- return 0;
-}
-
static bool rk3288_sleep_disable_osc(void)
{
static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
index 3cdb7a2..49faba8 100644
--- a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
+++ b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -778,7 +778,7 @@
else if (twr_tmp <= 8)
twr_tmp = 8;
else if (twr_tmp <= 12)
- twr_tmp = twr_tmp;
+ ; /* do nothing */
else if (twr_tmp <= 14)
twr_tmp = 14;
else
diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile
index 7913190..2bc87ae 100644
--- a/plat/rockchip/rk3399/drivers/m0/Makefile
+++ b/plat/rockchip/rk3399/drivers/m0/Makefile
@@ -5,13 +5,11 @@
#
include ../../../../../make_helpers/common.mk
+include ../../../../../make_helpers/build_macros.mk
include ../../../../../make_helpers/toolchain.mk
-# Cross Compile
-M0_CROSS_COMPILE ?= arm-none-eabi-
-
# Build architecture
-ARCH := cortex-m0
+ARCH := rk3399-m0
# Build platform
PLAT_M0 ?= rk3399m0
@@ -27,10 +25,13 @@
C_SOURCES_PMU := src/suspend.c
# Flags definition
-COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
+COMMON_FLAGS := -g -mcpu=cortex-m0 -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
CFLAGS := -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-common
-ASFLAGS := -Wa,--gdwarf-2
-LDFLAGS := -Wl,--gc-sections -Wl,--build-id=none
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
+CFLAGS += $(call cc_option, --param=min-pagesize=0)
+ASFLAGS := -Wa,--gdwarf-2 -Wa,--fatal-warnings
+LDFLAGS := -Wl,--gc-sections -Wl,--build-id=none -Wl,--fatal-warnings -z noexecstack
+LDFLAGS += $(call ld_option,-Xlinker --no-warn-rwx-segments)
# NOTE: The line continuation '\' is required in the next define otherwise we
# end up with a line-feed characer at the end of the last c filename.
@@ -62,7 +63,7 @@
$(OBJ) : $(2)
$(s)echo " CC $$<"
- $$(q)$(rk3399-m0-cc) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
+ $$(q)$($(ARCH)-cc) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
endef
define MAKE_S
@@ -70,7 +71,7 @@
$(OBJ) : $(2)
$(s)echo " AS $$<"
- $$(q)$(rk3399-m0-cc) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
+ $$(q)$($(ARCH)-as) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
endef
define MAKE_OBJS
@@ -91,20 +92,20 @@
.DEFAULT_GOAL := all
$(LINKERFILE): $(LINKERFILE_SRC)
- $(rk3399-m0-cc) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
+ $(q)$($(ARCH)-cc) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
-include $(LINKERFILE).d
$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
$(s)echo " LD $@"
- $(q)$(rk3399-m0-cc) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
+ $(q)$($(ARCH)-ld) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
%.bin : %.elf
$(s)echo " BIN $@"
- $(q)$(rk3399-m0-oc) -O binary $< $@
+ $(q)$($(ARCH)-oc) -O binary $< $@
$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
$(s)echo " LD $@"
- $(q)$(rk3399-m0-cc) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+ $(q)$($(ARCH)-ld) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c
index f693dbd..a4128b2 100644
--- a/plat/rockchip/rk3588/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c
@@ -760,10 +760,10 @@
"mrs x0, S3_0_C15_C2_7\n"
"orr x0, x0, #0x1\n"
"msr S3_0_C15_C2_7, x0\n"
- "wfi_loop:\n"
+ "1:\n"
"isb\n"
"wfi\n"
- "b wfi_loop\n");
+ "b 1b\n");
}
static void nonboot_cpus_off(void)
diff --git a/plat/st/common/include/stm32mp_svc_setup.h b/plat/st/common/include/stm32mp_svc_setup.h
new file mode 100644
index 0000000..e0e0d7f
--- /dev/null
+++ b/plat/st/common/include/stm32mp_svc_setup.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SVC_SETUP_H
+#define STM32MP_SVC_SETUP_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Common SMC function IDs for STM32 Service queries across STM32MP paltforms */
+#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
+#define STM32_SIP_SVC_UID 0x8200ff01
+/* 0x8200ff02 is reserved */
+#define STM32_SIP_SVC_VERSION 0x8200ff03
+
+/* STM32 SiP Service Calls version numbers */
+#define STM32_SIP_SVC_VERSION_MAJOR 0x0
+#define STM32_SIP_SVC_VERSION_MINOR 0x1
+
+/* SMC error codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
+void plat_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, uint32_t *ret1,
+ uint32_t *ret2, bool *ret2_enabled,
+ u_register_t flags);
+
+#endif /* STM32MP_SVC_SETUP_H */
diff --git a/plat/st/common/stm32mp_svc_setup.c b/plat/st/common/stm32mp_svc_setup.c
new file mode 100644
index 0000000..7fce896
--- /dev/null
+++ b/plat/st/common/stm32mp_svc_setup.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014-2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/scmi-msg.h>
+#include <lib/psci/psci.h>
+#include <platform_def.h>
+#include <tools_share/uuid.h>
+
+#include <stm32mp_svc_setup.h>
+
+/* STM32 SiP Service UUID */
+DEFINE_SVC_UUID2(stm32_sip_svc_uid,
+ 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
+ 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
+
+/* Setup STM32MP Standard Services */
+static int32_t stm32mp_svc_setup(void)
+{
+ /*
+ * PSCI is the only specification implemented as a Standard Service.
+ * Invoke PSCI setup from here.
+ */
+ return 0;
+}
+
+/*
+ * Top-level Standard Service SMC handler. This handler will dispatch the SMC
+ * to the correct feature handler or default call a platform handler
+ */
+static uintptr_t stm32mp_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, void *cookie,
+ void *handle, u_register_t flags)
+{
+ uint32_t ret1 = 0U, ret2 = 0U;
+ bool ret_uid = false, ret2_enabled = false;
+
+ switch (smc_fid) {
+ case STM32_SIP_SVC_UID:
+ /* Return UUID to the caller */
+ ret_uid = true;
+ break;
+
+ case STM32_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ ret1 = STM32_SIP_SVC_VERSION_MAJOR;
+ ret2 = STM32_SIP_SVC_VERSION_MINOR;
+ ret2_enabled = true;
+ break;
+ default:
+ plat_svc_smc_handler(smc_fid, x1, x2, x3, x4, &ret1, &ret2, &ret2_enabled, flags);
+ break;
+ }
+
+ if (ret_uid) {
+ SMC_UUID_RET(handle, stm32_sip_svc_uid);
+ }
+
+ if (ret2_enabled) {
+ SMC_RET2(handle, ret1, ret2);
+ }
+
+ SMC_RET1(handle, ret1);
+}
+
+/* Register Standard Service Calls as runtime service */
+DECLARE_RT_SVC(stm32mp_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ stm32mp_svc_setup,
+ stm32mp_svc_smc_handler
+);
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
index 52088de..ca4c88d 100644
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -39,16 +39,6 @@
#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000
#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001
-/* SMC function IDs for SiP Service queries */
-#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
-#define STM32_SIP_SVC_UID 0x8200ff01
-/* 0x8200ff02 is reserved */
-#define STM32_SIP_SVC_VERSION 0x8200ff03
-
-/* STM32 SiP Service Calls version numbers */
-#define STM32_SIP_SVC_VERSION_MAJOR 0x0
-#define STM32_SIP_SVC_VERSION_MINOR 0x1
-
/* Number of STM32 SiP Calls implemented */
#define STM32_COMMON_SIP_NUM_CALLS 3
@@ -58,10 +48,4 @@
#define STM32_SMC_WRITE_SHADOW 0x03
#define STM32_SMC_READ_OTP 0x04
-/* SMC error codes */
-#define STM32_SMC_OK 0x00000000U
-#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
-#define STM32_SMC_FAILED 0xFFFFFFFEU
-#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
-
#endif /* STM32MP1_SMC_H */
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
index 7cc0013..418a2e5 100644
--- a/plat/st/stm32mp1/services/bsec_svc.c
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -11,6 +11,7 @@
#include <platform_def.h>
#include <stm32mp1_smc.h>
+#include <stm32mp_svc_setup.h>
#include "bsec_svc.h"
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
index ed8a448..6e5544d 100644
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2014-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,56 +14,27 @@
#include <tools_share/uuid.h>
#include <stm32mp1_smc.h>
+#include <stm32mp_svc_setup.h>
#include "bsec_svc.h"
-/* STM32 SiP Service UUID */
-DEFINE_SVC_UUID2(stm32_sip_svc_uid,
- 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
- 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
-
-/* Setup STM32MP1 Standard Services */
-static int32_t stm32mp1_svc_setup(void)
-{
- /*
- * PSCI is the only specification implemented as a Standard Service.
- * Invoke PSCI setup from here.
- */
- return 0;
-}
-
/*
- * Top-level Standard Service SMC handler. This handler will in turn dispatch
- * calls to PSCI SMC handler.
+ * Platform Standard Service SMC handler. This handler will dispatch
+ * calls to features handlers.
*/
-static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
- u_register_t x2, u_register_t x3,
- u_register_t x4, void *cookie,
- void *handle, u_register_t flags)
+void plat_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, uint32_t *ret1,
+ uint32_t *ret2, bool *ret2_enabled,
+ u_register_t flags)
{
- uint32_t ret1 = 0U, ret2 = 0U;
- bool ret_uid = false, ret2_enabled = false;
-
switch (smc_fid) {
case STM32_SIP_SVC_CALL_COUNT:
- ret1 = STM32_COMMON_SIP_NUM_CALLS;
- break;
-
- case STM32_SIP_SVC_UID:
- /* Return UUID to the caller */
- ret_uid = true;
- break;
-
- case STM32_SIP_SVC_VERSION:
- /* Return the version of current implementation */
- ret1 = STM32_SIP_SVC_VERSION_MAJOR;
- ret2 = STM32_SIP_SVC_VERSION_MINOR;
- ret2_enabled = true;
+ *ret1 = STM32_COMMON_SIP_NUM_CALLS;
break;
-
case STM32_SMC_BSEC:
- ret1 = bsec_main(x1, x2, x3, &ret2);
- ret2_enabled = true;
+ *ret1 = bsec_main(x1, x2, x3, ret2);
+ *ret2_enabled = true;
break;
case STM32_SIP_SMC_SCMI_AGENT0:
@@ -75,26 +46,7 @@
default:
WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
- ret1 = STM32_SMC_NOT_SUPPORTED;
+ *ret1 = STM32_SMC_NOT_SUPPORTED;
break;
}
-
- if (ret_uid) {
- SMC_UUID_RET(handle, stm32_sip_svc_uid);
- }
-
- if (ret2_enabled) {
- SMC_RET2(handle, ret1, ret2);
- }
-
- SMC_RET1(handle, ret1);
}
-
-/* Register Standard Service Calls as runtime service */
-DECLARE_RT_SVC(stm32mp1_sip_svc,
- OEN_SIP_START,
- OEN_SIP_END,
- SMC_TYPE_FAST,
- stm32mp1_svc_setup,
- stm32mp1_svc_smc_handler
-);
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 9695c9b..0e34848 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2024, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -45,6 +45,7 @@
drivers/scmi-msg/smt.c
# stm32mp1 specific services
-BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
+BL32_SOURCES += plat/st/common/stm32mp_svc_setup.c \
+ plat/st/stm32mp1/services/bsec_svc.c \
plat/st/stm32mp1/services/stm32mp1_svc_setup.c \
plat/st/stm32mp1/stm32mp1_scmi.c
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index 2fabc41..621b784 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -385,6 +385,11 @@
break;
case BL33_IMAGE_ID:
+#if PSA_FWU_SUPPORT
+ stm32_fwu_set_boot_idx();
+#endif /* PSA_FWU_SUPPORT */
+ break;
+
default:
/* Do nothing in default case */
break;
diff --git a/plat/st/stm32mp2/include/stm32mp2_smc.h b/plat/st/stm32mp2/include/stm32mp2_smc.h
new file mode 100644
index 0000000..3bf6a84
--- /dev/null
+++ b/plat/st/stm32mp2/include/stm32mp2_smc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP2_SMC_H
+#define STM32MP2_SMC_H
+
+#define STM32_COMMON_SIP_NUM_CALLS 1U
+
+/*
+ * STM32_SIP_SMC_STGEN_SET_RATE call API
+ * This service is opened to secure world only.
+ *
+ * Argument a0: (input) SMCC ID
+ * (output) status return code
+ * Argument a1: (input) Frequency to set (given by sender)
+ */
+#define STM32_SIP_SMC_STGEN_SET_RATE 0x82000000
+
+#endif /* STM32MP2_SMC_H */
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index 25ae593..a9f8d8f 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -202,6 +202,13 @@
# Generic PSCI
BL31_SOURCES += plat/common/plat_psci_common.c
+BL31_SOURCES += plat/st/common/stm32mp_svc_setup.c \
+ plat/st/stm32mp2/services/stgen_svc.c \
+ plat/st/stm32mp2/services/stm32mp2_svc_setup.c
+
+# Arm Archtecture services
+BL31_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c
+
# Compilation rules
.PHONY: check_ddr_type
bl2: check_ddr_type
diff --git a/plat/st/stm32mp2/services/stgen_svc.c b/plat/st/stm32mp2/services/stgen_svc.c
new file mode 100644
index 0000000..dada315
--- /dev/null
+++ b/plat/st/stm32mp2/services/stgen_svc.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/st/stm32mp_clkfunc.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "stgen_svc.h"
+#include <stm32mp2_smc.h>
+#include <stm32mp_common.h>
+#include <stm32mp_svc_setup.h>
+
+/*
+ * This function reads and applies the STGEN frequency value in the STGENC base frequency register,
+ * which is the frequency the system base counter use for our platforms.
+ */
+uint32_t stgen_svc_handler(void)
+{
+ unsigned long freq_to_set = mmio_read_32(STGEN_BASE + CNTFID_OFF);
+
+ VERBOSE("STGEN frequency set to %lu\n", freq_to_set);
+
+ /*
+ * Update the system counter frequency according to STGEN's base
+ * counter frequency register
+ */
+ write_cntfrq_el0((u_register_t)freq_to_set);
+
+ /* Need to update timer with new frequency */
+ generic_delay_timer_init();
+
+ return STM32_SMC_OK;
+}
diff --git a/plat/st/stm32mp2/services/stgen_svc.h b/plat/st/stm32mp2/services/stgen_svc.h
new file mode 100644
index 0000000..98c2304
--- /dev/null
+++ b/plat/st/stm32mp2/services/stgen_svc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STGEN_SVC_H
+#define STGEN_SVC_H
+
+uint32_t stgen_svc_handler(void);
+
+#endif /* STGEN_SVC_H */
diff --git a/plat/st/stm32mp2/services/stm32mp2_svc_setup.c b/plat/st/stm32mp2/services/stm32mp2_svc_setup.c
new file mode 100644
index 0000000..1162757
--- /dev/null
+++ b/plat/st/stm32mp2/services/stm32mp2_svc_setup.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <stm32mp2_smc.h>
+#include <stm32mp_svc_setup.h>
+
+#include "stgen_svc.h"
+
+/*
+ * Platform-level Standard Service SIP SMC handler. This handler will dispatch
+ * the SMC to the correct feature handler.
+ */
+void plat_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, uint32_t *ret1,
+ uint32_t *ret2, bool *ret2_enabled,
+ u_register_t flags)
+{
+ switch (smc_fid) {
+ case STM32_SIP_SVC_CALL_COUNT:
+ *ret1 = STM32_COMMON_SIP_NUM_CALLS;
+ break;
+ case STM32_SIP_SMC_STGEN_SET_RATE:
+ if (!is_caller_secure(flags)) {
+ *ret1 = STM32_SMC_FAILED;
+ break;
+ }
+
+ *ret1 = stgen_svc_handler();
+ break;
+ default:
+ WARN("Unimplemented STM32MP2 Service Call: 0x%x\n", smc_fid);
+ *ret1 = STM32_SMC_NOT_SUPPORTED;
+ break;
+ }
+}
diff --git a/plat/st/stm32mp2/stm32mp2_private.c b/plat/st/stm32mp2/stm32mp2_private.c
index 5be4c5a..ea9d2fc 100644
--- a/plat/st/stm32mp2/stm32mp2_private.c
+++ b/plat/st/stm32mp2/stm32mp2_private.c
@@ -10,6 +10,7 @@
#include <platform_def.h>
+#define BKPR_FWU_INFO 48U
#define BKPR_BOOT_MODE 96U
#if defined(IMAGE_BL31)
@@ -328,6 +329,13 @@
return tamp_bkpr(BKPR_BOOT_MODE);
}
+#if PSA_FWU_SUPPORT
+uintptr_t stm32_get_bkpr_fwu_info_addr(void)
+{
+ return tamp_bkpr(BKPR_FWU_INFO);
+}
+#endif /* PSA_FWU_SUPPORT */
+
uintptr_t stm32_ddrdbg_get_base(void)
{
return DDRDBG_BASE;
diff --git a/tools/encrypt_fw/src/main.c b/tools/encrypt_fw/src/main.c
index 6e43e73..b6246f6 100644
--- a/tools/encrypt_fw/src/main.c
+++ b/tools/encrypt_fw/src/main.c
@@ -26,7 +26,9 @@
/* Global options */
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
static const char build_msg[] = "Built : " __TIME__ ", " __DATE__;
+#endif
static char *key_algs_str[] = {
[KEY_ALG_GCM] = "gcm",
diff --git a/tools/tlc/tests/conftest.py b/tools/tlc/tests/conftest.py
index b8f88b5..93e44a9 100644
--- a/tools/tlc/tests/conftest.py
+++ b/tools/tlc/tests/conftest.py
@@ -9,6 +9,8 @@
""" Common configurations and fixtures for test environment."""
+from random import randint
+
import pytest
import yaml
from click.testing import CliRunner
@@ -16,6 +18,10 @@
from tlc.cli import cli
+def generate_random_bytes(n):
+ return bytes([randint(0, 255) for _ in range(n)])
+
+
@pytest.fixture
def tmptlstr(tmpdir):
return tmpdir.join("tl.bin").strpath
@@ -63,10 +69,27 @@
def tlcrunner(tmptlstr):
runner = CliRunner()
with runner.isolated_filesystem():
- runner.invoke(cli, ["create", tmptlstr])
+ runner.invoke(cli, ["create", "--size", 0x1F000, tmptlstr])
return runner
@pytest.fixture
def tlc_entries(tmpfdt):
return [(0, "/dev/null"), (1, tmpfdt.strpath), (0x102, tmpfdt.strpath)]
+
+
+@pytest.fixture
+def random_entry():
+ def _random_entry(max_size):
+ return randint(0, 0xFFFFFF), generate_random_bytes(randint(0, max_size))
+
+ return _random_entry
+
+
+@pytest.fixture
+def random_entries(random_entry):
+ def _random_entries(n=5, max_size=0x100):
+ for _ in range(n):
+ yield random_entry(max_size)
+
+ return _random_entries
diff --git a/tools/tlc/tests/test_cli.py b/tools/tlc/tests/test_cli.py
index a5ef30e..ebe1f6a 100644
--- a/tools/tlc/tests/test_cli.py
+++ b/tools/tlc/tests/test_cli.py
@@ -17,6 +17,7 @@
import pytest
import yaml
from click.testing import CliRunner
+from conftest import generate_random_bytes
from tlc.cli import cli
from tlc.te import TransferEntry
@@ -32,6 +33,22 @@
assert TransferList.fromfile(test_file) is not None
+@pytest.mark.parametrize("align", [4, 6, 12, 13])
+def test_create_with_align(align, tlcrunner, tmpdir):
+ tl_file = tmpdir.join("tl.bin").strpath
+ tlcrunner.invoke(cli, ["create", "-s", "10000", "-a", align, tl_file])
+
+ blob = tmpdir.join("blob.bin")
+
+ blob.write_binary(generate_random_bytes(0x200))
+ tlcrunner.invoke(cli, ["add", "--entry", 1, blob.strpath, tl_file])
+
+ tl = TransferList.fromfile(tl_file)
+ te = tl.entries[-1]
+ assert tl.alignment == align
+ assert (te.offset + te.hdr_size) % (1 << align) == 0
+
+
def test_create_with_fdt(tmpdir):
runner = CliRunner()
fdt = tmpdir.join("fdt.dtb")
@@ -69,6 +86,20 @@
assert len(tl.entries) == len(tlc_entries)
+@pytest.mark.parametrize("align", [4, 6, 12, 13])
+def test_cli_add_entry_with_align(align, tlcrunner, tmpdir, tmptlstr):
+ blob = tmpdir.join("blob.bin")
+ blob.write_binary(bytes(0x100))
+
+ tlcrunner.invoke(cli, ["add", "--align", align, "--entry", 1, blob, tmptlstr])
+ tl = TransferList.fromfile(tmptlstr)
+ te = tl.entries[-1]
+
+ print(tl, *(te for te in tl.entries), sep="\n---------------\n")
+ assert (te.offset + te.hdr_size) % (1 << align) == 0
+ assert tl.alignment == align
+
+
def test_info(tlcrunner, tmptlstr, tmpfdt):
tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
diff --git a/tools/tlc/tests/test_transfer_list.py b/tools/tlc/tests/test_transfer_list.py
index e8c430e..6900b41 100644
--- a/tools/tlc/tests/test_transfer_list.py
+++ b/tools/tlc/tests/test_transfer_list.py
@@ -9,6 +9,7 @@
"""Contains unit tests for the types TransferEntry and TransferList."""
import math
+from random import randint
import pytest
@@ -49,16 +50,40 @@
assert tl.checksum == csum
-@pytest.mark.parametrize(("tag_id", "data"), test_entries)
-def test_add_transfer_entry(tag_id, data):
+def test_add_transfer_entry(random_entries):
tl = TransferList(0x1000)
- te = TransferEntry(tag_id, len(data), data)
- tl.add_transfer_entry(tag_id, data)
-
+ # Add a single entry and check it's in the list of entries
+ te = tl.add_transfer_entry(1, bytes(100))
assert te in tl.entries
- assert tl.size == TransferList.hdr_size + te.size
+ assert tl.size % 8 == 0
+
+ # Add a range of tag id's
+ for id, data in random_entries(50, 1):
+ te = tl.add_transfer_entry(id, data)
+ assert te in tl.entries
+ assert tl.size % 8 == 0
+
+
+@pytest.mark.parametrize("align", [4, 6, 12, 13])
+def test_add_transfer_entry_with_align(align, random_entries, random_entry):
+ tl = TransferList(0xF00000)
+ id, data = random_entry(4)
+ tl.add_transfer_entry(id, data)
+
+ # Add an entry with a larger alignment requirement
+ _, data = random_entry(4)
+ te = tl.add_transfer_entry(1, data, data_align=align)
+ assert (te.offset + te.hdr_size) % (1 << align) == 0
+ assert tl.alignment == align
+
+ # Add some more entries and ensure the alignment is preserved
+ for id, data in random_entries(5, 0x200):
+ te = tl.add_transfer_entry(id, data, data_align=align)
+ assert (te.offset + te.hdr_size) % (1 << align) == 0
+ assert tl.alignment == align
+
@pytest.mark.parametrize(
("tag_id", "data"),
@@ -88,13 +113,20 @@
assert te.sum_of_bytes == csum
-@pytest.mark.parametrize(("tag_id", "data"), test_entries)
-def test_calculate_tl_checksum(tag_id, data):
+def test_calc_tl_checksum(tmpdir, random_entries):
+ tl_file = tmpdir.join("tl.bin")
+
tl = TransferList(0x1000)
- tl.add_transfer_entry(tag_id, data)
- assert tl.sum_of_bytes() == 0
+ for id, data in random_entries(10):
+ tl.add_transfer_entry(id, data)
+ assert sum(tl.to_bytes()) % 256 == 0
+
+ # Write the transfer list to a file and check that the sum of bytes is 0
+ tl.write_to_file(tl_file)
+ assert sum(tl_file.read_binary()) % 256 == 0
+
def test_empty_transfer_list_blob(tmpdir):
"""Check that we can correctly create a transfer list header."""
@@ -125,28 +157,44 @@
assert f.read(te.data_size) == te.data
-def test_multiple_te_transfer_list(tmpdir):
+def test_write_multiple_tes_to_file(tmpdir, random_entries, random_entry):
"""Check that we can create a TL with multiple TE's."""
test_file = tmpdir.join("test_tl_blob.bin")
- tl = TransferList(0x1000)
+ tl = TransferList(0x4000)
+ _test_entries = list(random_entries())
- for tag_id, data in test_entries:
+ for tag_id, data in _test_entries:
tl.add_transfer_entry(tag_id, data)
+ # Add a few entries with special alignment requirements
+ blob_id, blob = random_entry(0x200)
+ tl.add_transfer_entry(blob_id, blob, data_align=12)
+
tl.write_to_file(test_file)
with open(test_file, "rb") as f:
assert f.read(tl.hdr_size) == tl.header_to_bytes()
# Ensure that TE's have the correct alignment
- for tag_id, data in test_entries:
- f.seek(int(math.ceil(f.tell() / 2**tl.alignment) * 2**tl.alignment))
- print(f.tell())
+ for tag_id, data in _test_entries:
+ f.seek(int(math.ceil(f.tell() / 8) * 8))
+
assert int.from_bytes(f.read(3), "little") == tag_id
assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
# Make sure the data in the TE matches the data in the original case
data_size = int.from_bytes(f.read(4), "little")
assert f.read(data_size) == data
+ f.seek(int(math.ceil(f.tell() / (1 << 12)) * (1 << 12)) - 8)
+ assert int.from_bytes(f.read(3), "little") == blob_id
+ assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
+ # Make sure the data in the TE matches the data in the original case
+ data_size = int.from_bytes(f.read(4), "little")
+ assert f.read(data_size) == blob
+
+ # padding is added to align TE's, make sure padding is added to the size of
+ # the TL by checking we don't overflow.
+ assert f.tell() <= tl.size
+
def test_read_empty_transfer_list_from_file(tmpdir):
test_file = tmpdir.join("test_tl_blob.bin")
@@ -196,19 +244,17 @@
assert tl.sum_of_bytes() == 0
-@pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
-def test_remove_tag_from_file(tag):
- tl = TransferList(0x1000)
-
- for tag_id, data in test_entries:
- tl.add_transfer_entry(tag_id, data)
+def test_remove_tag(random_entry):
+ """Adds a transfer entry and remove it, size == transfer list header."""
+ tl = TransferList(0x100)
+ id, data = random_entry(tl.total_size // 2)
- removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
- original_size = tl.size
- tl.remove_tag(tag)
+ te = tl.add_transfer_entry(id, data)
+ assert te in tl.entries
- assert not any(tag == te.id for te in tl.entries)
- assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
+ tl.remove_tag(id)
+ assert not tl.get_entry(id) and te not in tl.entries
+ assert tl.size == tl.hdr_size
def test_get_fdt_offset(tmpdir):
diff --git a/tools/tlc/tlc/cli.py b/tools/tlc/tlc/cli.py
index 3d60938..431af04 100644
--- a/tools/tlc/tlc/cli.py
+++ b/tools/tlc/tlc/cli.py
@@ -27,6 +27,14 @@
@cli.command()
@click.argument("filename", type=click.Path(dir_okay=False))
@click.option(
+ "-a",
+ "--align",
+ type=int,
+ default=3,
+ show_default=True,
+ help="Set alignment in powers of 2 (e.g., -a 3 for 8 byte alignment).",
+)
+@click.option(
"-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
)
@click.option(
@@ -51,7 +59,7 @@
type=click.Path(exists=True),
help="Create the transfer list from a YAML config file.",
)
-def create(filename, size, fdt, entry, flags, from_yaml):
+def create(filename, align, size, fdt, entry, flags, from_yaml):
"""Create a new Transfer List."""
try:
if from_yaml:
@@ -60,12 +68,12 @@
tl = TransferList.from_dict(config)
else:
- tl = TransferList(size)
+ tl = TransferList(size, flags=flags, alignment=align)
entry = (*entry, (1, fdt)) if fdt else entry
for id, path in entry:
- tl.add_transfer_entry_from_file(id, path)
+ tl.add_transfer_entry_from_file(id, path, data_align=align)
except MemoryError as mem_excp:
raise MemoryError(
"TL max size exceeded, consider increasing with the option -s"
@@ -133,19 +141,24 @@
@cli.command()
-@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "-a",
+ "--align",
+ type=int,
+ help="Set alignment in powers of 2 (e.g., -a 3 for 8 byte alignment).",
+)
@click.option(
"--entry",
type=(int, click.Path(exists=True)),
multiple=True,
help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
)
-def add(filename, entry):
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+def add(align, entry, filename):
"""Update an existing Transfer List with given images."""
tl = TransferList.fromfile(filename)
-
for id, path in entry:
- tl.add_transfer_entry_from_file(id, path)
+ tl.add_transfer_entry_from_file(id, path, data_align=align)
tl.write_to_file(filename)
diff --git a/tools/tlc/tlc/te.py b/tools/tlc/tlc/te.py
index cf7aa67..0b6b532 100644
--- a/tools/tlc/tlc/te.py
+++ b/tools/tlc/tlc/te.py
@@ -48,7 +48,10 @@
@property
def sum_of_bytes(self) -> int:
- return (sum(self.header_to_bytes()) + sum(self.data)) % 256
+ return sum(self.to_bytes()) % 256
+
+ def to_bytes(self) -> bytes:
+ return self.header_to_bytes() + self.data
def header_to_bytes(self) -> bytes:
return self.id.to_bytes(3, "little") + struct.pack(
diff --git a/tools/tlc/tlc/tl.py b/tools/tlc/tlc/tl.py
index 98d2205..dfbea9f 100644
--- a/tools/tlc/tlc/tl.py
+++ b/tools/tlc/tlc/tl.py
@@ -83,13 +83,17 @@
hdr_size = 0x18
signature = 0x4A0FB10B
version = 1
+ granule = 8
def __init__(
- self, max_size: int = hdr_size, flags: int = TRANSFER_LIST_ENABLE_CHECKSUM
+ self,
+ max_size: int = hdr_size,
+ flags: int = TRANSFER_LIST_ENABLE_CHECKSUM,
+ alignment: int = 3,
) -> None:
assert max_size >= self.hdr_size
self.checksum: int = 0
- self.alignment: int = 3
+ self.alignment: int = alignment
self.size = self.hdr_size
self.total_size = max_size
self.flags = flags
@@ -138,16 +142,15 @@
# the 3-byte wide ID as a 4-byte uint, shift out this padding
# once we have the id.
te_base = f.tell()
- (id, hdr_size, data_size) = struct.unpack(
+ (id, _, data_size) = struct.unpack(
TransferEntry.encoding[0] + "I" + TransferEntry.encoding[1:],
b"\x00" + f.read(TransferEntry.hdr_size),
)
id >>= 8
-
te = tl.add_transfer_entry(id, f.read(data_size))
te.offset = te_base
- f.seek(align(te_base + hdr_size + data_size, 2**tl.alignment))
+ f.seek(align(f.tell(), tl.granule))
return tl
@@ -163,10 +166,14 @@
# get settings from config and set defaults
max_size = config.get("max_size", 0x1000)
has_checksum = config.get("has_checksum", True)
+ align = config.get("alignment", None)
flags = TRANSFER_LIST_ENABLE_CHECKSUM if has_checksum else 0
- tl = cls(max_size, flags)
+ if align:
+ tl = cls(max_size, flags, alignment=align)
+ else:
+ tl = cls(max_size, flags)
for entry in config["entries"]:
tl.add_transfer_entry_from_dict(entry)
@@ -189,13 +196,15 @@
def update_checksum(self) -> None:
"""Calculates the checksum based on the sum of bytes."""
- self.checksum = 256 - ((self.sum_of_bytes() - self.checksum) % 256)
+ self.checksum = (256 - (self.sum_of_bytes() - self.checksum)) % 256
+ assert self.checksum <= 0xFF
+
+ def to_bytes(self) -> bytes:
+ return self.header_to_bytes() + b"".join([te.to_bytes() for te in self.entries])
def sum_of_bytes(self) -> int:
"""Sum of all bytes between the base address and the end of that last TE (modulo 0xff)."""
- return (
- sum(self.header_to_bytes()) + sum(te.sum_of_bytes for te in self.entries)
- ) % 256
+ return (sum(self.to_bytes())) % 256
def get_entry(self, tag_id: int) -> Optional[TransferEntry]:
for te in self.entries:
@@ -213,18 +222,35 @@
return te.offset + te.hdr_size
- def add_transfer_entry(self, tag_id: int, data: bytes) -> TransferEntry:
+ def add_transfer_entry(
+ self, tag_id: int, data: bytes, data_align: int = 0
+ ) -> TransferEntry:
"""Appends a TransferEntry into the internal list of TE's."""
+ data_offset = TransferEntry.hdr_size + self.size
+ data_align = self.alignment if not data_align else data_align
+
+ aligned_data_offset = align(data_offset, 1 << data_align)
+
+ if tag_id != 0 and data_offset != aligned_data_offset:
+ void_len = aligned_data_offset - data_offset - TransferEntry.hdr_size
+ self.add_transfer_entry(0, bytes(void_len))
+
+ assert align(self.size, self.granule)
+
if not (self.total_size >= self.size + TransferEntry.hdr_size + len(data)):
raise MemoryError(
f"TL size has exceeded the maximum allocation {self.total_size}."
)
- else:
- te = TransferEntry(tag_id, len(data), data)
- self.entries.append(te)
- self.size += te.size
- self.update_checksum()
- return te
+
+ te = TransferEntry(tag_id, len(data), data, offset=self.size)
+ self.entries.append(te)
+
+ self.size += align(te.size, self.granule)
+ if data_align > self.alignment:
+ self.alignment = data_align
+
+ self.update_checksum()
+ return te
def add_transfer_entry_from_struct_format(
self, tag_id: int, struct_format: str, *args: Any
@@ -305,32 +331,40 @@
tag_id = entry["tag_id"]
if tag_id in tag_name_to_tag_id:
tag_id = tag_name_to_tag_id[tag_id]
- te_format = transfer_entry_formats[tag_id]
- tag_name = te_format["tag_name"]
-
- if "blob_file_path" in entry:
- return self.add_transfer_entry_from_file(tag_id, entry["blob_file_path"])
- elif tag_name == "tpm_event_log_table":
- with open(entry["event_log"], "rb") as f:
- event_log_data = f.read()
- flags_bytes = entry["flags"].to_bytes(4, "little")
- data = flags_bytes + event_log_data
+ align = entry.get("alignment", None)
- return self.add_transfer_entry(tag_id, data)
- elif tag_name == "exec_ep_info":
- return self.add_entry_point_info_transfer_entry(entry)
- elif "format" in te_format and "fields" in te_format:
- fields = [entry[field] for field in te_format["fields"]]
- return self.add_transfer_entry_from_struct_format(
- tag_id, te_format["format"], *fields
+ if "blob_file_path" in entry:
+ return self.add_transfer_entry_from_file(
+ tag_id, entry["blob_file_path"], data_align=align
)
else:
- raise ValueError(f"Invalid transfer entry {entry}.")
+ te_format = transfer_entry_formats[tag_id]
+ tag_name = te_format["tag_name"]
- def add_transfer_entry_from_file(self, tag_id: int, path: Path) -> TransferEntry:
+ if tag_name == "tpm_event_log_table":
+ with open(entry["event_log"], "rb") as f:
+ event_log_data = f.read()
+
+ flags_bytes = entry["flags"].to_bytes(4, "little")
+ data = flags_bytes + event_log_data
+
+ return self.add_transfer_entry(tag_id, data, data_align=align)
+ elif tag_name == "exec_ep_info":
+ return self.add_entry_point_info_transfer_entry(entry)
+ elif "format" in te_format and "fields" in te_format:
+ fields = [entry[field] for field in te_format["fields"]]
+ return self.add_transfer_entry_from_struct_format(
+ tag_id, te_format["format"], *fields
+ )
+ else:
+ raise ValueError(f"Invalid transfer entry {entry}.")
+
+ def add_transfer_entry_from_file(
+ self, tag_id: int, path: Path, data_align: int = 0
+ ) -> TransferEntry:
with open(path, "rb") as f:
- return self.add_transfer_entry(tag_id, f.read())
+ return self.add_transfer_entry(tag_id, f.read(), data_align=data_align)
def write_to_file(self, file: Path) -> None:
"""Write the contents of the TL to a file."""
@@ -338,20 +372,11 @@
f.write(self.header_to_bytes())
for te in self.entries:
assert f.tell() + te.hdr_size + te.data_size < self.total_size
- te_base = f.tell()
+
f.write(te.header_to_bytes())
f.write(te.data)
- # Ensure the next TE has the correct alignment
- f.write(
- bytes(
- (
- align(
- te_base + te.hdr_size + te.data_size, 2**self.alignment
- )
- - f.tell()
- )
- )
- )
+ # Ensure the next TE is at an 8-byte aligned address
+ f.write(bytes((align(f.tell(), self.granule) - f.tell())))
def remove_tag(self, tag: int) -> None:
self.entries = list(filter(lambda te: te.id != tag, self.entries))