Browse Source

Merge branch '2021-03-12-assorted-improvements' into next

- More log enhancements
- A few warning fixes in some cases
- Secure Channel Protocol 03 (SCP03) support for TEEs
Tom Rini 3 years ago
parent
commit
1876b390f3

+ 2 - 0
arch/Kconfig

@@ -142,6 +142,8 @@ config SANDBOX
 	imply AVB_VERIFY
 	imply AVB_VERIFY
 	imply LIBAVB
 	imply LIBAVB
 	imply CMD_AVB
 	imply CMD_AVB
+	imply SCP03
+	imply CMD_SCP03
 	imply UDP_FUNCTION_FASTBOOT
 	imply UDP_FUNCTION_FASTBOOT
 	imply VIRTIO_MMIO
 	imply VIRTIO_MMIO
 	imply VIRTIO_PCI
 	imply VIRTIO_PCI

+ 8 - 1
cmd/Kconfig

@@ -2022,12 +2022,19 @@ config HASH_VERIFY
 	help
 	help
 	  Add -v option to verify data against a hash.
 	  Add -v option to verify data against a hash.
 
 
+config CMD_SCP03
+	bool "scp03 - SCP03 enable and rotate/provision operations"
+	depends on SCP03
+	help
+	  This command provides access to a Trusted Application
+	  running in a TEE to request Secure Channel Protocol 03
+	  (SCP03) enablement and/or rotation of its SCP03 keys.
+
 config CMD_TPM_V1
 config CMD_TPM_V1
 	bool
 	bool
 
 
 config CMD_TPM_V2
 config CMD_TPM_V2
 	bool
 	bool
-	select CMD_LOG
 
 
 config CMD_TPM
 config CMD_TPM
 	bool "Enable the 'tpm' command"
 	bool "Enable the 'tpm' command"

+ 3 - 0
cmd/Makefile

@@ -193,6 +193,9 @@ obj-$(CONFIG_CMD_BLOB) += blob.o
 # Android Verified Boot 2.0
 # Android Verified Boot 2.0
 obj-$(CONFIG_CMD_AVB) += avb.o
 obj-$(CONFIG_CMD_AVB) += avb.o
 
 
+# Foundries.IO SCP03
+obj-$(CONFIG_CMD_SCP03) += scp03.o
+
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_RISCV) += riscv/
 obj-$(CONFIG_RISCV) += riscv/
 obj-$(CONFIG_SANDBOX) += sandbox/
 obj-$(CONFIG_SANDBOX) += sandbox/

+ 52 - 0
cmd/scp03.c

