summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lib/coreboot.h1
-rw-r--r--lib/compiler-rt/builtins/assembly.h2
-rw-r--r--lib/compiler-rt/builtins/int_types.h2
-rw-r--r--lib/coreboot/coreboot_table.c10
-rw-r--r--lib/libc/printf.c7
-rw-r--r--lib/libc/snprintf.c6
-rw-r--r--lib/libfdt/fdt.c20
-rw-r--r--plat/arm/board/morello/morello_bl31_setup.c3
-rw-r--r--plat/arm/board/morello/morello_pm.c29
-rw-r--r--plat/arm/board/morello/morello_private.h15
-rw-r--r--plat/arm/board/morello/platform.mk1
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl31_setup.c5
-rw-r--r--plat/arm/board/n1sdp/n1sdp_pm.c29
-rw-r--r--plat/arm/board/n1sdp/n1sdp_private.h15
-rw-r--r--plat/arm/board/n1sdp/platform.mk1
-rw-r--r--services/spd/opteed/opteed.mk1
-rw-r--r--services/spd/opteed/opteed_main.c104
17 files changed, 237 insertions, 14 deletions
diff --git a/include/lib/coreboot.h b/include/lib/coreboot.h
index 0aa65791d..42d4149aa 100644
--- a/include/lib/coreboot.h
+++ b/include/lib/coreboot.h
@@ -41,5 +41,6 @@ typedef enum {
coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size);
void coreboot_table_setup(void *base);
+void coreboot_get_table_location(uint64_t *address, uint32_t *size);
#endif /* COREBOOT_H */
diff --git a/lib/compiler-rt/builtins/assembly.h b/lib/compiler-rt/builtins/assembly.h
index 69a3d8620..169d49683 100644
--- a/lib/compiler-rt/builtins/assembly.h
+++ b/lib/compiler-rt/builtins/assembly.h
@@ -267,7 +267,7 @@
#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
.globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
- DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR \
+ DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
.set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
#if defined(__ARM_EABI__)
diff --git a/lib/compiler-rt/builtins/int_types.h b/lib/compiler-rt/builtins/int_types.h
index 7a72de480..e94d3154c 100644
--- a/lib/compiler-rt/builtins/int_types.h
+++ b/lib/compiler-rt/builtins/int_types.h
@@ -64,7 +64,7 @@ typedef union {
} udwords;
#if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \
- defined(__riscv) || defined(_WIN64)
+ defined(__SIZEOF_INT128__) || defined(_WIN64)
#define CRT_HAS_128BIT
#endif
diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c
index fb31ef1e0..43e983590 100644
--- a/lib/coreboot/coreboot_table.c
+++ b/lib/coreboot/coreboot_table.c
@@ -46,6 +46,8 @@ typedef struct {
coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES];
coreboot_serial_t coreboot_serial;
+uint64_t coreboot_table_addr;
+uint32_t coreboot_table_size;
/*
* The coreboot table is parsed before the MMU is enabled (i.e. with strongly
@@ -108,6 +110,12 @@ coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size)
return CB_MEM_NONE;
}
+void coreboot_get_table_location(uint64_t *address, uint32_t *size)
+{
+ *address = coreboot_table_addr;
+ *size = coreboot_table_size;
+}
+
void coreboot_table_setup(void *base)
{
cb_header_t *header = base;
@@ -118,6 +126,8 @@ void coreboot_table_setup(void *base)
ERROR("coreboot table signature corrupt!\n");
return;
}
+ coreboot_table_addr = (uint64_t) base;
+ coreboot_table_size = header->header_bytes + header->table_bytes;
ptr = base + header->header_bytes;
for (i = 0; i < header->table_entries; i++) {
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
index e52cbed73..faccfdff4 100644
--- a/lib/libc/printf.c
+++ b/lib/libc/printf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -81,6 +81,7 @@ static int unsigned_num_print(unsigned long long int unum, unsigned int radix,
* %x - hexadecimal format
* %s - string format
* %d or %i - signed decimal format
+ * %c - character format
* %u - unsigned decimal format
* %p - pointer format
*
@@ -130,6 +131,10 @@ loop:
count += unsigned_num_print(unum, 10,
padc, padn);
break;
+ case 'c':
+ (void)putchar(va_arg(args, int));
+ count++;
+ break;
case 's':
str = va_arg(args, char *);
count += string_print(str);
diff --git a/lib/libc/snprintf.c b/lib/libc/snprintf.c
index 0e3256cde..21d34168f 100644
--- a/lib/libc/snprintf.c
+++ b/lib/libc/snprintf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -85,6 +85,7 @@ static void unsigned_num_print(char **s, size_t n, size_t *chars_printed,
*
* %x (or %X) - hexadecimal format
* %d or %i - signed decimal format
+ * %c - character format
* %s - string format
* %u - unsigned decimal format
* %p - pointer format
@@ -181,6 +182,9 @@ loop:
unsigned_num_print(&s, n, &chars_printed,
unum, 10, padc, padn, false);
break;
+ case 'c':
+ CHECK_AND_PUT_CHAR(s, n, chars_printed, va_arg(args, int));
+ break;
case 's':
str = va_arg(args, char *);
string_print(&s, n, &chars_printed, str);
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 9fe7cf4b7..20c6415b9 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -106,7 +106,6 @@ int fdt_check_header(const void *fdt)
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
-
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
@@ -115,9 +114,7 @@ int fdt_check_header(const void *fdt)
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
- }
- if (!can_assume(VALID_DTB)) {
/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
@@ -165,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
- uint32_t tag;
+ uint32_t tag, len, sum;
int offset = startoffset;
const char *p;
@@ -191,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
+
+ len = fdt32_to_cpu(*lenp);
+ sum = len + offset;
+ if (!can_assume(VALID_DTB) &&
+ (INT_MAX <= sum || sum < (uint32_t) offset))
+ return FDT_END; /* premature end */
+
/* skip-name offset, length and value */
- offset += sizeof(struct fdt_property) - FDT_TAGSIZE
- + fdt32_to_cpu(*lenp);
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
+
if (!can_assume(LATEST) &&
- fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
- ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+ fdt_version(fdt) < 0x10 && len >= 8 &&
+ ((offset - len) % 8) != 0)
offset += 4;
break;
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
index cef42f46c..e13a38b32 100644
--- a/plat/arm/board/morello/morello_bl31_setup.c
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -12,6 +12,7 @@
#include <services/arm_arch_svc.h>
#include "morello_def.h"
+#include "morello_private.h"
#include <platform_def.h>
#ifdef TARGET_PLATFORM_SOC
@@ -33,6 +34,8 @@ scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id)
const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
{
+ ops->pwr_domain_off = morello_pwr_domain_off;
+ ops->pwr_domain_suspend = morello_pwr_domain_suspend;
return css_scmi_override_pm_ops(ops);
}
diff --git a/plat/arm/board/morello/morello_pm.c b/plat/arm/board/morello/morello_pm.c
new file mode 100644
index 000000000..dda006eac
--- /dev/null
+++ b/plat/arm/board/morello/morello_pm.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+#include "morello_private.h"
+
+/*******************************************************************************
+ * Morello specific functions called when turning off or suspending a power
+ * domain. Both additionally disable the GIC redistributor interface as cores
+ * are disabled to let cluster-PPU state transition to completion when a
+ * cluster is powered down.
+ ******************************************************************************/
+void morello_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ css_pwr_domain_off(target_state);
+ plat_arm_gic_redistif_off();
+}
+
+void morello_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ css_pwr_domain_suspend(target_state);
+ plat_arm_gic_redistif_off();
+}
diff --git a/plat/arm/board/morello/morello_private.h b/plat/arm/board/morello/morello_private.h
new file mode 100644
index 000000000..ea2fce974
--- /dev/null
+++ b/plat/arm/board/morello/morello_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MORELLO_PRIVATE_H
+#define MORELLO_PRIVATE_H
+
+#include <lib/psci/psci.h>
+
+void morello_pwr_domain_off(const psci_power_state_t *target_state);
+void morello_pwr_domain_suspend(const psci_power_state_t *target_state);
+
+#endif /* MORELLO_PRIVATE_H */
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
index 0f0cabbad..0ae769338 100644
--- a/plat/arm/board/morello/platform.mk
+++ b/plat/arm/board/morello/platform.mk
@@ -49,6 +49,7 @@ BL31_SOURCES := ${MORELLO_CPU_SOURCES} \
${INTERCONNECT_SOURCES} \
${MORELLO_GIC_SOURCES} \
${MORELLO_BASE}/morello_bl31_setup.c \
+ ${MORELLO_BASE}/morello_pm.c \
${MORELLO_BASE}/morello_topology.c \
${MORELLO_BASE}/morello_security.c \
drivers/arm/css/sds/sds.c
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index bd0566006..db7215f43 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,7 @@
#include <plat/arm/common/plat_arm.h>
#include "n1sdp_def.h"
+#include "n1sdp_private.h"
#include <platform_def.h>
/*
@@ -69,6 +70,8 @@ scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id)
const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
{
+ ops->pwr_domain_off = n1sdp_pwr_domain_off;
+ ops->pwr_domain_suspend = n1sdp_pwr_domain_suspend;
return css_scmi_override_pm_ops(ops);
}
diff --git a/plat/arm/board/n1sdp/n1sdp_pm.c b/plat/arm/board/n1sdp/n1sdp_pm.c
new file mode 100644
index 000000000..e43832a23
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_pm.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+#include "n1sdp_private.h"
+
+/*******************************************************************************
+ * N1SDP specific functions called when turning off or suspending a power
+ * domain. Both additionally disable the GIC redistributor interface as cores
+ * are disabled to let cluster-PPU state transition to completion when a
+ * cluster is powered down.
+ ******************************************************************************/
+void n1sdp_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ css_pwr_domain_off(target_state);
+ plat_arm_gic_redistif_off();
+}
+
+void n1sdp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ css_pwr_domain_suspend(target_state);
+ plat_arm_gic_redistif_off();
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_private.h b/plat/arm/board/n1sdp/n1sdp_private.h
new file mode 100644
index 000000000..7a5c51d97
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef N1SDP_PRIVATE_H
+#define N1SDP_PRIVATE_H
+
+#include <lib/psci/psci.h>
+
+void n1sdp_pwr_domain_off(const psci_power_state_t *target_state);
+void n1sdp_pwr_domain_suspend(const psci_power_state_t *target_state);
+
+#endif /* N1SDP_PRIVATE_H */
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 9c0cc022c..bd6261454 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -47,6 +47,7 @@ BL31_SOURCES := ${N1SDP_CPU_SOURCES} \
${INTERCONNECT_SOURCES} \
${N1SDP_GIC_SOURCES} \
${N1SDP_BASE}/n1sdp_bl31_setup.c \
+ ${N1SDP_BASE}/n1sdp_pm.c \
${N1SDP_BASE}/n1sdp_topology.c \
${N1SDP_BASE}/n1sdp_security.c \
drivers/arm/css/sds/sds.c
diff --git a/services/spd/opteed/opteed.mk b/services/spd/opteed/opteed.mk
index 477b45d98..f394744e9 100644
--- a/services/spd/opteed/opteed.mk
+++ b/services/spd/opteed/opteed.mk
@@ -31,4 +31,5 @@ $(warning "OPTEE_ALLOW_SMC_LOAD is enabled which may result in an insecure \
platform")
$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
$(eval $(call add_define,OPTEE_ALLOW_SMC_LOAD))
+include lib/libfdt/libfdt.mk
endif
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index f069775d2..4d055db17 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -24,9 +24,13 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
+#include <lib/coreboot.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/optee_utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
+#if OPTEE_ALLOW_SMC_LOAD
+#include <libfdt.h>
+#endif /* OPTEE_ALLOW_SMC_LOAD */
#include <plat/common/platform.h>
#include <tools_share/uuid.h>
@@ -51,6 +55,10 @@ static bool opteed_allow_load;
DEFINE_SVC_UUID2(optee_image_load_uuid,
0xb1eafba3, 0x5d31, 0x4612, 0xb9, 0x06,
0xc4, 0xc7, 0xa4, 0xbe, 0x3c, 0xc0);
+
+#define OPTEED_FDT_SIZE 256
+static uint8_t fdt_buf[OPTEED_FDT_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
+
#else
static int32_t opteed_init(void);
#endif
@@ -209,6 +217,91 @@ static int32_t opteed_init(void)
#endif /* !OPTEE_ALLOW_SMC_LOAD */
#if OPTEE_ALLOW_SMC_LOAD
+#if COREBOOT
+/*
+ * Adds a firmware/coreboot node with the coreboot table information to a device
+ * tree. Returns zero on success or if there is no coreboot table information;
+ * failure code otherwise.
+ */
+static int add_coreboot_node(void *fdt)
+{
+ int ret;
+ uint64_t coreboot_table_addr;
+ uint32_t coreboot_table_size;
+ struct {
+ uint64_t addr;
+ uint32_t size;
+ } reg_node;
+ coreboot_get_table_location(&coreboot_table_addr, &coreboot_table_size);
+ if (!coreboot_table_addr || !coreboot_table_size) {
+ WARN("Unable to get coreboot table location for device tree");
+ return 0;
+ }
+ ret = fdt_begin_node(fdt, "firmware");
+ if (ret)
+ return ret;
+
+ ret = fdt_property(fdt, "ranges", NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = fdt_begin_node(fdt, "coreboot");
+ if (ret)
+ return ret;
+
+ ret = fdt_property_string(fdt, "compatible", "coreboot");
+ if (ret)
+ return ret;
+
+ reg_node.addr = cpu_to_fdt64(coreboot_table_addr);
+ reg_node.size = cpu_to_fdt32(coreboot_table_size);
+ ret = fdt_property(fdt, "reg", &reg_node,
+ sizeof(uint64_t) + sizeof(uint32_t));
+ if (ret)
+ return ret;
+
+ ret = fdt_end_node(fdt);
+ if (ret)
+ return ret;
+
+ return fdt_end_node(fdt);
+}
+#endif /* COREBOOT */
+
+/*
+ * Creates a device tree for passing into OP-TEE. Currently is populated with
+ * the coreboot table address.
+ * Returns 0 on success, error code otherwise.
+ */
+static int create_opteed_dt(void)
+{
+ int ret;
+
+ ret = fdt_create(fdt_buf, OPTEED_FDT_SIZE);
+ if (ret)
+ return ret;
+
+ ret = fdt_finish_reservemap(fdt_buf);
+ if (ret)
+ return ret;
+
+ ret = fdt_begin_node(fdt_buf, "");
+ if (ret)
+ return ret;
+
+#if COREBOOT
+ ret = add_coreboot_node(fdt_buf);
+ if (ret)
+ return ret;
+#endif /* COREBOOT */
+
+ ret = fdt_end_node(fdt_buf);
+ if (ret)
+ return ret;
+
+ return fdt_finish(fdt_buf);
+}
+
/*******************************************************************************
* This function is responsible for handling the SMC that loads the OP-TEE
* binary image via a non-secure SMC call. It takes the size and physical
@@ -232,6 +325,7 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
uint64_t target_size;
entry_point_info_t optee_ep_info;
uint32_t linear_id = plat_my_core_pos();
+ uint64_t dt_addr = 0;
mapped_data_pa = page_align(data_pa, DOWN);
mapped_data_va = mapped_data_pa;
@@ -292,12 +386,20 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
/* Save the non-secure state */
cm_el1_sysregs_context_save(NON_SECURE);
+ rc = create_opteed_dt();
+ if (rc) {
+ ERROR("Failed device tree creation %d\n", rc);
+ return rc;
+ }
+ dt_addr = (uint64_t)fdt_buf;
+ flush_dcache_range(dt_addr, OPTEED_FDT_SIZE);
+
opteed_init_optee_ep_state(&optee_ep_info,
opteed_rw,
image_pa,
0,
0,
- 0,
+ dt_addr,
&opteed_sp_context[linear_id]);
if (opteed_init_with_entry_point(&optee_ep_info) == 0) {
rc = -EFAULT;