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 LIBAVB
 	imply CMD_AVB
+	imply SCP03
+	imply CMD_SCP03
 	imply UDP_FUNCTION_FASTBOOT
 	imply VIRTIO_MMIO
 	imply VIRTIO_PCI

+ 8 - 1
cmd/Kconfig

@@ -2022,12 +2022,19 @@ config HASH_VERIFY
 	help
 	  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
 	bool
 
 config CMD_TPM_V2
 	bool
-	select CMD_LOG
 
 config CMD_TPM
 	bool "Enable the 'tpm' command"

+ 3 - 0
cmd/Makefile

@@ -193,6 +193,9 @@ obj-$(CONFIG_CMD_BLOB) += blob.o
 # Android Verified Boot 2.0
 obj-$(CONFIG_CMD_AVB) += avb.o
 
+# Foundries.IO SCP03
+obj-$(CONFIG_CMD_SCP03) += scp03.o
+
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_RISCV) += riscv/
 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
 
+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
 	bool # "Support hashing API (SHA1, SHA256, etc.)"
 	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_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;
 
-	if (rec->force_debug)
+	if (rec->flags & LOGRECF_FORCE_DEBUG)
 		return true;
 
 	/* 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) &&
 		    log_passes_filters(ldev, rec)) {
 			if (!rec->msg) {
-				vsnprintf(buf, sizeof(buf), fmt, args);
+				int len;
+
+				len = vsnprintf(buf, sizeof(buf), fmt, args);
 				rec->msg = buf;
+				gd->log_cont = len && buf[len - 1] != '\n';
 			}
 			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.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.line = line;
 	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++;
 
 		/* 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];
 
 			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)
 {
 	int fmt = gd->log_fmt;
+	bool add_space = false;
 
 	/*
 	 * 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 ()
 	 *    - 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))
-		printf("%s%s", fmt != BIT(LOGF_MSG) ? " " : "", rec->msg);
+		printf("%s%s", add_space ? " " : "", rec->msg);
 
 	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
 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

+ 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
 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
 can be used whenever your function returns an error value:
 
 .. 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
 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
 ~~~~~~~~~~~~~~~~~~~~~
 

+ 1 - 0
doc/usage/index.rst

@@ -33,3 +33,4 @@ Shell commands
    qfw
    sbi
    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
 	  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
 
 endif

+ 53 - 1
drivers/tee/sandbox.c

@@ -8,6 +8,7 @@
 #include <tee.h>
 #include <tee/optee_ta_avb.h>
 #include <tee/optee_ta_rpc_test.h>
+#include <tee/optee_ta_scp03.h>
 
 #include "optee/optee_msg.h"
 #include "optee/optee_private.h"
@@ -68,6 +69,7 @@ void *optee_alloc_and_init_page_list(void *buf, ulong len,
 	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)
 {
 	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,
 			struct tee_param *params)
 {
-	u8 p[] = { p0, p1, p2, p3};
+	u8 p[] = { p0, p1, p2, p3 };
 	uint n;
 
 	for (n = 0; n < ARRAY_SIZE(p); n++)
@@ -97,6 +99,50 @@ bad_params:
 
 	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
 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,
 	},
 #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,

+ 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);
 	sent += sizeof(length);
 	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);
 		rc = TPM2_RC_SIZE;
 		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.
 	 */
 	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
 #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; \
 	})
+
+/*
+ * 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
 /* Non-logging versions of the above which just return the error code */
 #define log_ret(_ret) (_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
 
+/** * 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
  *
@@ -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
  * @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
+ * @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)
  * @msg: Log message (allocated)
  */
 struct log_rec {
 	enum log_category_t cat;
 	enum log_level_t level;
-	bool force_debug;
+	u16 line;
+	u8 flags;
 	const char *file;
-	int line;
 	const char *func;
 	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);
 	addr = (ulong)map_to_sysmem(buf);
 	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));
 	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) +
 			   3 * sizeof(u32), U_BOOT_BUILD_DATE);
 	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) +
 			   3 * sizeof(u64), U_BOOT_BUILD_DATE);
 	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 = 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 = 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);
 	ut_assert_console_end();
 

+ 15 - 4
test/log/cont_test.c

@@ -15,8 +15,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define BUFFSIZE 64
-
 static int log_test_cont(struct unit_test_state *uts)
 {
 	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->default_log_level = LOGL_INFO;
 	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);
 	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 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));
 
 	/* 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_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;
 }
 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