@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <scp03.h>
+
+int do_scp03_enable(struct cmd_tbl *cmdtp, int flag, int argc,
+		    char *const argv[])
+{
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	if (tee_enable_scp03()) {
+		printf("TEE failed to enable SCP03\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("SCP03 is enabled\n");
+
+	return CMD_RET_SUCCESS;
+}
+
+int do_scp03_provision(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	if (tee_provision_scp03()) {
+		printf("TEE failed to provision SCP03 keys\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("SCP03 is provisioned\n");
+
+	return CMD_RET_SUCCESS;
+}
+
+static char text[] =
+	"provides a command to enable SCP03 and provision the SCP03 keys\n"
+	" enable    - enable SCP03 on the TEE\n"
+	" provision - provision SCP03 on the TEE\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text,
+	U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable),
+	U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision));
+

+ 8 - 0
common/Kconfig

@@ -588,6 +588,14 @@ config AVB_BUF_SIZE
 
 
 endif # AVB_VERIFY
 endif # AVB_VERIFY
 
 
+config SCP03
+	bool "Build SCP03 - Secure Channel Protocol O3 - controls"
+	depends on OPTEE || SANDBOX
+	depends on TEE
+	help
+	  This option allows U-Boot to enable and or provision SCP03 on an OPTEE
+	  controlled Secured Element.
+
 config SPL_HASH
 config SPL_HASH
 	bool # "Support hashing API (SHA1, SHA256, etc.)"
 	bool # "Support hashing API (SHA1, SHA256, etc.)"
 	help
 	help

+ 1 - 0
common/Makefile

@@ -137,3 +137,4 @@ obj-$(CONFIG_CMD_LOADB) += xyzModem.o
 obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
 obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
 
 
 obj-$(CONFIG_AVB_VERIFY) += avb_verify.o
 obj-$(CONFIG_AVB_VERIFY) += avb_verify.o
+obj-$(CONFIG_SCP03) += scp03.o

+ 12 - 4
common/log.c

@@ -153,7 +153,7 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
 {
 {
 	struct log_filter *filt;
 	struct log_filter *filt;
 
 
-	if (rec->force_debug)
+	if (rec->flags & LOGRECF_FORCE_DEBUG)
 		return true;
 		return true;
 
 
 	/* If there are no filters, filter on the default log level */
 	/* If there are no filters, filter on the default log level */
@@ -218,8 +218,11 @@ static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args)
 		if ((ldev->flags & LOGDF_ENABLE) &&
 		if ((ldev->flags & LOGDF_ENABLE) &&
 		    log_passes_filters(ldev, rec)) {
 		    log_passes_filters(ldev, rec)) {
 			if (!rec->msg) {
 			if (!rec->msg) {
-				vsnprintf(buf, sizeof(buf), fmt, args);
+				int len;
+
+				len = vsnprintf(buf, sizeof(buf), fmt, args);
 				rec->msg = buf;
 				rec->msg = buf;
+				gd->log_cont = len && buf[len - 1] != '\n';
 			}
 			}
 			ldev->drv->emit(ldev, rec);
 			ldev->drv->emit(ldev, rec);
 		}
 		}
@@ -245,7 +248,11 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 
 
 	rec.cat = cat;
 	rec.cat = cat;
 	rec.level = level & LOGL_LEVEL_MASK;
 	rec.level = level & LOGL_LEVEL_MASK;
-	rec.force_debug = level & LOGL_FORCE_DEBUG;
+	rec.flags = 0;
+	if (level & LOGL_FORCE_DEBUG)
+		rec.flags |= LOGRECF_FORCE_DEBUG;
+	if (gd->log_cont)
+		rec.flags |= LOGRECF_CONT;
 	rec.file = file;
 	rec.file = file;
 	rec.line = line;
 	rec.line = line;
 	rec.func = func;
 	rec.func = func;
@@ -255,7 +262,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 		gd->log_drop_count++;
 		gd->log_drop_count++;
 
 
 		/* display dropped traces with console puts and DEBUG_UART */
 		/* display dropped traces with console puts and DEBUG_UART */
-		if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) {
+		if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL ||
+		    rec.flags & LOGRECF_FORCE_DEBUG) {
 			char buf[CONFIG_SYS_CBSIZE];
 			char buf[CONFIG_SYS_CBSIZE];
 
 
 			va_start(args, fmt);
 			va_start(args, fmt);

+ 15 - 11
common/log_console.c

@@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
 static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
 static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
 {
 {
 	int fmt = gd->log_fmt;
 	int fmt = gd->log_fmt;
+	bool add_space = false;
 
 
 	/*
 	/*
 	 * The output format is designed to give someone a fighting chance of
 	 * The output format is designed to give someone a fighting chance of
@@ -26,18 +27,21 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
 	 *    - function is an identifier and ends with ()
 	 *    - function is an identifier and ends with ()
 	 *    - message has a space before it unless it is on its own
 	 *    - message has a space before it unless it is on its own
 	 */
 	 */
-	if (fmt & BIT(LOGF_LEVEL))
-		printf("%s.", log_get_level_name(rec->level));
-	if (fmt & BIT(LOGF_CAT))
-		printf("%s,", log_get_cat_name(rec->cat));
-	if (fmt & BIT(LOGF_FILE))
-		printf("%s:", rec->file);
-	if (fmt & BIT(LOGF_LINE))
-		printf("%d-", rec->line);
-	if (fmt & BIT(LOGF_FUNC))
-		printf("%s()", rec->func);
+	if (!(rec->flags & LOGRECF_CONT) && fmt != BIT(LOGF_MSG)) {
+		add_space = true;
+		if (fmt & BIT(LOGF_LEVEL))
+			printf("%s.", log_get_level_name(rec->level));
+		if (fmt & BIT(LOGF_CAT))
+			printf("%s,", log_get_cat_name(rec->cat));
+		if (fmt & BIT(LOGF_FILE))
+			printf("%s:", rec->file);
+		if (fmt & BIT(LOGF_LINE))
+			printf("%d-", rec->line);
+		if (fmt & BIT(LOGF_FUNC))
+			printf("%s()", rec->func);
+	}
 	if (fmt & BIT(LOGF_MSG))
 	if (fmt & BIT(LOGF_MSG))
-		printf("%s%s", fmt != BIT(LOGF_MSG) ? " " : "", rec->msg);
+		printf("%s%s", add_space ? " " : "", rec->msg);
 
 
 	return 0;
 	return 0;
 }
 }

+ 53 - 0
common/scp03.c

@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <scp03.h>
+#include <tee.h>
+#include <tee/optee_ta_scp03.h>
+
+static int scp03_enable(bool provision)
+{
+	const struct tee_optee_ta_uuid uuid = PTA_SCP03_UUID;
+	struct tee_open_session_arg session;
+	struct tee_invoke_arg invoke;
+	struct tee_param param;
+	struct udevice *tee = NULL;
+
+	tee = tee_find_device(tee, NULL, NULL, NULL);
+	if (!tee)
+		return -ENODEV;
+
+	memset(&session, 0, sizeof(session));
+	tee_optee_ta_uuid_to_octets(session.uuid, &uuid);
+	if (tee_open_session(tee, &session, 0, NULL))
+		return -ENXIO;
+
+	memset(&param, 0, sizeof(param));
+	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param.u.value.a = provision;
+
+	memset(&invoke, 0, sizeof(invoke));
+	invoke.func = PTA_CMD_ENABLE_SCP03;
+	invoke.session = session.session;
+
+	if (tee_invoke_func(tee, &invoke, 1, &param))
+		return -EIO;
+
+	tee_close_session(tee, session.session);
+
+	return 0;
+}
+
+int tee_enable_scp03(void)
+{
+	return scp03_enable(false);
+}
+
+int tee_provision_scp03(void)
+{
+	return scp03_enable(true);
+}

+ 1 - 1
doc/arch/sandbox.rst

@@ -82,7 +82,7 @@ console::
 You can issue commands as your would normally. If the command you want is
 You can issue commands as your would normally. If the command you want is
 not supported you can add it to include/configs/sandbox.h.
 not supported you can add it to include/configs/sandbox.h.
 
 
-To exit, type 'reset' or press Ctrl-C.
+To exit, type 'poweroff' or press Ctrl-C.
 
 
 
 
 Console / LCD support
 Console / LCD support

+ 30 - 1
doc/develop/logging.rst

@@ -96,16 +96,45 @@ Also debug() and error() will generate log records  - these use LOG_CATEGORY
 as the category, so you should #define this right at the top of the source
 as the category, so you should #define this right at the top of the source
 file to ensure the category is correct.
 file to ensure the category is correct.
 
 
+Generally each log format_string ends with a newline. If it does not, then the
+next log statement will have the LOGRECF_CONT flag set. This can be used to
+continue the statement on the same line as the previous one without emitting
+new header information (such as category/level). This behaviour is implemented
+with log_console. Here is an example that prints a list all on one line with
+the tags at the start:
+
+.. code-block:: c
+
+   log_debug("Here is a list:");
+   for (i = 0; i < count; i++)
+      log_debug(" item %d", i);
+   log_debug("\n");
+
+Also see the special category LOGL_CONT and level LOGC_CONT.
+
 You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
 You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
 can be used whenever your function returns an error value:
 can be used whenever your function returns an error value:
 
 
 .. code-block:: c
 .. code-block:: c
 
 
-   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+   return log_ret(uclass_first_device_err(UCLASS_MMC, &dev));
 
 
 This will write a log record when an error code is detected (a value < 0). This
 This will write a log record when an error code is detected (a value < 0). This
 can make it easier to trace errors that are generated deep in the call stack.
 can make it easier to trace errors that are generated deep in the call stack.
 
 
+The log_msg_ret() variant will print a short string if CONFIG_LOG_ERROR_RETURN
+is enabled. So long as the string is unique within the function you can normally
+determine exactly which call failed:
+
+.. code-block:: c
+
+   ret = gpio_request_by_name(dev, "cd-gpios", 0, &desc, GPIOD_IS_IN);
+   if (ret)
+      return log_msg_ret("gpio", ret);
+
+Some functions return 0 for success and any other value is an error. For these,
+log_retz() and log_msg_retz() are available.
+
 Convenience functions
 Convenience functions
 ~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~
 
 

+ 1 - 0
doc/usage/index.rst

@@ -33,3 +33,4 @@ Shell commands
    qfw
    qfw
    sbi
    sbi
    true
    true
+   scp03

+ 33 - 0
doc/usage/scp03.rst

@@ -0,0 +1,33 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+scp03 command
+=============
+
+Synopsis
+--------
+
+::
+
+    scp03 enable
+    scp03 provision
+
+Description
+-----------
+
+The *scp03* command calls into a Trusted Application executing in a
+Trusted Execution Environment to enable (if present) the Secure
+Channel Protocol 03 stablished between the processor and the secure
+element.
+
+This protocol encrypts all the communication between the processor and
+the secure element using a set of pre-defined keys. These keys can be
+rotated (provisioned) using the *provision* request.
+
+See also
+--------
+
+For some information on the internals implemented in the TEE, please
+check the GlobalPlatform documentation on `Secure Channel Protocol '03'`_
+
+.. _Secure Channel Protocol '03':
+   https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf

+ 6 - 0
drivers/tee/optee/Kconfig

@@ -31,6 +31,12 @@ config OPTEE_TA_RPC_TEST
 	  permits to test reverse RPC calls to TEE supplicant. Should
 	  permits to test reverse RPC calls to TEE supplicant. Should
 	  be used only in sandbox env.
 	  be used only in sandbox env.
 
 
+config OPTEE_TA_SCP03
+	bool "Support SCP03 TA"
+	default y
+	help
+	  Enables support for controlling (enabling, provisioning) the
+	  Secure Channel Protocol 03 operation in the OP-TEE SCP03 TA.
 endmenu
 endmenu
 
 
 endif
 endif

+ 53 - 1
drivers/tee/sandbox.c

@@ -8,6 +8,7 @@
 #include <tee.h>
 #include <tee.h>
 #include <tee/optee_ta_avb.h>
 #include <tee/optee_ta_avb.h>
 #include <tee/optee_ta_rpc_test.h>
 #include <tee/optee_ta_rpc_test.h>
+#include <tee/optee_ta_scp03.h>
 
 
 #include "optee/optee_msg.h"
 #include "optee/optee_msg.h"
 #include "optee/optee_private.h"
 #include "optee/optee_private.h"
@@ -68,6 +69,7 @@ void *optee_alloc_and_init_page_list(void *buf, ulong len,
 	return NULL;
 	return NULL;
 }
 }
 
 
+#if defined(CONFIG_OPTEE_TA_SCP03) || defined(CONFIG_OPTEE_TA_AVB)
 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 {
 {
 	if (n >= num_params)
 	if (n >= num_params)
@@ -79,7 +81,7 @@ static u32 get_attr(uint n, uint num_params, struct tee_param *params)
 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
 static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
 			struct tee_param *params)
 			struct tee_param *params)
 {
 {
-	u8 p[] = { p0, p1, p2, p3};
+	u8 p[] = { p0, p1, p2, p3 };
 	uint n;
 	uint n;
 
 
 	for (n = 0; n < ARRAY_SIZE(p); n++)
 	for (n = 0; n < ARRAY_SIZE(p); n++)
@@ -97,6 +99,50 @@ bad_params:
 
 
 	return TEE_ERROR_BAD_PARAMETERS;
 	return TEE_ERROR_BAD_PARAMETERS;
 }
 }
+#endif
+
+#ifdef CONFIG_OPTEE_TA_SCP03
+static u32 pta_scp03_open_session(struct udevice *dev, uint num_params,
+				  struct tee_param *params)
+{
+	/*
+	 * We don't expect additional parameters when opening a session to
+	 * this TA.
+	 */
+	return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    num_params, params);
+}
+
+static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
+				 struct tee_param *params)
+{
+	u32 res;
+	static bool enabled;
+
+	switch (func) {
+	case PTA_CMD_ENABLE_SCP03:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		if (!enabled) {
+			enabled = true;
+		} else {
+		}
+
+		if (params[0].u.value.a)
+
+		return TEE_SUCCESS;
+	default:
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+}
+#endif
 
 
 #ifdef CONFIG_OPTEE_TA_AVB
 #ifdef CONFIG_OPTEE_TA_AVB
 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
 static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
@@ -357,6 +403,12 @@ static const struct ta_entry ta_entries[] = {
 	  .invoke_func = ta_rpc_test_invoke_func,
 	  .invoke_func = ta_rpc_test_invoke_func,
 	},
 	},
 #endif
 #endif
