SPRTL: Add log API for Secure Partitions
SPM and Secure Partitions(SP) will use different log implementations.
This patch adds the implementations for SP:
- SP log HAL API
- SP log interface
The log implementations re-use the currently shared log implementations.
Change-Id: I3e87e9424e6ea2a51e534bdab85406e4007c8261
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
Co-authored-by: Summer Qin <summer.qin@arm.com>
Co-authored-by: Shawn Shan <shawn.shan@arm.com>
diff --git a/platform/ext/common/tfm_hal_sp_logdev.h b/platform/ext/common/tfm_hal_sp_logdev.h
new file mode 100644
index 0000000..e31dbea
--- /dev/null
+++ b/platform/ext/common/tfm_hal_sp_logdev.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_HAL_SP_LOGDEV_H__
+#define __TFM_HAL_SP_LOGDEV_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+/**
+ * \brief HAL API for Secure Partition(SP) log system
+ *
+ * \param[in] str The string to output
+ * \param[in] len Length of the string in bytes
+ *
+ * \retval >= 0 Number of chars output.
+ * \retval < 0 TF-M HAL error code.
+ */
+int32_t tfm_hal_output_sp_log(const unsigned char *str, size_t len);
+
+#endif /* __TFM_HAL_SP_LOGDEV_H__ */
diff --git a/platform/ext/common/tfm_hal_sp_logdev_periph.c b/platform/ext/common/tfm_hal_sp_logdev_periph.c
new file mode 100644
index 0000000..9c9313b
--- /dev/null
+++ b/platform/ext/common/tfm_hal_sp_logdev_periph.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_hal_sp_logdev.h"
+#include "uart_stdout.h"
+
+int32_t tfm_hal_output_sp_log(const unsigned char *str, size_t len)
+{
+ /* Peripheral based log function call the stdio_output_string directly */
+ return stdio_output_string(str, len);
+}
diff --git a/secure_fw/partitions/crypto/CMakeLists.txt b/secure_fw/partitions/crypto/CMakeLists.txt
index 9a0e654..80ed6d5 100644
--- a/secure_fw/partitions/crypto/CMakeLists.txt
+++ b/secure_fw/partitions/crypto/CMakeLists.txt
@@ -47,6 +47,7 @@
platform_s
crypto_service_mbedcrypto
psa_interface
+ tfm_sprt
)
target_compile_definitions(tfm_partition_crypto
PUBLIC
diff --git a/secure_fw/partitions/crypto/crypto_init.c b/secure_fw/partitions/crypto/crypto_init.c
index 648b76a..9b93ea8 100644
--- a/secure_fw/partitions/crypto/crypto_init.c
+++ b/secure_fw/partitions/crypto/crypto_init.c
@@ -9,7 +9,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
-#include "log/tfm_log.h"
+#include "tfm_sp_log.h"
/*
* \brief This Mbed TLS include is needed to initialise the memory allocator
@@ -278,7 +278,7 @@
{
/* Log unsafe entropy source */
#if defined (MBEDTLS_TEST_NULL_ENTROPY)
- LOG_MSG("\033[1;34m[Crypto] MBEDTLS_TEST_NULL_ENTROPY is not suitable for production!\033[0m\r\n");
+ LOG_INFFMT("\033[1;34m[Crypto] MBEDTLS_TEST_NULL_ENTROPY is not suitable for production!\033[0m\r\n");
#endif
/* Initialise the Mbed Crypto memory allocator to use static
diff --git a/secure_fw/partitions/lib/sprt/CMakeLists.txt b/secure_fw/partitions/lib/sprt/CMakeLists.txt
index 66a92f2..2e78e6a 100644
--- a/secure_fw/partitions/lib/sprt/CMakeLists.txt
+++ b/secure_fw/partitions/lib/sprt/CMakeLists.txt
@@ -21,6 +21,8 @@
./crt_memmove.c
./crt_memset.c
./service_api.c
+ ./tfm_sp_log_raw.c
+ ${CMAKE_SOURCE_DIR}/platform/ext/common/tfm_hal_sp_logdev_periph.c
)
target_link_libraries(tfm_sprt
diff --git a/secure_fw/partitions/lib/sprt/include/tfm_sp_log.h b/secure_fw/partitions/lib/sprt/include/tfm_sp_log.h
new file mode 100644
index 0000000..dfdd981
--- /dev/null
+++ b/secure_fw/partitions/lib/sprt/include/tfm_sp_log.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, 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
+
+#define LOG_INFFMT(...) tfm_sp_log_printf(__VA_ARGS__)
+
+/**
+ * \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/sprt/tfm_sp_log_raw.c b/secure_fw/partitions/lib/sprt/tfm_sp_log_raw.c
new file mode 100644
index 0000000..bf39b3d
--- /dev/null
+++ b/secure_fw/partitions/lib/sprt/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;
+}