SPRT: Rename the folder name to 'runtime'
The original name 'sprt' can be confusing if user did not read
SPRTL related document, hence rename it as 'runtime' to
indicate it is a secure partition runtime API set.
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Change-Id: I3ba7d5e80dd2ee32d52463bcdf012a2f5bf6017c
diff --git a/secure_fw/partitions/lib/runtime/CMakeLists.txt b/secure_fw/partitions/lib/runtime/CMakeLists.txt
new file mode 100644
index 0000000..395045e
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/CMakeLists.txt
@@ -0,0 +1,77 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 3.15)
+
+add_library(tfm_sprt STATIC)
+
+target_include_directories(tfm_sprt
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ ${CMAKE_SOURCE_DIR}/secure_fw/include
+)
+
+target_sources(tfm_sprt
+ PRIVATE
+ ./crt_memcmp.c
+ ./crt_memmove.c
+ ./crt_strnlen.c
+ ./service_api.c
+ ${CMAKE_SOURCE_DIR}/secure_fw/shared/crt_memcpy.c
+ ${CMAKE_SOURCE_DIR}/secure_fw/shared/crt_memset.c
+ $<$<BOOL:${CONFIG_TFM_PARTITION_META}>:./sprt_partition_metadata_indicator.c>
+ $<$<BOOL:${CONFIG_TFM_PARTITION_META}>:./rt_main.c>
+ $<$<BOOL:${CONFIG_TFM_SPM_BACKEND_IPC}>:./sfn_common_thread.c>
+)
+
+target_link_libraries(tfm_sprt
+ PUBLIC
+ $<$<BOOL:${TFM_SP_LOG_RAW_ENABLED}>:tfm_sp_log_raw>
+ PRIVATE
+ platform_s
+ tfm_secure_api
+ psa_interface
+ tfm_boot_status
+)
+
+target_compile_definitions(tfm_partition_defs
+ INTERFACE
+ TFM_PARTITION_LOG_LEVEL=${TFM_PARTITION_LOG_LEVEL}
+ $<$<BOOL:${TFM_SP_LOG_RAW_ENABLED}>:TFM_SP_LOG_RAW_ENABLED>
+)
+
+target_include_directories(tfm_partitions
+ INTERFACE
+ $<BUILD_INTERFACE:$<$<BOOL:${CONFIG_TFM_PARTITION_META}>:${CMAKE_CURRENT_SOURCE_DIR}/include>>
+)
+
+# Create a dedicated tfm_sp_log_raw library for some regression test modules
+# which don't include tfm_sprt.
+# tfm_sp_log_raw shall be controlled by TFM_SP_LOG_RAW_ENABLED.
+# Otherwise, build will fail if TFM_SP_LOG_RAW_ENABLED is disabled since some
+# definitions are unavailable with TFM_SP_LOG_RAW_ENABLED disabled.
+if (TFM_SP_LOG_RAW_ENABLED)
+ add_library(tfm_sp_log_raw INTERFACE)
+
+ target_sources(tfm_sp_log_raw
+ INTERFACE
+ ${CMAKE_CURRENT_SOURCE_DIR}/tfm_sp_log_raw.c
+ ${CMAKE_SOURCE_DIR}/platform/ext/common/tfm_hal_sp_logdev_periph.c
+ )
+
+ target_include_directories(tfm_sp_log_raw
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ )
+
+ target_link_libraries(tfm_sp_log_raw
+ INTERFACE
+ platform_s
+ tfm_partition_defs
+ tfm_secure_api
+ )
+endif()
diff --git a/secure_fw/partitions/lib/runtime/crt_memcmp.c b/secure_fw/partitions/lib/runtime/crt_memcmp.c
new file mode 100644
index 0000000..da17839
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_memcmp.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+ int result = 0;
+ const uint8_t *p1 = (const uint8_t *)s1;
+ const uint8_t *p2 = (const uint8_t *)s2;
+
+ while (n--) {
+ if ((*p1 != *p2) && (result == 0)) {
+ result = *p1 - *p2;
+ } else {
+ p1++;
+ p2++;
+ }
+ }
+ return result;
+}
diff --git a/secure_fw/partitions/lib/runtime/crt_memmove.c b/secure_fw/partitions/lib/runtime/crt_memmove.c
new file mode 100644
index 0000000..a4dbf7b
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_memmove.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+#include "crt_impl_private.h"
+
+static void *memcpy_r(void *dest, const void *src, size_t n)
+{
+ union composite_addr_t p_dst, p_src;
+
+ p_dst.uint_addr = (uintptr_t)dest + n;
+ p_src.uint_addr = (uintptr_t)src + n;
+
+ /* Byte copy for unaligned address. check the last bit of address. */
+ while (n && (ADDR_WORD_UNALIGNED(p_dst.uint_addr) ||
+ ADDR_WORD_UNALIGNED(p_src.uint_addr))) {
+ *(--p_dst.p_byte) = *(--p_src.p_byte);
+ n--;
+ }
+
+ /* Quad byte copy for aligned address. */
+ while (n >= sizeof(uint32_t)) {
+ *(--p_dst.p_word) = *(--p_src.p_word);
+ n -= sizeof(uint32_t);
+ }
+
+ /* Byte copy for the remaining bytes. */
+ while (n--) {
+ *(--p_dst.p_byte) = *(--p_src.p_byte);
+ }
+
+ return dest;
+}
+
+/* Mind the direction for copying in memcpy! */
+#define memcpy_f memcpy
+
+/*
+ * For overlapped memory area:
+ * 1) overlapped: use reverse memory move.
+ * 2) non-overlapped: use forward memory move.
+ */
+void *memmove(void *dest, const void *src, size_t n)
+{
+ if (src >= dest) {
+ return memcpy_f(dest, src, n);
+ } else {
+ return memcpy_r(dest, src, n);
+ }
+}
diff --git a/secure_fw/partitions/lib/runtime/crt_strnlen.c b/secure_fw/partitions/lib/runtime/crt_strnlen.c
new file mode 100644
index 0000000..13872c6
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_strnlen.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+
+size_t tfm_strnlen(const char *s, size_t maxlen)
+{
+ size_t idx;
+
+ for (idx = 0; idx < maxlen; idx++) {
+ if (s[idx] == '\0') {
+ return idx;
+ }
+ }
+
+ return idx;
+}
diff --git a/secure_fw/partitions/lib/runtime/include/rt_main.h b/secure_fw/partitions/lib/runtime/include/rt_main.h
new file mode 100644
index 0000000..22169ce
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/include/rt_main.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __RT_MAIN_H__
+#define __RT_MAIN_H__
+
+/* Common partition runtime entry - 'sprt_main' */
+void sprt_main(void);
+
+#endif /* __RT_MAIN_H__ */
diff --git a/secure_fw/partitions/lib/runtime/include/service_api.h b/secure_fw/partitions/lib/runtime/include/service_api.h
new file mode 100644
index 0000000..57f3e3d
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/include/service_api.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __SERVICE_API_H__
+#define __SERVICE_API_H__
+
+#include <stdint.h>
+#include "tfm_boot_status.h"
+
+/**
+ * \brief Retrieve secure partition related data from shared memory area, which
+ * stores shared data between bootloader and runtime firmware.
+ *
+ * \param[in] major_type Major type.
+ * \param[out] boot_data Pointer to boot data.
+ * \param[in] len The length of the boot data.
+ */
+int32_t tfm_core_get_boot_data(uint8_t major_type,
+ struct tfm_boot_data *boot_data,
+ uint32_t len);
+
+#endif /* __SERVICE_API_H__ */
diff --git a/secure_fw/partitions/lib/runtime/include/tfm_sp_log.h b/secure_fw/partitions/lib/runtime/include/tfm_sp_log.h
new file mode 100644
index 0000000..bf2f67d
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/include/tfm_sp_log.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SP_LOG_H__
+#define __TFM_SP_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The Secure Partition log levels */
+#define TFM_PARTITION_LOG_LEVEL_DEBUG 3 /* All log APIs output */
+#define TFM_PARTITION_LOG_LEVEL_INFO 2 /*
+ * All log APIs output except
+ * LOG_DBGFMT
+ */
+#define TFM_PARTITION_LOG_LEVEL_ERROR 1 /*
+ * Only LOG_ERRFMT APIs output.
+ */
+#define TFM_PARTITION_LOG_LEVEL_SILENCE 0 /* All log APIs are suppressed */
+
+#ifndef TFM_PARTITION_LOG_LEVEL
+#error "TFM_PARTITION_LOG_LEVEL not defined!"
+#endif
+
+#if (TFM_PARTITION_LOG_LEVEL > TFM_PARTITION_LOG_LEVEL_DEBUG) || \
+ (TFM_PARTITION_LOG_LEVEL < TFM_PARTITION_LOG_LEVEL_SILENCE)
+#error "Incorrect TFM_PARTITION_LOG_LEVEL value!"
+#endif
+
+#if (TFM_PARTITION_LOG_LEVEL == TFM_PARTITION_LOG_LEVEL_DEBUG)
+#define LOG_DBGFMT(...) tfm_sp_log_printf(__VA_ARGS__)
+#else
+#define LOG_DBGFMT(...)
+#endif
+
+#if (TFM_PARTITION_LOG_LEVEL >= TFM_PARTITION_LOG_LEVEL_INFO)
+#define LOG_INFFMT(...) tfm_sp_log_printf(__VA_ARGS__)
+#else
+#define LOG_INFFMT(...)
+#endif
+
+#if (TFM_PARTITION_LOG_LEVEL >= TFM_PARTITION_LOG_LEVEL_ERROR)
+#define LOG_ERRFMT(...) tfm_sp_log_printf(__VA_ARGS__)
+#else
+#define LOG_ERRFMT(...)
+#endif
+
+/**
+ * \brief Print log messages
+ *
+ * \param[in] fmt Formatted string
+ * \param[in] ... Variable length argument
+ *
+ * \retval >= 0 Number of chars printed
+ * \retval < 0 TF-M HAL error code
+ *
+ * \note This function has the similar input argument format as
+ * the 'printf' function. But it supports only some basic
+ * formats like 'sdicpuxX' and '%'. It will output
+ * "[Unsupported Tag]" when none of the above formats match
+ *
+ * \details The following output formats are supported.
+ * %s - string
+ * %d - decimal signed integer (same for %i)
+ * %u - decimal unsigned integer
+ * %x - hex in lowercase
+ * %X - hex in uppercase
+ * %p - hex address of a pointer in lowercase
+ * %c - character
+ * %% - the '%' symbol
+ */
+int tfm_sp_log_printf(const char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_SP_LOG_H__ */
diff --git a/secure_fw/partitions/lib/runtime/include/tfm_strnlen.h b/secure_fw/partitions/lib/runtime/include/tfm_strnlen.h
new file mode 100644
index 0000000..4b20c58
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/include/tfm_strnlen.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_STRNLEN_H__
+#define __TFM_STRNLEN_H__
+
+/**
+ * \brief Return the length of a given string, up to a maximum of maxlen bytes.
+ *
+ * \param[in] s Points to the string to be examined.
+ * \param[in] maxlen The maximum number of characters to examine.
+ */
+size_t tfm_strnlen(const char *s, size_t maxlen);
+
+#endif /* __TFM_STRNLEN_H__ */
diff --git a/secure_fw/partitions/lib/runtime/rt_main.c b/secure_fw/partitions/lib/runtime/rt_main.c
new file mode 100644
index 0000000..e9ad7be
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/rt_main.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "compiler_ext_defs.h"
+#include "runtime_defs.h"
+#include "sprt_partition_metadata_indicator.h"
+#include "rt_main.h"
+
+extern void common_sfn_thread(void);
+
+__used static uintptr_t runtime_init_c(void)
+{
+ struct runtime_metadata_t *p_rt_meta;
+
+ p_rt_meta = PART_METADATA();
+
+ if (p_rt_meta->n_sfn == 0) {
+ /* IPC Partition */
+ return p_rt_meta->entry;
+ } else {
+ /* SFN Partition */
+ return (uintptr_t)common_sfn_thread;
+ }
+}
+
+#if defined(__ICCARM__)
+#pragma required = runtime_init_c
+#endif
+
+__naked void sprt_main(void)
+{
+ __asm volatile(
+#if !defined(__ICCARM__)
+ ".syntax unified \n"
+#endif
+ "bl runtime_init_c \n"
+ "bx r0 \n"
+ );
+}
diff --git a/secure_fw/partitions/lib/runtime/service_api.c b/secure_fw/partitions/lib/runtime/service_api.c
new file mode 100644
index 0000000..f145448
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/service_api.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cmsis_compiler.h"
+#include "service_api.h"
+#ifdef TFM_PSA_API
+#include "psa/service.h"
+#include "svc_num.h"
+#else
+#include "tfm_core_svc.h"
+#endif /* TFM_PSA_API */
+#include "utilities.h"
+
+__attribute__((naked))
+int32_t tfm_core_get_boot_data(uint8_t major_type,
+ struct tfm_boot_data *boot_status,
+ uint32_t len)
+{
+ __ASM volatile(
+ "SVC "M2S(TFM_SVC_GET_BOOT_DATA)" \n"
+ "BX lr \n"
+ );
+}
+
+#if defined TFM_PSA_API && TFM_LVL != 1
+/* Entry point when Partition FLIH functions return */
+__attribute__((naked))
+void tfm_flih_func_return(psa_flih_result_t result)
+{
+ __ASM volatile("SVC "M2S(TFM_SVC_FLIH_FUNC_RETURN)" \n"
+ "BX r0 \n"
+ );
+}
+#endif /* TFM_PSA_API && TFM_LVL != 1 */
diff --git a/secure_fw/partitions/lib/runtime/sfn_common_thread.c b/secure_fw/partitions/lib/runtime/sfn_common_thread.c
new file mode 100644
index 0000000..2a2d649
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/sfn_common_thread.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "runtime_defs.h"
+#include "sprt_partition_metadata_indicator.h"
+
+#include "psa/error.h"
+#include "psa/service.h"
+
+void common_sfn_thread(void)
+{
+ psa_signal_t sig_asserted, signal_mask, sig;
+ psa_msg_t msg;
+ struct runtime_metadata_t *meta;
+ service_fn_t *p_sfn_table;
+ sfn_init_fn_t sfn_init;
+
+ meta = PART_METADATA();
+ sfn_init = (sfn_init_fn_t)meta->entry;
+ p_sfn_table = (service_fn_t *)meta->sfn_table;
+ signal_mask = (1 << meta->n_sfn) - 1;
+
+ if (sfn_init && sfn_init() != PSA_SUCCESS) {
+ psa_panic();
+ }
+
+ while (1) {
+ sig_asserted = psa_wait(signal_mask, PSA_BLOCK);
+ /* Handle signals */
+ for (int i = 0; sig_asserted != 0 && i < meta->n_sfn; i++) {
+ sig = 1 << i;
+ if (sig_asserted & sig) {
+ /* The i bit signal asserted, index of SFN is i as well */
+ if (!p_sfn_table[i]) {
+ /* No corresponding SFN */
+ psa_panic();
+ }
+
+ psa_get(sig, &msg);
+ psa_reply(msg.handle, ((service_fn_t)p_sfn_table[i])(&msg));
+ sig_asserted &= ~sig;
+ }
+ }
+
+ if (sig_asserted != 0) {
+ /* Wrong signal asserted */
+ psa_panic();
+ }
+ }
+}
diff --git a/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.c b/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.c
new file mode 100644
index 0000000..8f1aaee
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+/*
+ * The address of Partition metadata, stored in TFM_SP_META_PTR region.
+ * All privilege RW. Gets updated by Scheduler when scheduling.
+ */
+__attribute__((section(".bss.SP_META_PTR_SPRTL_INST")))
+uintptr_t p_partition_metadata;
diff --git a/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.h b/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.h
new file mode 100644
index 0000000..b2ab390
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/sprt_partition_metadata_indicator.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SPRT_PARTITION_METADATA_INDICATOR_H__
+#define __SPRT_PARTITION_METADATA_INDICATOR_H__
+
+#include <stdint.h>
+
+extern uintptr_t p_partition_metadata;
+
+/* Partition Metadata pointer */
+#define PART_METADATA() ((struct runtime_metadata_t *)p_partition_metadata)
+
+#endif /* __SPRT_PARTITION_METADATA_INDICATOR_H__ */
diff --git a/secure_fw/partitions/lib/runtime/tfm_sp_log_raw.c b/secure_fw/partitions/lib/runtime/tfm_sp_log_raw.c
new file mode 100644
index 0000000..8a8d462
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/tfm_sp_log_raw.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "tfm_hal_defs.h"
+#include "tfm_hal_sp_logdev.h"
+
+#define PRINT_BUFF_SIZE 32
+#define NUM_BUFF_SIZE 12
+
+struct formatted_buffer_t {
+ size_t pos;
+ uint8_t buf[PRINT_BUFF_SIZE];
+};
+
+static const char hex_digits_lo[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+static const char hex_digits_up[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+static void _tfm_flush_formatted_buffer(struct formatted_buffer_t *pb,
+ uint8_t data)
+{
+ pb->buf[pb->pos++] = data;
+ if (pb->pos >= PRINT_BUFF_SIZE) {
+ pb->pos = 0;
+ /* uart flush and print here. */
+ tfm_hal_output_sp_log(pb->buf, PRINT_BUFF_SIZE);
+ }
+}
+
+static int _tfm_string_output(struct formatted_buffer_t *pb,
+ const char *str)
+{
+ int count = 0;
+
+ while (*str) {
+ _tfm_flush_formatted_buffer(pb, *str++);
+ count++;
+ }
+
+ return count;
+}
+
+static int _tfm_dec_num_output(struct formatted_buffer_t *pb,
+ int32_t num, uint8_t sign)
+{
+ int count = 0;
+ uint8_t num_buff[NUM_BUFF_SIZE] = {0};
+ uint32_t number = (uint32_t)num;
+ uint32_t k = 0;
+
+ if (sign == 'd' && num < 0) {
+ _tfm_flush_formatted_buffer(pb, '-');
+ count++;
+ number = -num;
+ }
+
+ do {
+ num_buff[k++] = '0' + number % 10;
+ number /= 10;
+ } while (number);
+
+ while (k) {
+ _tfm_flush_formatted_buffer(pb, num_buff[--k]);
+ count++;
+ }
+
+ return count;
+}
+
+static int _tfm_hex_num_output(struct formatted_buffer_t *pb, uint32_t num,
+ const char *hex_digits)
+{
+ int count = 0;
+ uint8_t num_buff[NUM_BUFF_SIZE] = {0};
+ uint32_t k = 0;
+
+ do {
+ num_buff[k++] = hex_digits[num & 0x0f];
+ num >>= 4;
+ } while (num);
+
+ while (k) {
+ _tfm_flush_formatted_buffer(pb, num_buff[--k]);
+ count++;
+ }
+
+ return count;
+}
+
+static int _tfm_sp_log_vprintf(const char *fmt, va_list ap)
+{
+ int count = 0;
+ struct formatted_buffer_t outputbuf;
+
+ outputbuf.pos = 0;
+
+ if (fmt == NULL) {
+ return TFM_HAL_ERROR_INVALID_INPUT;
+ }
+
+ while (*fmt) {
+ if (*fmt == '%') {
+ switch (*(++fmt)) {
+ case 'd':
+ case 'i':
+ count += _tfm_dec_num_output(&outputbuf,
+ va_arg(ap, int32_t), 'd');
+ break;
+ case 'u':
+ count += _tfm_dec_num_output(&outputbuf,
+ va_arg(ap, int32_t), 'u');
+ break;
+ case 'x':
+ count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
+ hex_digits_lo);
+ break;
+ case 'X':
+ count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
+ hex_digits_up);
+ break;
+ case 'p':
+ count += _tfm_string_output(&outputbuf, "0x");
+ count += _tfm_hex_num_output(&outputbuf, va_arg(ap, uint32_t),
+ hex_digits_lo);
+ break;
+ case 's':
+ count += _tfm_string_output(&outputbuf, va_arg(ap, char*));
+ break;
+ case 'c':
+ _tfm_flush_formatted_buffer(&outputbuf,
+ (uint8_t)va_arg(ap, int32_t));
+ count++;
+ break;
+ case '%':
+ _tfm_flush_formatted_buffer(&outputbuf, '%');
+ count++;
+ break;
+ default:
+ count += _tfm_string_output(&outputbuf, "[Unsupported Tag]");
+ continue;
+ }
+ fmt++;
+ } else {
+ _tfm_flush_formatted_buffer(&outputbuf, *fmt++);
+ count++;
+ }
+ }
+
+ /* End of printf, flush buf */
+ if (outputbuf.pos) {
+ count += tfm_hal_output_sp_log(outputbuf.buf, outputbuf.pos);
+ }
+
+ return count;
+}
+
+int tfm_sp_log_printf(const char *fmt, ...)
+{
+ int count = 0;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = _tfm_sp_log_vprintf(fmt, ap);
+ va_end(ap);
+
+ return count;
+}