+#ifdef CONFIG_OPTEE_TA_SCP03
+	{ .uuid = PTA_SCP03_UUID,
+	  .open_session = pta_scp03_open_session,
+	  .invoke_func = pta_scp03_invoke_func,
+	},
+#endif
 };
 };
 
 
 static void sandbox_tee_get_version(struct udevice *dev,
 static void sandbox_tee_get_version(struct udevice *dev,

+ 1 - 1
drivers/tpm/tpm2_tis_sandbox.c

@@ -285,7 +285,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
 	length = get_unaligned_be32(sent);
 	length = get_unaligned_be32(sent);
 	sent += sizeof(length);
 	sent += sizeof(length);
 	if (length != send_size) {
 	if (length != send_size) {
-		printf("TPM2: Unmatching length, received: %ld, expected: %d\n",
+		printf("TPM2: Unmatching length, received: %zd, expected: %d\n",
 		       send_size, length);
 		       send_size, length);
 		rc = TPM2_RC_SIZE;
 		rc = TPM2_RC_SIZE;
 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);

+ 6 - 0
include/asm-generic/global_data.h

@@ -410,6 +410,12 @@ struct global_data {
 	 * This value is used as logging level for continuation messages.
 	 * This value is used as logging level for continuation messages.
 	 */
 	 */
 	int logl_prev;
 	int logl_prev;
+	/**
+	 * @log_cont: Previous log line did not finished wtih \n
+	 *
+	 * This allows for chained log messages on the same line
+	 */
+	bool log_cont;
 #endif
 #endif
 #if CONFIG_IS_ENABLED(BLOBLIST)
 #if CONFIG_IS_ENABLED(BLOBLIST)
 	/**
 	/**

+ 32 - 4
include/log.h

@@ -316,12 +316,40 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
 		    __ret); \
 		    __ret); \
 	__ret; \
 	__ret; \
 	})
 	})
+
+/*
+ * Similar to the above, but any non-zero value is consider an error, not just
+ * values less than 0.
+ */
+#define log_retz(_ret) ({ \
+	int __ret = (_ret); \
+	if (__ret) \
+		log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \
+	__ret; \
+	})
+#define log_msg_retz(_msg, _ret) ({ \
+	int __ret = (_ret); \
+	if (__ret) \
+		log(LOG_CATEGORY, LOGL_ERR, "%s: returning err=%d\n", _msg, \
+		    __ret); \
+	__ret; \
+	})
 #else
 #else
 /* Non-logging versions of the above which just return the error code */
 /* Non-logging versions of the above which just return the error code */
 #define log_ret(_ret) (_ret)
 #define log_ret(_ret) (_ret)
 #define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
 #define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
