Integrate newlib into opteesp environment
Use newlib external component in opteesp targeted builds along the
necessary compiler and linker options. Also adding/modifying the source
files for startup, heap handling and trace features. The sp.ld.S file
is based on ta/arch/arm/ta.ld.S from optee_os
6be0dbcaa11394a2ad5a46ac77e2f76e31a41722.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: Ie9f3e8f0fb755bb88cc33feffda86fbbbf3c7fce
diff --git a/environments/opteesp/component.cmake b/environments/opteesp/component.cmake
index bd6e036..f6a65cd 100644
--- a/environments/opteesp/component.cmake
+++ b/environments/opteesp/component.cmake
@@ -10,24 +10,40 @@
endif()
target_sources(${TGT} PRIVATE
- "${CMAKE_CURRENT_LIST_DIR}/libsp_entry.c"
+ "${CMAKE_CURRENT_LIST_DIR}/optee_sp_header.c"
+ "${CMAKE_CURRENT_LIST_DIR}/newlib_init.c"
+ "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_assert.c"
+ "${CMAKE_CURRENT_LIST_DIR}/newlib_sp_heap.c"
+ "${CMAKE_CURRENT_LIST_DIR}/sp_entry.c"
"${CMAKE_CURRENT_LIST_DIR}/sp_trace.c"
- )
+)
target_include_directories(${TGT}
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/include"
)
-if (NOT DEFINED TRACE_PREFIX)
- set(TRACE_PREFIX "SP" CACHE STRING "Trace prefix")
-endif()
-
-if (NOT DEFINED TRACE_LEVEL)
- set(TRACE_LEVEL "TRACE_LEVEL_ERROR" CACHE STRING "Trace level")
-endif()
+# Default trace configuration, can be overwritten by setting the same variables
+# in the deployment specific file before including this file.
+set(TRACE_PREFIX "SP" CACHE STRING "Trace prefix")
+set(TRACE_LEVEL "TRACE_LEVEL_ERROR" CACHE STRING "Trace level")
target_compile_definitions(${TGT} PRIVATE
TRACE_LEVEL=${TRACE_LEVEL}
TRACE_PREFIX="${TRACE_PREFIX}"
)
+
+include(../../../external/newlib/newlib.cmake)
+
+target_link_libraries(${TGT} PRIVATE
+ c
+ nosys
+)
+
+target_link_options(${TGT} PRIVATE
+ -Wl,--hash-style=sysv
+ -Wl,--as-needed
+ -Wl,--gc-sections
+)
+
+compiler_set_linker_script(TARGET ${TGT} FILE ${CMAKE_CURRENT_LIST_DIR}/sp.ld.S DEF ARM64=1)
diff --git a/environments/opteesp/default_toolchain_file.cmake b/environments/opteesp/default_toolchain_file.cmake
index 34ca0c9..f0e0277 100644
--- a/environments/opteesp/default_toolchain_file.cmake
+++ b/environments/opteesp/default_toolchain_file.cmake
@@ -15,10 +15,6 @@
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_POSITION_INDEPENDENT_CODE True)
-#set(CMAKE_C_FLAGS_INIT --specs=nosys.specs)
-#set(CMAKE_CXX_FLAGS_INIT --specs=nosys.specs)
-#set(CMAKE_EXE_LINKER_FLAGS_INIT --specs=nosys.specs)
-
include($ENV{TS_ROOT}/tools/cmake/compiler/GCC.cmake REQUIRED)
include($ENV{TS_ROOT}/tools/cmake/compiler/config_iface.cmake REQUIRED)
# Set mandatory compiler and linker flags for this environment:
diff --git a/environments/opteesp/include/libc_init.h b/environments/opteesp/include/libc_init.h
new file mode 100644
index 0000000..232c3c0
--- /dev/null
+++ b/environments/opteesp/include/libc_init.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LIBC_INIT_H_
+#define LIBC_INIT_H_
+
+void libc_init(void);
+
+#endif /* LIBC_INIT_H_ */
diff --git a/environments/opteesp/include/optee_sp_internal_api.h b/environments/opteesp/include/optee_sp_internal_api.h
new file mode 100644
index 0000000..d275caa
--- /dev/null
+++ b/environments/opteesp/include/optee_sp_internal_api.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef OPTEE_SP_INTERNAL_API_H_
+#define OPTEE_SP_INTERNAL_API_H_
+
+#include <stdint.h>
+
+/*
+ * The file describes the API between the OP-TEE and the SP.
+ * The SP code base should also contain a header file named
+ * "optee_sp_user_defines.h" for passing the following definitions to the SP dev
+ * kit:
+ * * OPTEE_SP_HEAP_SIZE: Heap size in bytes
+ * * OPTEE_SP_UUID: UUID of the SP as an sp_uuid structure
+ * * OPTEE_SP_STACK_SIZE: Stack size in bytes
+ * * OPTEE_SP_FLAGS: SP attributes (currently none available, set to zero)
+ */
+
+/*
+ * SP header types
+ */
+struct optee_sp_uuid {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t timeHiAndVersion;
+ uint8_t clockSeqAndNode[8];
+};
+
+struct optee_sp_head {
+ struct optee_sp_uuid uuid;
+ uint32_t stack_size;
+ uint32_t flags;
+ uint64_t reserved;
+};
+
+#endif /* OPTEE_SP_INTERNAL_API_H_ */
diff --git a/environments/opteesp/libsp_entry.c b/environments/opteesp/libsp_entry.c
deleted file mode 100644
index 68f410b..0000000
--- a/environments/opteesp/libsp_entry.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include "ffa_internal_api.h"
-#include "optee_sp_internal_api.h"
-#include "sp_api.h"
-
-void __noreturn optee_sp_entry(uintptr_t a0, uintptr_t a1, uintptr_t a2,
- uintptr_t a3)
-{
- (void)a1;
- (void)a2;
- (void)a3;
-
- sp_main((struct ffa_init_info *)a0);
-}
-
-void __noreturn optee_sp_panic(void)
-{
- while (1)
- ;
-}
diff --git a/environments/opteesp/newlib_init.c b/environments/opteesp/newlib_init.c
new file mode 100644
index 0000000..9450a68
--- /dev/null
+++ b/environments/opteesp/newlib_init.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include "libc_init.h"
+
+/* Comes from libc */
+void __libc_init_array(void);
+
+void _init(void)
+{
+ /* Dummy */
+}
+
+void libc_init(void)
+{
+ /* Initializing global variables, calling constructors */
+ __libc_init_array();
+}
diff --git a/environments/opteesp/newlib_sp_assert.c b/environments/opteesp/newlib_sp_assert.c
new file mode 100644
index 0000000..5a2d428
--- /dev/null
+++ b/environments/opteesp/newlib_sp_assert.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include <assert.h>
+#include "compiler.h"
+#include "trace.h"
+
+/*
+ * The generic trace function called on assert fail.
+ */
+void __noreturn __assert_func(const char *file, int line, const char *func, const char *failedexpr)
+{
+#if TRACE_LEVEL >= TRACE_LEVEL_ERROR
+ trace_printf(func, line, TRACE_LEVEL_ERROR, "assertion %s failed", failedexpr);
+#endif /* TRACE_LEVEL */
+
+ while (1)
+ ;
+}
diff --git a/environments/opteesp/newlib_sp_heap.c b/environments/opteesp/newlib_sp_heap.c
new file mode 100644
index 0000000..77a288a
--- /dev/null
+++ b/environments/opteesp/newlib_sp_heap.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include "compiler.h"
+#include "optee_sp_user_defines.h"
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+/* Allocating heap area */
+#ifndef OPTEE_SP_HEAP_SIZE
+#error "OPTEE_SP_HEAP_SIZE is not defined in SP"
+#endif
+
+static uint8_t sp_heap[OPTEE_SP_HEAP_SIZE] __aligned(16);
+static uint8_t *program_break = sp_heap;
+
+/**
+ * Basic sbrk implementation which increases the program break through the
+ * sp_heap buffer.
+ */
+void *_sbrk(ptrdiff_t incr)
+{
+ uint8_t *previous_break = program_break;
+ uint8_t *new_break = program_break + incr;
+
+ if ((new_break < sp_heap) || (new_break > (sp_heap + sizeof(sp_heap)))) {
+ errno = ENOMEM;
+ return (void *)(uintptr_t) -1;
+ }
+
+ program_break += incr;
+
+ return (void *) previous_break;
+}
diff --git a/environments/opteesp/optee_sp_header.c b/environments/opteesp/optee_sp_header.c
new file mode 100644
index 0000000..25056da
--- /dev/null
+++ b/environments/opteesp/optee_sp_header.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include <compiler.h>
+#include "optee_sp_internal_api.h"
+#include "optee_sp_user_defines.h"
+
+#ifndef OPTEE_SP_UUID
+#error "OPTEE_SP_UUID is not defined in SP"
+#endif
+
+#ifndef OPTEE_SP_STACK_SIZE
+#error "OPTEE_SP_STACK_SIZE is not defined in SP"
+#endif
+
+#ifndef OPTEE_SP_FLAGS
+#error "OPTEE_SP_FLAGS is not defined in SP"
+#endif
+
+const struct optee_sp_head sp_head __section(".sp_head") = {
+ .uuid = OPTEE_SP_UUID,
+ .stack_size = OPTEE_SP_STACK_SIZE,
+ .flags = OPTEE_SP_FLAGS,
+ .reserved = UINT64_MAX
+};
diff --git a/environments/opteesp/sp.ld.S b/environments/opteesp/sp.ld.S
new file mode 100644
index 0000000..a1f3fb3
--- /dev/null
+++ b/environments/opteesp/sp.ld.S
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause */
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V. All rights reserved.
+ * Copyright (c) 2015, Linaro Limited. All rights reserved.
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+#ifdef ARM32
+OUTPUT_FORMAT("elf32-littlearm")
+OUTPUT_ARCH(arm)
+#endif
+#ifdef ARM64
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+#endif
+
+EXTERN(sp_head)
+ENTRY(__sp_entry)
+
+SECTIONS {
+ .sp_head : {*(.sp_head)}
+ .text : {
+ __text_start = .;
+ *(.text .text.*)
+ *(.stub)
+ *(.glue_7)
+ *(.glue_7t)
+ *(.gnu.linkonce.t.*)
+ /* Workaround for an erratum in ARM's VFP11 coprocessor */
+ *(.vfp11_veneer)
+ __text_end = .;
+ }
+ .plt : { *(.plt) }
+
+ .eh_frame_hdr : {
+ *(.eh_frame_hdr)
+ *(.eh_frame_entry .eh_frame_entry.*)
+ }
+ .eh_frame : { KEEP(*(.eh_frame)) *(.eh_frame.*) }
+ .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) }
+ .rodata : {
+ *(.gnu.linkonce.r.*)
+ *(.rodata .rodata.*)
+ }
+ .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
+ /* .ARM.exidx is sorted, so has to go in its own output section. */
+ PROVIDE_HIDDEN(__exidx_start = .);
+ .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
+ PROVIDE_HIDDEN(__exidx_end = .);
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .hash : { *(.hash) }
+
+ /* Page align to allow dropping execute bit for RW data */
+ . = ALIGN(4096);
+
+ .dynamic : { *(.dynamic) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .got : { *(.got.plt) *(.got) }
+ .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+ .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+ .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+ .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rel.dyn : { *(.rel.dyn) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+
+ .data : { *(.data .data.* .gnu.linkonce.d.*) }
+ .bss : {
+ *(.bss .bss.* .gnu.linkonce.b.* COMMON)
+ }
+
+ /DISCARD/ : { *(.interp) }
+}
diff --git a/environments/opteesp/sp_entry.c b/environments/opteesp/sp_entry.c
new file mode 100644
index 0000000..6249407
--- /dev/null
+++ b/environments/opteesp/sp_entry.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "compiler.h"
+#include "libc_init.h"
+#include "sp_api.h"
+
+/*
+ * According to the FF-A specification an optional initialization descriptor can
+ * be passed to the SP in w0/x0-w3/x3 registers (a0-a3 parameters). As the exact
+ * register is implementation defined the first four registers are forwarded to
+ * the user code.
+ */
+void __noreturn __sp_entry(uintptr_t a0, uintptr_t a1,
+ uintptr_t a2, uintptr_t a3);
+void __noreturn __sp_entry(uintptr_t a0, uintptr_t a1,
+ uintptr_t a2, uintptr_t a3)
+{
+ (void)a1;
+ (void)a2;
+ (void)a3;
+
+ libc_init();
+
+ sp_main((struct ffa_init_info *)a0);
+}