+#define log_retz(_ret) (_ret)
+#define log_msg_retz(_msg, _ret) ((void)(_msg), _ret)
 #endif
 #endif
 
 
+/** * enum log_rec_flags - Flags for a log record */
+enum log_rec_flags {
+	/** @LOGRECF_FORCE_DEBUG: Force output of debug record */
+	LOGRECF_FORCE_DEBUG	= BIT(0),
+	/** @LOGRECF_CONT: Continuation of previous log record */
+	LOGRECF_CONT		= BIT(1),
+};
+
 /**
 /**
  * struct log_rec - a single log record
  * struct log_rec - a single log record
  *
  *
@@ -337,18 +365,18 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
  *
  *
  * @cat: Category, representing a uclass or part of U-Boot
  * @cat: Category, representing a uclass or part of U-Boot
  * @level: Severity level, less severe is higher
  * @level: Severity level, less severe is higher
- * @force_debug: Force output of debug
- * @file: Name of file where the log record was generated (not allocated)
  * @line: Line number where the log record was generated
  * @line: Line number where the log record was generated
+ * @flags: Flags for log record (enum log_rec_flags)
+ * @file: Name of file where the log record was generated (not allocated)
  * @func: Function where the log record was generated (not allocated)
  * @func: Function where the log record was generated (not allocated)
  * @msg: Log message (allocated)
  * @msg: Log message (allocated)
  */
  */
 struct log_rec {
 struct log_rec {
 	enum log_category_t cat;
 	enum log_category_t cat;
 	enum log_level_t level;
 	enum log_level_t level;
-	bool force_debug;
+	u16 line;
+	u8 flags;
 	const char *file;
 	const char *file;
-	int line;
 	const char *func;
 	const char *func;
 	const char *msg;
 	const char *msg;
 };
 };

+ 21 - 0
include/scp03.h

@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#ifndef _SCP03_H
+#define _SCP03_H
+
+/*
+ * Requests to OPTEE to enable or provision the Secure Channel Protocol on its
+ * Secure Element
+ *
+ *  If key provisioning is requested, OPTEE shall generate new SCP03 keys and
+ *  write them to the Secure Element.
+ *
+ *  Both functions return < 0 on error else 0.
+ */
+int tee_enable_scp03(void);
+int tee_provision_scp03(void);
+#endif /* _SCP03_H */

+ 21 - 0
include/tee/optee_ta_scp03.h

@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+#ifndef __TA_SCP03_H
+#define __TA_SCP03_H
+
+#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \
+			{ 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } }
+
+/*
+ * Enable Secure Channel Protocol functionality (SCP03) on the Secure Element.
+ *   Setting the operation value to something different than NULL will trigger
+ *   the SCP03 provisioning request.
+ *
+ *   in	params[0].a = operation
+ */
+#define PTA_CMD_ENABLE_SCP03	0
+
+#endif /*__TA_SCP03_H*/

+ 6 - 6
test/dm/acpi.c

@@ -360,24 +360,24 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
 	run_command("acpi list", 0);
 	run_command("acpi list", 0);
 	addr = (ulong)map_to_sysmem(buf);
 	addr = (ulong)map_to_sysmem(buf);
 	ut_assert_nextline("ACPI tables start at %lx", addr);
 	ut_assert_nextline("ACPI tables start at %lx", addr);
-	ut_assert_nextline("RSDP %08lx %06lx (v02 U-BOOT)", addr,
+	ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr,
 			   sizeof(struct acpi_rsdp));
 			   sizeof(struct acpi_rsdp));
 	addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
 	addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
-	ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("RSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
 			   addr, sizeof(struct acpi_table_header) +
 			   3 * sizeof(u32), U_BOOT_BUILD_DATE);
 			   3 * sizeof(u32), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
 	addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
-	ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("XSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_table_header) +
 			   addr, sizeof(struct acpi_table_header) +
 			   3 * sizeof(u64), U_BOOT_BUILD_DATE);
 			   3 * sizeof(u64), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
 	addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
 	addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
-	ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)",
+	ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)",
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 			   addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
 	ut_assert_console_end();
 	ut_assert_console_end();
 
 

+ 15 - 4
test/log/cont_test.c

@@ -15,8 +15,6 @@
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
-#define BUFFSIZE 64
-
 static int log_test_cont(struct unit_test_state *uts)
 static int log_test_cont(struct unit_test_state *uts)
 {
 {
 	int log_fmt;
 	int log_fmt;
@@ -29,12 +27,13 @@ static int log_test_cont(struct unit_test_state *uts)
 	gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
 	gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
 	gd->default_log_level = LOGL_INFO;
 	gd->default_log_level = LOGL_INFO;
 	console_record_reset_enable();
 	console_record_reset_enable();
-	log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+	log(LOGC_ARCH, LOGL_ERR, "ea%d\n", 1);
 	log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
 	log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
 	gd->default_log_level = log_level;
 	gd->default_log_level = log_level;
 	gd->log_fmt = log_fmt;
 	gd->log_fmt = log_fmt;
 	gd->flags &= ~GD_FLG_RECORD;
 	gd->flags &= ~GD_FLG_RECORD;
-	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 ERR.arch, cc2"));
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1"));
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, cc2"));
 	ut_assertok(ut_check_console_end(uts));
 	ut_assertok(ut_check_console_end(uts));
 
 
 	/* Write a third message which is not a continuation */
 	/* Write a third message which is not a continuation */
@@ -48,6 +47,18 @@ static int log_test_cont(struct unit_test_state *uts)
 	ut_assertok(ut_check_console_line(uts, "INFO.efi, ie3"));
 	ut_assertok(ut_check_console_line(uts, "INFO.efi, ie3"));
 	ut_assertok(ut_check_console_end(uts));
 	ut_assertok(ut_check_console_end(uts));
 
 
+	/* Write two messages without a newline between them */
+	gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG);
+	gd->default_log_level = LOGL_INFO;
+	console_record_reset_enable();
+	log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1);
+	log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2);
+	gd->default_log_level = log_level;
+	gd->log_fmt = log_fmt;
+	gd->flags &= ~GD_FLG_RECORD;
+	ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 cc2"));
+	ut_assertok(ut_check_console_end(uts));
+
 	return 0;
 	return 0;
 }
 }
 LOG_TEST(log_test_cont);
 LOG_TEST(log_test_cont);

+ 27 - 0
test/py/tests/test_scp03.py

@@ -0,0 +1,27 @@
+# Copyright (c) 2021 Foundries.io Ltd
+#
+# SPDX-License-Identifier:  GPL-2.0+
+#
+# SCP03 command test
+
+"""
+This tests SCP03 command in U-boot.
+
+For additional details check doc/usage/scp03.rst
+"""
+
+import pytest
+import u_boot_utils as util
+
+@pytest.mark.buildconfigspec('cmd_scp03')
+def test_scp03(u_boot_console):
+    """Enable and provision keys with SCP03
+    """
+
+    success_str1 = "SCP03 is enabled"
+    success_str2 = "SCP03 is provisioned"
+
+    response = u_boot_console.run_command('scp03 enable')
+    assert success_str1 in response
+    response = u_boot_console.run_command('scp03 provision')
+    assert success_str2 in response