Merge tag 'doc-2021-04-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for documentation tag doc-2021-04-rc1

* document man-page base command
* move README.fdt-overlays to HTML documentation
* add synopsis for pstore command
diff --git a/api/api.c b/api/api.c
index 493b77f..89003c1 100644
--- a/api/api.c
+++ b/api/api.c
@@ -642,7 +642,7 @@
 	return 1;
 }
 
-void api_init(void)
+int api_init(void)
 {
 	struct api_signature *sig;
 
@@ -679,7 +679,7 @@
 	sig = malloc(sizeof(struct api_signature));
 	if (sig == NULL) {
 		printf("API: could not allocate memory for the signature!\n");
-		return;
+		return -ENOMEM;
 	}
 
 	env_set_hex("api_address", (unsigned long)sig);
@@ -691,6 +691,8 @@
 	sig->checksum = crc32(0, (unsigned char *)sig,
 			      sizeof(struct api_signature));
 	debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
+
+	return 0;
 }
 
 void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
diff --git a/api/api_private.h b/api/api_private.h
index 07fd50a..bb23821 100644
--- a/api/api_private.h
+++ b/api/api_private.h
@@ -8,7 +8,7 @@
 #ifndef _API_PRIVATE_H_
 #define _API_PRIVATE_H_
 
-void	api_init(void);
+int	api_init(void);
 void	platform_set_mr(struct sys_info *, unsigned long, unsigned long, int);
 int	platform_sys_info(struct sys_info *);
 
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index f7b4a5e..d85ddde 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -9,14 +9,16 @@
 ifndef CONFIG_$(SPL_TPL_)TIMER
 obj-$(CONFIG_SYS_ARCH_TIMER) += generic_timer.o
 endif
+ifndef CONFIG_$(SPL_)SYS_DCACHE_OFF
 obj-y	+= cache_v8.o
+obj-y	+= cache.o
+endif
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o
 else
 obj-y	+= exceptions.o
 obj-y	+= exception_level.o
 endif
-obj-y	+= cache.o
 obj-y	+= tlb.o
 obj-y	+= transition.o
 ifndef CONFIG_ARMV8_PSCI
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index ce55294..5fe8369 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -628,7 +628,18 @@
 				     enum dcache_option option);
 
 #ifdef CONFIG_SYS_NONCACHED_MEMORY
-void noncached_init(void);
+/**
+ * noncached_init() - Initialize non-cached memory region
+ *
+ * Initialize non-cached memory area. This memory region will be typically
+ * located right below the malloc() area and mapped uncached in the MMU.
+ *
+ * It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int noncached_init(void);
+
 phys_addr_t noncached_alloc(size_t size, size_t align);
 #endif /* CONFIG_SYS_NONCACHED_MEMORY */
 
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
index ee7d14b..bdde9cd 100644
--- a/arch/arm/lib/cache.c
+++ b/arch/arm/lib/cache.c
@@ -86,7 +86,7 @@
 #endif
 }
 
-void noncached_init(void)
+int noncached_init(void)
 {
 	phys_addr_t start, end;
 	size_t size;
@@ -103,6 +103,8 @@
 	noncached_next = start;
 
 	noncached_set_region();
+
+	return 0;
 }
 
 phys_addr_t noncached_alloc(size_t size, size_t align)
diff --git a/arch/m68k/lib/traps.c b/arch/m68k/lib/traps.c
index c49141f..0c2c1a9 100644
--- a/arch/m68k/lib/traps.c
+++ b/arch/m68k/lib/traps.c
@@ -40,7 +40,7 @@
 	for(;;);
 }
 
-void trap_init(ulong value) {
+static void trap_init(ulong value) {
 	unsigned long *vec = (ulong *)value;
 	int i;
 
@@ -59,3 +59,10 @@
 
 	setvbr(value);		/* set vector base register to new table */
 }
+
+int arch_initr_trap(void)
+{
+	trap_init(CONFIG_SYS_SDRAM_BASE);
+
+	return 0;
+}
diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
index df8b63f..540ea48 100644
--- a/arch/mips/lib/traps.c
+++ b/arch/mips/lib/traps.c
@@ -99,7 +99,7 @@
 	flush_cache(ebase + offset, size);
 }
 
-void trap_init(ulong reloc_addr)
+static void trap_init(ulong reloc_addr)
 {
 	unsigned long ebase = gd->irq_sp;
 
@@ -131,3 +131,10 @@
 	clear_c0_status(ST0_BEV);
 	execution_hazard_barrier();
 }
+
+int arch_initr_trap(void)
+{
+	trap_init(CONFIG_SYS_SDRAM_BASE);
+
+	return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index e0f0f7e..e920e01 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -1028,7 +1028,7 @@
 	mtmsr(msr);
 }
 
-void cpu_secondary_init_r(void)
+int cpu_secondary_init_r(void)
 {
 #ifdef CONFIG_QE
 #ifdef CONFIG_U_QE
@@ -1040,6 +1040,8 @@
 	qe_init(qe_base);
 	qe_reset();
 #endif
+
+	return 0;
 }
 
 #ifdef CONFIG_BOARD_LATE_INIT
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index f61809a..2782740 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -40,6 +40,7 @@
 obj-$(CONFIG_CMD_KGDB) += kgdb.o
 obj-y	+= stack.o
 obj-y	+= time.o
+obj-y	+= traps.o
 endif # not minimal
 
 ifdef CONFIG_SPL_BUILD
diff --git a/arch/powerpc/lib/traps.c b/arch/powerpc/lib/traps.c
new file mode 100644
index 0000000..288e377
--- /dev/null
+++ b/arch/powerpc/lib/traps.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <init.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void trap_init(unsigned long reloc_addr);
+
+int arch_initr_trap(void)
+{
+	trap_init(gd->relocaddr);
+
+	return 0;
+}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 8322ed7a..2d18d9d 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -9,6 +9,7 @@
 #include <efi_loader.h>
 #include <errno.h>
 #include <init.h>
+#include <log.h>
 #include <os.h>
 #include <cli.h>
 #include <sort.h>
@@ -486,6 +487,10 @@
 	 */
 	gd->reloc_off = (ulong)gd->arch.text_base;
 
+	/* sandbox test: log functions called before log_init in board_init_f */
+	log_info("sandbox: starting...\n");
+	log_debug("debug: %s\n", __func__);
+
 	/* Do pre- and post-relocation init */
 	board_init_f(0);
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index da86a94..1b53e5b 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -122,6 +122,7 @@
 
 config CMD_CPU
 	bool "cpu"
+	depends on CPU
 	help
 	  Print information about available CPUs. This normally shows the
 	  number of CPUs, type (e.g. manufacturer, architecture, product or
@@ -1034,6 +1035,14 @@
 	  Print list of available block device drivers, and for each, the list
 	  of known block devices.
 
+config CMD_MBR
+	bool "MBR (Master Boot Record) command"
+	select DOS_PARTITION
+	select HAVE_BLOCK_DEVICE
+	help
+	  Enable the 'mbr' command to ready and write MBR (Master Boot Record)
+	  style partition tables.
+
 config CMD_MISC
 	bool "misc"
 	depends on MISC
diff --git a/cmd/Makefile b/cmd/Makefile
index 5b3400a..87aa949 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -178,6 +178,7 @@
 
 obj-$(CONFIG_CMD_DFU) += dfu.o
 obj-$(CONFIG_CMD_GPT) += gpt.o
+obj-$(CONFIG_CMD_MBR) += mbr.o
 obj-$(CONFIG_CMD_ETHSW) += ethsw.o
 obj-$(CONFIG_CMD_AXI) += axi.o
 obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o
diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index 1ba7b62..409ef9a 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -45,6 +45,7 @@
 	KEY_UP,
 	KEY_DOWN,
 	KEY_SELECT,
+	KEY_QUIT,
 };
 
 static char *bootmenu_getoption(unsigned short int n)
@@ -109,6 +110,9 @@
 			case '\r':
 				*key = KEY_SELECT;
 				break;
+			case 0x3: /* ^C */
+				*key = KEY_QUIT;
+				break;
 			default:
 				*key = KEY_NONE;
 				break;
@@ -136,13 +140,25 @@
 {
 	int c;
 
-	while (!tstc()) {
-		WATCHDOG_RESET();
-		mdelay(10);
+	if (*esc == 1) {
+		if (tstc()) {
+			c = getchar();
+		} else {
+			WATCHDOG_RESET();
+			mdelay(10);
+			if (tstc())
+				c = getchar();
+			else
+				c = '\e';
+		}
+	} else {
+		while (!tstc()) {
+			WATCHDOG_RESET();
+			mdelay(10);
+		}
+		c = getchar();
 	}
 
-	c = getchar();
-
 	switch (*esc) {
 	case 0:
 		/* First char of ANSI escape sequence '\e' */
@@ -157,7 +173,9 @@
 			*esc = 2;
 			*key = KEY_NONE;
 		} else {
-			*esc = 0;
+		/* Alone ESC key was pressed */
+			*key = KEY_QUIT;
+			*esc = (c == '\e') ? 1 : 0;
 		}
 		break;
 	case 2:
@@ -187,6 +205,10 @@
 	/* enter key was pressed */
 	if (c == '\r')
 		*key = KEY_SELECT;
+
+	/* ^C was pressed */
+	if (c == 0x3)
+		*key = KEY_QUIT;
 }
 
 static char *bootmenu_choice_entry(void *data)
@@ -222,6 +244,12 @@
 			for (i = 0; i < menu->active; ++i)
 				iter = iter->next;
 			return iter->key;
+		case KEY_QUIT:
+			/* Quit by choosing the last entry - U-Boot console */
+			iter = menu->first;
+			while (iter->next)
+				iter = iter->next;
+			return iter->key;
 		default:
 			break;
 		}
@@ -389,7 +417,7 @@
 	printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
 	puts(ANSI_CLEAR_LINE);
 	printf(ANSI_CURSOR_POSITION, menu->count + 6, 1);
-	puts("  Press UP/DOWN to move, ENTER to select");
+	puts("  Press UP/DOWN to move, ENTER to select, ESC/CTRL+C to quit");
 	puts(ANSI_CLEAR_LINE_TO_END);
 	printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
 	puts(ANSI_CLEAR_LINE);
diff --git a/cmd/disk.c b/cmd/disk.c
index 8060e75..0bc3808 100644
--- a/cmd/disk.c
+++ b/cmd/disk.c
@@ -120,7 +120,6 @@
 			return 1;
 		}
 		bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
-		fit_print_contents(fit_hdr);
 	}
 #endif
 
diff --git a/cmd/gpt.c b/cmd/gpt.c
index df75941..76a95ad 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -18,6 +18,7 @@
 #include <command.h>
 #include <part.h>
 #include <part_efi.h>
+#include <part.h>
 #include <exports.h>
 #include <uuid.h>
 #include <linux/ctype.h>
@@ -621,6 +622,152 @@
 	return ret;
 }
 
+/**
+ * gpt_enumerate() - Enumerate partition names into environment variable.
+ *
+ * Enumerate partition names. Partition names are stored in gpt_partition_list
+ * environment variable. Each partition name is delimited by space.
+ *
+ * @desc: block device descriptor
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_enumerate(struct blk_desc *desc)
+{
+	struct part_driver *first_drv, *part_drv;
+	int str_len = 0, tmp_len;
+	char part_list[2048];
+	int n_drvs;
+	char *ptr;
+
+	part_list[0] = 0;
+	n_drvs = part_driver_get_count();
+	if (!n_drvs) {
+		printf("Failed to get partition driver count\n");
+		return -ENOENT;
+	}
+
+	first_drv = part_driver_get_first();
+	for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) {
+		struct disk_partition pinfo;
+		int ret;
+		int i;
+
+		for (i = 1; i < part_drv->max_entries; i++) {
+			ret = part_drv->get_info(desc, i, &pinfo);
+			if (ret) {
+				/* no more entries in table */
+				break;
+			}
+
+			ptr = &part_list[str_len];
+			tmp_len = strlen((const char *)pinfo.name);
+			str_len += tmp_len;
+			/* +1 for space */
+			str_len++;
+			if (str_len > sizeof(part_list)) {
+				printf("Error insufficient memory\n");
+				return -ENOMEM;
+			}
+			strcpy(ptr, (const char *)pinfo.name);
+			/* One byte for space(" ") delimiter */
+			ptr[tmp_len] = ' ';
+		}
+	}
+	if (*part_list)
+		part_list[strlen(part_list) - 1] = 0;
+	debug("setenv gpt_partition_list %s\n", part_list);
+
+	return env_set("gpt_partition_list", part_list);
+}
+
+/**
+ * gpt_setenv_part_variables() - setup partition environmental variables
+ *
+ * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
+ * and gpt_partition_size environment variables.
+ *
+ * @pinfo: pointer to disk partition
+ * @i: partition entry
+ *
+ * @Return: '0' on success and -ENOENT on failure
+ */
+static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
+{
+	int ret;
+
+	ret = env_set_hex("gpt_partition_addr", pinfo->start);
+	if (ret)
+		goto fail;
+
+	ret = env_set_hex("gpt_partition_size", pinfo->size);
+	if (ret)
+		goto fail;
+
+	ret = env_set_ulong("gpt_partition_entry", i);
+	if (ret)
+		goto fail;
+
+	ret = env_set("gpt_partition_name", (const char *)pinfo->name);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	return -ENOENT;
+}
+
+/**
+ * gpt_setenv() - Dynamically setup environment variables.
+ *
+ * Dynamically setup environment variables for name, index, offset and size
+ * for partition in GPT table after running "gpt setenv" for a partition name.
+ *
+ * @desc: block device descriptor
+ * @name: partition name
+ *
+ * @Return: '0' on success and -ve err on failure
+ */
+static int gpt_setenv(struct blk_desc *desc, const char *name)
+{
+	struct part_driver *first_drv, *part_drv;
+	int n_drvs;
+	int ret = -1;
+
+	n_drvs = part_driver_get_count();
+	if (!n_drvs) {
+		printf("Failed to get partition driver count\n");
+		goto fail;
+	}
+
+	first_drv = part_driver_get_first();
+	for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) {
+		struct disk_partition pinfo;
+		int i;
+
+		for (i = 1; i < part_drv->max_entries; i++) {
+			ret = part_drv->get_info(desc, i, &pinfo);
+			if (ret) {
+				/* no more entries in table */
+				break;
+			}
+
+			if (!strcmp(name, (const char *)pinfo.name)) {
+				/* match found, setup environment variables */
+				ret = gpt_setenv_part_variables(&pinfo, i);
+				if (ret)
+					goto fail;
+
+				return 0;
+			}
+		}
+	}
+
+fail:
+	return ret;
+}
+
 static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
 {
 	int ret;
@@ -827,6 +974,10 @@
 	} else if ((strcmp(argv[1], "verify") == 0)) {
 		ret = gpt_verify(blk_dev_desc, argv[4]);
 		printf("Verify GPT: ");
+	} else if ((strcmp(argv[1], "setenv") == 0)) {
+		ret = gpt_setenv(blk_dev_desc, argv[4]);
+	} else if ((strcmp(argv[1], "enumerate") == 0)) {
+		ret = gpt_enumerate(blk_dev_desc);
 	} else if (strcmp(argv[1], "guid") == 0) {
 		ret = do_disk_guid(blk_dev_desc, argv[4]);
 #ifdef CONFIG_CMD_GPT_RENAME
@@ -857,7 +1008,17 @@
 	" to interface\n"
 	" Example usage:\n"
 	" gpt write mmc 0 $partitions\n"
+	"    - write the GPT to device\n"
 	" gpt verify mmc 0 $partitions\n"
+	"    - verify the GPT on device against $partitions\n"
+	" gpt setenv mmc 0 $name\n"
+	"    - setup environment variables for partition $name:\n"
+	"      gpt_partition_addr, gpt_partition_size,\n"
+	"      gpt_partition_name, gpt_partition_entry\n"
+	" gpt enumerate mmc 0\n"
+	"    - store list of partitions to gpt_partition_list environment variable\n"
+	" read <interface> <dev>\n"
+	"    - read GPT into a data structure for manipulation\n"
 	" gpt guid <interface> <dev>\n"
 	"    - print disk GUID\n"
 	" gpt guid <interface> <dev> <varname>\n"
diff --git a/cmd/mbr.c b/cmd/mbr.c
new file mode 100644
index 0000000..da2e3a4
--- /dev/null
+++ b/cmd/mbr.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_mbr.c -- MBR (Master Boot Record) handling command
+ *
+ * Copyright (C) 2020 Samsung Electronics
+ * author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * based on the gpt command.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <malloc.h>
+#include <part.h>
+
+/**
+ * extract_val() - Extract a value from the key=value pair list
+ * @str: pointer to string with key=values pairs
+ * @key: pointer to the key to search for
+ *
+ * The list of parameters is come separated, only a value for
+ * the given key is returend.
+ *
+ * Function allocates memory for the value, remember to free!
+ *
+ * Return: Pointer to allocated string with the value.
+ */
+static char *extract_val(const char *str, const char *key)
+{
+	char *v, *k;
+	char *s, *strcopy;
+	char *new = NULL;
+
+	strcopy = strdup(str);
+	if (strcopy == NULL)
+		return NULL;
+
+	s = strcopy;
+	while (s) {
+		v = strsep(&s, ",");
+		if (!v)
+			break;
+		k = strsep(&v, "=");
+		if (!k)
+			break;
+		if  (strcmp(k, key) == 0) {
+			new = strdup(v);
+			break;
+		}
+	}
+
+	free(strcopy);
+
+	return new;
+}
+
+/**
+ * found_key() - Search for a key without a value in the parameter list
+ * @str: pointer to string with key
+ * @key: pointer to the key to search for
+ *
+ * The list of parameters is come separated.
+ *
+ * Return: True if key has been found.
+ */
+static bool found_key(const char *str, const char *key)
+{
+	char *k;
+	char *s, *strcopy;
+	bool result = false;
+
+	strcopy = strdup(str);
+	if (!strcopy)
+		return NULL;
+
+	s = strcopy;
+	while (s) {
+		k = strsep(&s, ",");
+		if (!k)
+			break;
+		if  (strcmp(k, key) == 0) {
+			result = true;
+			break;
+		}
+	}
+
+	free(strcopy);
+
+	return result;
+}
+
+static int str_to_partitions(const char *str_part, int blksz,
+	unsigned long *disk_uuid, struct disk_partition **partitions,
+	int *parts_count)
+{
+	char *tok, *str, *s;
+	int i;
+	char *val, *p;
+	int p_count;
+	struct disk_partition *parts;
+	int errno = 0;
+	uint64_t size_ll, start_ll;
+
+	if (str_part == NULL)
+		return -1;
+
+	str = strdup(str_part);
+	if (str == NULL)
+		return -ENOMEM;
+
+	/* extract disk guid */
+	s = str;
+	val = extract_val(str, "uuid_disk");
+	if (val) {
+		val = strsep(&val, ";");
+		p = val;
+		*disk_uuid = ustrtoull(p, &p, 0);
+		free(val);
+		/* Move s to first partition */
+		strsep(&s, ";");
+	}
+	if (s == NULL) {
+		printf("Error: is the partitions string NULL-terminated?\n");
+		return -EINVAL;
+	}
+
+	/* remove the optional semicolon at the end of the string */
+	i = strlen(s) - 1;
+	if (s[i] == ';')
+		s[i] = '\0';
+
+	/* calculate expected number of partitions */
+	p_count = 1;
+	p = s;
+	while (*p) {
+		if (*p++ == ';')
+			p_count++;
+	}
+
+	/* allocate memory for partitions */
+	parts = calloc(sizeof(struct disk_partition), p_count);
+	if (parts == NULL)
+		return -ENOMEM;
+
+	/* retrieve partitions data from string */
+	for (i = 0; i < p_count; i++) {
+		tok = strsep(&s, ";");
+
+		if (tok == NULL)
+			break;
+
+		/* size */
+		val = extract_val(tok, "size");
+		if (!val) { /* 'size' is mandatory */
+			errno = -4;
+			goto err;
+		}
+		p = val;
+		if ((strcmp(p, "-") == 0)) {
+			/* auto extend the size */
+			parts[i].size = 0;
+		} else {
+			size_ll = ustrtoull(p, &p, 0);
+			parts[i].size = size_ll / blksz;
+		}
+		free(val);
+
+		/* start address */
+		val = extract_val(tok, "start");
+		if (val) { /* start address is optional */
+			p = val;
+			start_ll = ustrtoull(p, &p, 0);
+			parts[i].start = start_ll / blksz;
+			free(val);
+		}
+
+		/* system id */
+		val = extract_val(tok, "id");
+		if (!val) { /* '' is mandatory */
+			errno = -4;
+			goto err;
+		}
+		p = val;
+		parts[i].sys_ind = ustrtoul(p, &p, 0);
+		free(val);
+
+		/* bootable */
+		if (found_key(tok, "bootable"))
+			parts[i].bootable = PART_BOOTABLE;
+	}
+
+	*parts_count = p_count;
+	*partitions = parts;
+	free(str);
+
+	return 0;
+err:
+	free(str);
+	free(parts);
+
+	return errno;
+}
+
+static int do_write_mbr(struct blk_desc *dev, const char *str)
+{
+	unsigned long disk_uuid = 0;
+	struct disk_partition *partitions;
+	int blksz = dev->blksz;
+	int count;
+
+	if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
+		printf("MBR: failed to setup partitions from \"%s\"\n", str);
+		return -1;
+	}
+
+	if (layout_mbr_partitions(partitions, count, dev->lba)) {
+		printf("MBR: failed to layout partitions on the device\n");
+		free(partitions);
+		return -1;
+	}
+
+	if (write_mbr_partitions(dev, partitions, count, disk_uuid)) {
+		printf("MBR: failed to write partitions to the device\n");
+		free(partitions);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int do_verify_mbr(struct blk_desc *dev, const char *str)
+{
+	unsigned long disk_uuid = 0;
+	struct disk_partition *partitions;
+	int blksz = dev->blksz;
+	int count, i, ret = 1;
+
+	if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
+		printf("MBR: failed to setup partitions from \"%s\"\n", str);
+		return -1;
+	}
+
+	for (i = 0; i < count; i++) {
+		struct disk_partition p;
+
+		if (part_get_info(dev, i+1, &p))
+			goto fail;
+
+		if ((partitions[i].size && p.size < partitions[i].size) ||
+		    (partitions[i].start && p.start < partitions[i].start) ||
+		    (p.sys_ind != partitions[i].sys_ind))
+			goto fail;
+	}
+	ret = 0;
+fail:
+	free(partitions);
+	return ret;
+}
+
+static int do_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	const char *parts = NULL;
+	int ret = CMD_RET_SUCCESS;
+	int dev = 0;
+	char *ep;
+	struct blk_desc *blk_dev_desc = NULL;
+
+	if (argc != 4 && argc != 5)
+		return CMD_RET_USAGE;
+
+	dev = (int)simple_strtoul(argv[3], &ep, 10);
+	if (!ep || ep[0] != '\0') {
+		printf("'%s' is not a number\n", argv[3]);
+		return CMD_RET_USAGE;
+	}
+	blk_dev_desc = blk_get_dev(argv[2], dev);
+	if (!blk_dev_desc) {
+		printf("%s: %s dev %d NOT available\n",
+		       __func__, argv[2], dev);
+		return CMD_RET_FAILURE;
+	}
+
+	if ((strcmp(argv[1], "write") == 0)) {
+		parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
+		printf("MBR: write ");
+		ret = do_write_mbr(blk_dev_desc, parts);
+	} else if ((strcmp(argv[1], "verify") == 0)) {
+		printf("MBR: verify ");
+		parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
+		ret = do_verify_mbr(blk_dev_desc, parts);
+	} else {
+		return CMD_RET_USAGE;
+	}
+
+	if (ret) {
+		printf("error!\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("success!\n");
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
+	"MBR (Master Boot Record)",
+	"<command> <interface> <dev> <partitions_list>\n"
+	" - MBR partition table restoration utility\n"
+	" Restore or check partition information on a device connected\n"
+	" to the given block interface\n"
+	" Example usage:\n"
+	" mbr write mmc 0 [\"${mbr_parts}\"]\n"
+	" mbr verify mmc 0 [\"${partitions}\"]\n"
+);
diff --git a/common/Kconfig b/common/Kconfig
index 2bce8c9..d8982ba 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -17,6 +17,14 @@
 	  To enable console recording, call console_record_reset_enable()
 	  from your code.
 
+config CONSOLE_RECORD_INIT_F
+	bool "Enable console recording during pre-relocation init"
+	depends on CONSOLE_RECORD && SYS_MALLOC_F
+	default y
+	help
+	  This option enables console recording during pre-relocation init.
+	  CONFIG_SYS_MALLOC_F must be enabled to use this feature.
+
 config CONSOLE_RECORD_OUT_SIZE
 	hex "Output buffer size"
 	depends on CONSOLE_RECORD
diff --git a/common/Kconfig.boot b/common/Kconfig.boot
index 58e9854..4525a12 100644
--- a/common/Kconfig.boot
+++ b/common/Kconfig.boot
@@ -819,7 +819,10 @@
 	  This option adds the feature to only stop the autobooting,
 	  and therefore boot into the U-Boot prompt, when the input
 	  string / password matches a values that is encypted via
-	  a SHA256 hash and saved in the environment.
+	  a SHA256 hash and saved in the environment variable
+	  "bootstopkeysha256". If the value in that variable
+	  includes a ":", the portion prior to the ":" will be treated
+	  as a salt value.
 
 config AUTOBOOT_USE_MENUKEY
 	bool "Allow a specify key to run a menu from the environment"
diff --git a/common/Makefile b/common/Makefile
index bcf352d..daeea67 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -68,7 +68,6 @@
 endif
 obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o
 obj-$(CONFIG_TPL_HASH_SUPPORT) += hash.o
-obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
 obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
 obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
diff --git a/common/autoboot.c b/common/autoboot.c
index e628baf..ddb6246 100644
--- a/common/autoboot.c
+++ b/common/autoboot.c
@@ -25,7 +25,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define MAX_DELAY_STOP_STR 32
+#define MAX_DELAY_STOP_STR 64
 
 #ifndef DEBUG_BOOTKEYS
 #define DEBUG_BOOTKEYS 0
@@ -80,6 +80,7 @@
 	u8 sha_env[SHA256_SUM_LEN];
 	u8 *sha;
 	char *presskey;
+	char *c;
 	const char *algo_name = "sha256";
 	u_int presskey_len = 0;
 	int abort = 0;
@@ -89,6 +90,14 @@
 	if (sha_env_str == NULL)
 		sha_env_str = AUTOBOOT_STOP_STR_SHA256;
 
+	presskey = malloc_cache_aligned(MAX_DELAY_STOP_STR);
+	c = strstr(sha_env_str, ":");
+	if (c && (c - sha_env_str < MAX_DELAY_STOP_STR)) {
+		/* preload presskey with salt */
+		memcpy(presskey, sha_env_str, c - sha_env_str);
+		presskey_len = c - sha_env_str;
+		sha_env_str = c + 1;
+	}
 	/*
 	 * Generate the binary value from the environment hash value
 	 * so that we can compare this value with the computed hash
@@ -100,7 +109,6 @@
 		return 0;
 	}
 
-	presskey = malloc_cache_aligned(MAX_DELAY_STOP_STR);
 	sha = malloc_cache_aligned(SHA256_SUM_LEN);
 	size = SHA256_SUM_LEN;
 	/*
diff --git a/common/board_f.c b/common/board_f.c
index 9f441c4..ae3001b 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -503,14 +503,6 @@
 	return 0;
 }
 
-static int setup_machine(void)
-{
-#ifdef CONFIG_MACH_TYPE
-	gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
-#endif
-	return 0;
-}
-
 static int reserve_global_data(void)
 {
 	gd->start_addr_sp = reserve_stack_aligned(sizeof(gd_t));
@@ -522,21 +514,21 @@
 
 static int reserve_fdt(void)
 {
-#ifndef CONFIG_OF_EMBED
-	/*
-	 * If the device tree is sitting immediately above our image then we
-	 * must relocate it. If it is embedded in the data section, then it
-	 * will be relocated with other data.
-	 */
-	if (gd->fdt_blob) {
-		gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+	if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+		/*
+		 * If the device tree is sitting immediately above our image
+		 * then we must relocate it. If it is embedded in the data
+		 * section, then it will be relocated with other data.
+		 */
+		if (gd->fdt_blob) {
+			gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
 
-		gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
-		gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
-		debug("Reserving %lu Bytes for FDT at: %08lx\n",
-		      gd->fdt_size, gd->start_addr_sp);
+			gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
+			gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
+			debug("Reserving %lu Bytes for FDT at: %08lx\n",
+			      gd->fdt_size, gd->start_addr_sp);
+		}
 	}
-#endif
 
 	return 0;
 }
@@ -605,6 +597,10 @@
 		bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE;  /* size  of SRAM */
 	}
 
+#ifdef CONFIG_MACH_TYPE
+	bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
+#endif
+
 	return arch_setup_bdinfo();
 }
 
@@ -620,14 +616,15 @@
 
 static int reloc_fdt(void)
 {
-#ifndef CONFIG_OF_EMBED
-	if (gd->flags & GD_FLG_SKIP_RELOC)
-		return 0;
-	if (gd->new_fdt) {
-		memcpy(gd->new_fdt, gd->fdt_blob, fdt_totalsize(gd->fdt_blob));
-		gd->fdt_blob = gd->new_fdt;
+	if (!IS_ENABLED(CONFIG_OF_EMBED)) {
+		if (gd->flags & GD_FLG_SKIP_RELOC)
+			return 0;
+		if (gd->new_fdt) {
+			memcpy(gd->new_fdt, gd->fdt_blob,
+			       fdt_totalsize(gd->fdt_blob));
+			gd->fdt_blob = gd->new_fdt;
+		}
 	}
-#endif
 
 	return 0;
 }
@@ -765,15 +762,6 @@
 	return 0;
 }
 
-static int initf_console_record(void)
-{
-#if defined(CONFIG_CONSOLE_RECORD) && CONFIG_VAL(SYS_MALLOC_F_LEN)
-	return console_record_init();
-#else
-	return 0;
-#endif
-}
-
 static int initf_dm(void)
 {
 #if defined(CONFIG_DM) && CONFIG_VAL(SYS_MALLOC_F_LEN)
@@ -784,11 +772,12 @@
 	bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
 	if (ret)
 		return ret;
-#endif
-#ifdef CONFIG_TIMER_EARLY
-	ret = dm_timer_init();
-	if (ret)
-		return ret;
+
+	if (IS_ENABLED(CONFIG_TIMER_EARLY)) {
+		ret = dm_timer_init();
+		if (ret)
+			return ret;
+	}
 #endif
 
 	return 0;
@@ -830,7 +819,9 @@
 	bloblist_init,
 #endif
 	setup_spl_handoff,
-	initf_console_record,
+#if defined(CONFIG_CONSOLE_RECORD_INIT_F)
+	console_record_init,
+#endif
 #if defined(CONFIG_HAVE_FSP)
 	arch_fsp_init,
 #endif
@@ -922,7 +913,6 @@
 	reserve_uboot,
 	reserve_malloc,
 	reserve_board,
-	setup_machine,
 	reserve_global_data,
 	reserve_fdt,
 	reserve_bootstage,
diff --git a/common/board_r.c b/common/board_r.c
index 29dd7d2..9fa4d4b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -91,21 +91,8 @@
 	return 0;
 }
 
-__weak void cpu_secondary_init_r(void)
+__weak int cpu_secondary_init_r(void)
 {
-}
-
-static int initr_secondary_cpu(void)
-{
-	/*
-	 * after non-volatile devices & environment is setup and cpu code have
-	 * another round to deal with any initialization that might require
-	 * full access to the environment or loading of some image (firmware)
-	 * from a non-volatile device
-	 */
-	/* TODO: maybe define this for all archs? */
-	cpu_secondary_init_r();
-
 	return 0;
 }
 
@@ -195,20 +182,10 @@
 	return 0;
 }
 
-#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
-static int initr_trap(void)
+__weak int arch_initr_trap(void)
 {
-	/*
-	 * Setup trap handlers
-	 */
-#if defined(CONFIG_PPC)
-	trap_init(gd->relocaddr);
-#else
-	trap_init(CONFIG_SYS_SDRAM_BASE);
-#endif
 	return 0;
 }
-#endif
 
 #ifdef CONFIG_ADDR_MAP
 static int initr_addr_map(void)
@@ -219,14 +196,6 @@
 }
 #endif
 
-#ifdef CONFIG_POST
-static int initr_post_backlog(void)
-{
-	post_output_backlog();
-	return 0;
-}
-#endif
-
 #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
 static int initr_unlock_ram_in_cache(void)
 {
@@ -235,25 +204,6 @@
 }
 #endif
 
-#ifdef CONFIG_PCI_ENDPOINT
-static int initr_pci_ep(void)
-{
-	pci_ep_init();
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PCI
-static int initr_pci(void)
-{
-	if (IS_ENABLED(CONFIG_PCI_INIT_R))
-		pci_init();
-
-	return 0;
-}
-#endif
-
 static int initr_barrier(void)
 {
 #ifdef CONFIG_PPC
@@ -282,23 +232,6 @@
 	return 0;
 }
 
-static int initr_console_record(void)
-{
-#if defined(CONFIG_CONSOLE_RECORD)
-	return console_record_init();
-#else
-	return 0;
-#endif
-}
-
-#ifdef CONFIG_SYS_NONCACHED_MEMORY
-static int initr_noncached(void)
-{
-	noncached_init();
-	return 0;
-}
-#endif
-
 static int initr_of_live(void)
 {
 	if (CONFIG_IS_ENABLED(OF_LIVE)) {
@@ -485,14 +418,6 @@
 }
 #endif
 
-#ifdef CONFIG_XEN
-static int initr_xen(void)
-{
-	xen_init();
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_PVBLOCK
 static int initr_pvblock(void)
 {
@@ -555,21 +480,6 @@
 }
 #endif
 
-static int initr_jumptable(void)
-{
-	jumptable_init();
-	return 0;
-}
-
-#if defined(CONFIG_API)
-static int initr_api(void)
-{
-	/* Initialize API */
-	api_init();
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_CMD_NET
 static int initr_ethaddr(void)
 {
@@ -614,14 +524,6 @@
 }
 #endif
 
-#ifdef CONFIG_BITBANGMII
-static int initr_bbmii(void)
-{
-	bb_miiphy_init();
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_CMD_NET
 static int initr_net(void)
 {
@@ -713,9 +615,11 @@
 	initr_malloc,
 	log_init,
 	initr_bootstage,	/* Needs malloc() but has its own timer */
-	initr_console_record,
+#if defined(CONFIG_CONSOLE_RECORD)
+	console_record_init,
+#endif
 #ifdef CONFIG_SYS_NONCACHED_MEMORY
-	initr_noncached,
+	noncached_init,
 #endif
 	initr_of_live,
 #ifdef CONFIG_DM
@@ -755,9 +659,7 @@
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
 	initr_manual_reloc_cmdtable,
 #endif
-#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
-	initr_trap,
-#endif
+	arch_initr_trap,
 #ifdef CONFIG_ADDR_MAP
 	initr_addr_map,
 #endif
@@ -766,15 +668,15 @@
 #endif
 	INIT_FUNC_WATCHDOG_RESET
 #ifdef CONFIG_POST
-	initr_post_backlog,
+	post_output_backlog,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
-#if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
+#if defined(CONFIG_PCI_INIT_R) && defined(CONFIG_SYS_EARLY_PCI_INIT)
 	/*
 	 * Do early PCI configuration _before_ the flash gets initialised,
 	 * because PCU resources are crucial for flash access on some boards.
 	 */
-	initr_pci,
+	pci_init,
 #endif
 #ifdef CONFIG_ARCH_EARLY_INIT_R
 	arch_early_init_r,
@@ -798,7 +700,7 @@
 	initr_mmc,
 #endif
 #ifdef CONFIG_XEN
-	initr_xen,
+	xen_init,
 #endif
 #ifdef CONFIG_PVBLOCK
 	initr_pvblock,
@@ -808,21 +710,21 @@
 	initr_malloc_bootparams,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
-	initr_secondary_cpu,
+	cpu_secondary_init_r,
 #if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
 	mac_read_from_eeprom,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
-#if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
+#if defined(CONFIG_PCI_INIT_R) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
 	/*
 	 * Do pci configuration
 	 */
-	initr_pci,
+	pci_init,
 #endif
 	stdio_add_devices,
-	initr_jumptable,
+	jumptable_init,
 #ifdef CONFIG_API
-	initr_api,
+	api_init,
 #endif
 	console_init_r,		/* fully init console as a device */
 #ifdef CONFIG_DISPLAY_BOARDINFO_LATE
@@ -861,10 +763,10 @@
 	initr_scsi,
 #endif
 #ifdef CONFIG_BITBANGMII
-	initr_bbmii,
+	bb_miiphy_init,
 #endif
 #ifdef CONFIG_PCI_ENDPOINT
-	initr_pci_ep,
+	pci_ep_init,
 #endif
 #ifdef CONFIG_CMD_NET
 	INIT_FUNC_WATCHDOG_RESET
diff --git a/common/cli_readline.c b/common/cli_readline.c
index 47b8762..5c158d0 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -493,8 +493,10 @@
 		}
 #endif
 		default:
-			cread_add_char(ichar, insert, &num, &eol_num, buf,
-				       *len);
+			if (ichar >= ' ' && ichar <= '~') {
+				cread_add_char(ichar, insert, &num, &eol_num,
+					       buf, *len);
+			}
 			break;
 		}
 	}
diff --git a/common/command.c b/common/command.c
index 068cb55..3fe6791 100644
--- a/common/command.c
+++ b/common/command.c
@@ -16,6 +16,8 @@
 #include <log.h>
 #include <linux/ctype.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Use puts() instead of printf() to avoid printf buffer overflow
  * for long help messages
@@ -488,9 +490,6 @@
 }
 #endif
 
-#if defined(CONFIG_NEEDS_MANUAL_RELOC)
-DECLARE_GLOBAL_DATA_PTR;
-
 void fixup_cmdtable(struct cmd_tbl *cmdtp, int size)
 {
 	int	i;
@@ -535,7 +534,6 @@
 		cmdtp++;
 	}
 }
-#endif
 
 int cmd_always_repeatable(struct cmd_tbl *cmdtp, int flag, int argc,
 			  char *const argv[], int *repeatable)
diff --git a/common/console.c b/common/console.c
index 3348436..f3cc45c 100644
--- a/common/console.c
+++ b/common/console.c
@@ -44,14 +44,15 @@
 	case env_op_create:
 	case env_op_overwrite:
 
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
-		if (iomux_doenv(console, value))
-			return 1;
-#else
-		/* Try assigning specified device */
-		if (console_assign(console, value) < 0)
-			return 1;
-#endif
+		if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
+			if (iomux_doenv(console, value))
+				return 1;
+		} else {
+			/* Try assigning specified device */
+			if (console_assign(console, value) < 0)
+				return 1;
+		}
+
 		return 0;
 
 	case env_op_delete:
@@ -69,14 +70,13 @@
 static int on_silent(const char *name, const char *value, enum env_op op,
 	int flags)
 {
-#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)
-	if (flags & H_INTERACTIVE)
-		return 0;
-#endif
-#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)
-	if ((flags & H_INTERACTIVE) == 0)
-		return 0;
-#endif
+	if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET))
+		if (flags & H_INTERACTIVE)
+			return 0;
+
+	if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC))
+		if ((flags & H_INTERACTIVE) == 0)
+			return 0;
 
 	if (value != NULL)
 		gd->flags |= GD_FLG_SILENT;
@@ -88,6 +88,64 @@
 U_BOOT_ENV_CALLBACK(silent, on_silent);
 #endif
 
+#ifdef CONFIG_CONSOLE_RECORD
+/* helper function: access to gd->console_out and gd->console_in */
+static void console_record_putc(const char c)
+{
+	if (!(gd->flags & GD_FLG_RECORD))
+		return;
+	if  (gd->console_out.start)
+		membuff_putbyte((struct membuff *)&gd->console_out, c);
+}
+
+static void console_record_puts(const char *s)
+{
+	if (!(gd->flags & GD_FLG_RECORD))
+		return;
+	if  (gd->console_out.start)
+		membuff_put((struct membuff *)&gd->console_out, s, strlen(s));
+}
+
+static int console_record_getc(void)
+{
+	if (!(gd->flags & GD_FLG_RECORD))
+		return -1;
+	if (!gd->console_in.start)
+		return -1;
+
+	return membuff_getbyte((struct membuff *)&gd->console_in);
+}
+
+static int console_record_tstc(void)
+{
+	if (!(gd->flags & GD_FLG_RECORD))
+		return 0;
+	if (gd->console_in.start) {
+		if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
+			return 1;
+	}
+	return 0;
+}
+#else
+static void console_record_putc(char c)
+{
+}
+
+static void console_record_puts(const char *s)
+{
+}
+
+static int console_record_getc(void)
+{
+	return -1;
+}
+
+static int console_record_tstc(void)
+{
+	return 0;
+}
+#endif
+
 #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
 /*
  * if overwrite_console returns 1, the stdin, stderr and stdout
@@ -114,13 +172,9 @@
 	case stdin:
 	case stdout:
 	case stderr:
-		/* Start new device */
-		if (dev->start) {
-			error = dev->start(dev);
-			/* If it's not started dont use it */
-			if (error < 0)
-				break;
-		}
+		error = console_start(file, dev);
+		if (error)
+			break;
 
 		/* Assign the new device (leaving the existing one started) */
 		stdio_devices[file] = dev;
@@ -159,14 +213,13 @@
 {
 	bool is_serial;
 
-#ifdef CONFIG_DM_SERIAL
-	if (sdev->flags & DEV_FLAGS_DM) {
+	if (IS_ENABLED(CONFIG_DM_SERIAL) && (sdev->flags & DEV_FLAGS_DM)) {
 		struct udevice *dev = sdev->priv;
 
 		is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
-	} else
-#endif
-	is_serial = !strcmp(sdev->name, "serial");
+	} else {
+		is_serial = !strcmp(sdev->name, "serial");
+	}
 
 	return is_serial;
 }
@@ -174,10 +227,42 @@
 #if CONFIG_IS_ENABLED(CONSOLE_MUX)
 /** Console I/O multiplexing *******************************************/
 
+/* tstcdev: save the last stdio device with pending characters, with tstc != 0 */
 static struct stdio_dev *tstcdev;
 struct stdio_dev **console_devices[MAX_FILES];
 int cd_count[MAX_FILES];
 
+static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
+{
+	console_devices[file][0] = dev;
+}
+
+/**
+ * console_needs_start_stop() - check if we need to start or stop the STDIO device
+ * @file: STDIO file
+ * @sdev: STDIO device in question
+ *
+ * This function checks if we need to start or stop the stdio device used for
+ * a console. For IOMUX case it simply enforces one time start and one time
+ * stop of the device independently of how many STDIO files are using it. In
+ * other words, we start console once before first STDIO device wants it and
+ * stop after the last is gone.
+ */
+static bool console_needs_start_stop(int file, struct stdio_dev *sdev)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
+		if (i == file)
+			continue;
+
+		for (j = 0; j < cd_count[i]; j++)
+			if (console_devices[i][j] == sdev)
+				return false;
+	}
+	return true;
+}
+
 /*
  * This depends on tstc() always being called before getchar().
  * This is guaranteed to be true because this routine is called
@@ -194,6 +279,12 @@
 	return ret;
 }
 
+/*  Upper layer may have already called tstc(): check the saved result */
+static bool console_has_tstc(void)
+{
+	return !!tstcdev;
+}
+
 static int console_tstc(int file)
 {
 	int i, ret;
@@ -276,11 +367,26 @@
 }
 #endif
 #else
+
+static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
+{
+}
+
+static inline bool console_needs_start_stop(int file, struct stdio_dev *sdev)
+{
+	return true;
+}
+
 static inline int console_getc(int file)
 {
 	return stdio_devices[file]->getc(stdio_devices[file]);
 }
 
+static bool console_has_tstc(void)
+{
+	return false;
+}
+
 static inline int console_tstc(int file)
 {
 	return stdio_devices[file]->tstc(stdio_devices[file]);
@@ -310,6 +416,32 @@
 #endif
 #endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
 
+int console_start(int file, struct stdio_dev *sdev)
+{
+	int error;
+
+	if (!console_needs_start_stop(file, sdev))
+		return 0;
+
+	/* Start new device */
+	if (sdev->start) {
+		error = sdev->start(sdev);
+		/* If it's not started don't use it */
+		if (error < 0)
+			return error;
+	}
+	return 0;
+}
+
+void console_stop(int file, struct stdio_dev *sdev)
+{
+	if (!console_needs_start_stop(file, sdev))
+		return;
+
+	if (sdev->stop)
+		sdev->stop(sdev);
+}
+
 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
 
 int serial_printf(const char *fmt, ...)
@@ -338,25 +470,25 @@
 		 */
 		for (;;) {
 			WATCHDOG_RESET();
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
-			/*
-			 * Upper layer may have already called tstc() so
-			 * check for that first.
-			 */
-			if (tstcdev != NULL)
-				return console_getc(file);
-			console_tstc(file);
-#else
-			if (console_tstc(file))
-				return console_getc(file);
-#endif
-#ifdef CONFIG_WATCHDOG
+			if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
+				/*
+				 * Upper layer may have already called tstc() so
+				 * check for that first.
+				 */
+				if (console_has_tstc())
+					return console_getc(file);
+				console_tstc(file);
+			} else {
+				if (console_tstc(file))
+					return console_getc(file);
+			}
+
 			/*
 			 * If the watchdog must be rate-limited then it should
 			 * already be handled in board-specific code.
 			 */
-			 udelay(1);
-#endif
+			if (IS_ENABLED(CONFIG_WATCHDOG))
+				udelay(1);
 		}
 	}
 
@@ -406,23 +538,18 @@
 
 int getchar(void)
 {
-#ifdef CONFIG_DISABLE_CONSOLE
-	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+	int ch;
+
+	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return 0;
-#endif
 
 	if (!gd->have_console)
 		return 0;
 
-#ifdef CONFIG_CONSOLE_RECORD
-	if (gd->console_in.start) {
-		int ch;
+	ch = console_record_getc();
+	if (ch != -1)
+		return ch;
 
-		ch = membuff_getbyte((struct membuff *)&gd->console_in);
-		if (ch != -1)
-			return 1;
-	}
-#endif
 	if (gd->flags & GD_FLG_DEVINIT) {
 		/* Get from the standard input */
 		return fgetc(stdin);
@@ -434,19 +561,15 @@
 
 int tstc(void)
 {
-#ifdef CONFIG_DISABLE_CONSOLE
-	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return 0;
-#endif
 
 	if (!gd->have_console)
 		return 0;
-#ifdef CONFIG_CONSOLE_RECORD
-	if (gd->console_in.start) {
-		if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
-			return 1;
-	}
-#endif
+
+	if (console_record_tstc())
+		return 1;
+
 	if (gd->flags & GD_FLG_DEVINIT) {
 		/* Test the standard input */
 		return ftstc(stdin);
@@ -485,10 +608,8 @@
 	char buf_out[CONFIG_PRE_CON_BUF_SZ + 1];
 	char *buf_in;
 
-#ifdef CONFIG_SILENT_CONSOLE
-	if (gd->flags & GD_FLG_SILENT)
+	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
 		return;
-#endif
 
 	buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
 	if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
@@ -517,38 +638,31 @@
 
 void putc(const char c)
 {
-#ifdef CONFIG_SANDBOX
+	if (!gd)
+		return;
+
+	console_record_putc(c);
+
 	/* sandbox can send characters to stdout before it has a console */
-	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+	if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
 		os_putc(c);
 		return;
 	}
-#endif
-#ifdef CONFIG_DEBUG_UART
+
 	/* if we don't have a console yet, use the debug UART */
-	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+	if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
 		printch(c);
 		return;
 	}
-#endif
-	if (!gd)
-		return;
-#ifdef CONFIG_CONSOLE_RECORD
-	if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
-		membuff_putbyte((struct membuff *)&gd->console_out, c);
-#endif
-#ifdef CONFIG_SILENT_CONSOLE
-	if (gd->flags & GD_FLG_SILENT) {
+
+	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
 		if (!(gd->flags & GD_FLG_DEVINIT))
 			pre_console_putc(c);
 		return;
 	}
-#endif
 
-#ifdef CONFIG_DISABLE_CONSOLE
-	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return;
-#endif
 
 	if (!gd->have_console)
 		return pre_console_putc(c);
@@ -565,15 +679,18 @@
 
 void puts(const char *s)
 {
-#ifdef CONFIG_SANDBOX
+	if (!gd)
+		return;
+
+	console_record_puts(s);
+
 	/* sandbox can send characters to stdout before it has a console */
-	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+	if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
 		os_puts(s);
 		return;
 	}
-#endif
-#ifdef CONFIG_DEBUG_UART
-	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+
+	if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
 		while (*s) {
 			int ch = *s++;
 
@@ -581,25 +698,15 @@
 		}
 		return;
 	}
-#endif
-	if (!gd)
-		return;
-#ifdef CONFIG_CONSOLE_RECORD
-	if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
-		membuff_put((struct membuff *)&gd->console_out, s, strlen(s));
-#endif
-#ifdef CONFIG_SILENT_CONSOLE
-	if (gd->flags & GD_FLG_SILENT) {
+
+	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
 		if (!(gd->flags & GD_FLG_DEVINIT))
 			pre_console_puts(s);
 		return;
 	}
-#endif
 
-#ifdef CONFIG_DISABLE_CONSOLE
-	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+	if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
 		return;
-#endif
 
 	if (!gd->have_console)
 		return pre_console_puts(s);
@@ -725,7 +832,7 @@
 
 /** U-Boot INIT FUNCTIONS *************************************************/
 
-struct stdio_dev *search_device(int flags, const char *name)
+struct stdio_dev *console_search_dev(int flags, const char *name)
 {
 	struct stdio_dev *dev;
 
@@ -761,7 +868,7 @@
 
 	/* Check for valid device name */
 
-	dev = search_device(flag, devname);
+	dev = console_search_dev(flag, devname);
 
 	if (dev)
 		return console_setfile(file, dev);
@@ -772,19 +879,19 @@
 /* return true if the 'silent' flag is removed */
 static bool console_update_silent(void)
 {
-#ifdef CONFIG_SILENT_CONSOLE
+	unsigned long flags = gd->flags;
+
+	if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
+		return false;
+
 	if (env_get("silent")) {
 		gd->flags |= GD_FLG_SILENT;
-	} else {
-		unsigned long flags = gd->flags;
-
-		gd->flags &= ~GD_FLG_SILENT;
-
-		return !!(flags & GD_FLG_SILENT);
+		return false;
 	}
-#endif
 
-	return false;
+	gd->flags &= ~GD_FLG_SILENT;
+
+	return !!(flags & GD_FLG_SILENT);
 }
 
 int console_announce_r(void)
@@ -843,12 +950,8 @@
 {
 	char *stdinname, *stdoutname, *stderrname;
 	struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
-#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
 	int i;
-#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
 	int iomux_err = 0;
-#endif
 	int flushpoint;
 
 	/* update silent for env loaded from flash (initr_env) */
@@ -871,27 +974,27 @@
 	stderrname = env_get("stderr");
 
 	if (OVERWRITE_CONSOLE == 0) {	/* if not overwritten by config switch */
-		inputdev  = search_device(DEV_FLAGS_INPUT,  stdinname);
-		outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
-		errdev    = search_device(DEV_FLAGS_OUTPUT, stderrname);
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
-		iomux_err = iomux_doenv(stdin, stdinname);
-		iomux_err += iomux_doenv(stdout, stdoutname);
-		iomux_err += iomux_doenv(stderr, stderrname);
-		if (!iomux_err)
-			/* Successful, so skip all the code below. */
-			goto done;
-#endif
+		inputdev  = console_search_dev(DEV_FLAGS_INPUT,  stdinname);
+		outputdev = console_search_dev(DEV_FLAGS_OUTPUT, stdoutname);
+		errdev    = console_search_dev(DEV_FLAGS_OUTPUT, stderrname);
+		if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
+			iomux_err = iomux_doenv(stdin, stdinname);
+			iomux_err += iomux_doenv(stdout, stdoutname);
+			iomux_err += iomux_doenv(stderr, stderrname);
+			if (!iomux_err)
+				/* Successful, so skip all the code below. */
+				goto done;
+		}
 	}
 	/* if the devices are overwritten or not found, use default device */
 	if (inputdev == NULL) {
-		inputdev  = search_device(DEV_FLAGS_INPUT,  "serial");
+		inputdev  = console_search_dev(DEV_FLAGS_INPUT,  "serial");
 	}
 	if (outputdev == NULL) {
-		outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
+		outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
 	}
 	if (errdev == NULL) {
-		errdev    = search_device(DEV_FLAGS_OUTPUT, "serial");
+		errdev    = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
 	}
 	/* Initializes output console first */
 	if (outputdev != NULL) {
@@ -907,33 +1010,25 @@
 		console_doenv(stdin, inputdev);
 	}
 
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
 done:
-#endif
 
-#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
-	stdio_print_current_devices();
-#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
+	if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
+		stdio_print_current_devices();
+
 #ifdef CONFIG_VIDCONSOLE_AS_LCD
 	if (strstr(stdoutname, CONFIG_VIDCONSOLE_AS_NAME))
 		printf("Warning: Please change '%s' to 'vidconsole' in stdout/stderr environment vars\n",
 		       CONFIG_VIDCONSOLE_AS_NAME);
 #endif
 
-#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
-	/* set the environment variables (will overwrite previous env settings) */
-	for (i = 0; i < MAX_FILES; i++) {
-		env_set(stdio_names[i], stdio_devices[i]->name);
+	if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
+		/* set the environment variables (will overwrite previous env settings) */
+		for (i = 0; i < MAX_FILES; i++)
+			env_set(stdio_names[i], stdio_devices[i]->name);
 	}
-#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
 
 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
 
-#if 0
-	/* If nothing usable installed, use only the initial console */
-	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
-		return 0;
-#endif
 	print_pre_console_buffer(flushpoint);
 	return 0;
 }
@@ -956,18 +1051,16 @@
 	else
 		flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
 
-#ifdef CONFIG_SPLASH_SCREEN
 	/*
 	 * suppress all output if splash screen is enabled and we have
 	 * a bmp to display. We redirect the output from frame buffer
 	 * console to serial console in this case or suppress it if
 	 * "silent" mode was requested.
 	 */
-	if (env_get("splashimage") != NULL) {
+	if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
 		if (!(gd->flags & GD_FLG_SILENT))
-			outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
+			outputdev = console_search_dev (DEV_FLAGS_OUTPUT, "serial");
 	}
-#endif
 
 	/* Scan devices looking for input and output devices */
 	list_for_each(pos, list) {
@@ -987,23 +1080,18 @@
 	if (outputdev != NULL) {
 		console_setfile(stdout, outputdev);
 		console_setfile(stderr, outputdev);
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
-		console_devices[stdout][0] = outputdev;
-		console_devices[stderr][0] = outputdev;
-#endif
+		console_devices_set(stdout, outputdev);
+		console_devices_set(stderr, outputdev);
 	}
 
 	/* Initializes input console */
 	if (inputdev != NULL) {
 		console_setfile(stdin, inputdev);
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
-		console_devices[stdin][0] = inputdev;
-#endif
+		console_devices_set(stdin, inputdev);
 	}
 
-#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
-	stdio_print_current_devices();
-#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
+	if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
+		stdio_print_current_devices();
 
 	/* Setting environment variables */
 	for (i = 0; i < MAX_FILES; i++) {
@@ -1012,11 +1100,6 @@
 
 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
 
-#if 0
-	/* If nothing usable installed, use only the initial console */
-	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
-		return 0;
-#endif
 	print_pre_console_buffer(flushpoint);
 	return 0;
 }
diff --git a/common/exports.c b/common/exports.c
index 6253b55..4578f07 100644
--- a/common/exports.c
+++ b/common/exports.c
@@ -25,8 +25,10 @@
 # define miiphy_set_current_dev		dummy
 #endif
 
-void jumptable_init(void)
+int jumptable_init(void)
 {
 	gd->jt = malloc(sizeof(struct jt_funcs));
 #include <_exports.h>
+
+	return 0;
 }
diff --git a/common/iomux.c b/common/iomux.c
index 7cfd9f2..15bf533 100644
--- a/common/iomux.c
+++ b/common/iomux.c
@@ -27,8 +27,8 @@
 {
 	char *console_args, *temp, **start;
 	int i, j, k, io_flag, cs_idx, repeat;
+	struct stdio_dev **cons_set, **old_set;
 	struct stdio_dev *dev;
-	struct stdio_dev **cons_set;
 
 	console_args = strdup(arg);
 	if (console_args == NULL)
@@ -45,15 +45,14 @@
 	i = 0;
 	temp = console_args;
 	for (;;) {
-		temp = strchr(temp, ',');
-		if (temp != NULL) {
-			i++;
-			temp++;
-			continue;
-		}
 		/* There's always one entry more than the number of commas. */
 		i++;
-		break;
+
+		temp = strchr(temp, ',');
+		if (temp == NULL)
+			break;
+
+		temp++;
 	}
 	start = (char **)malloc(i * sizeof(char *));
 	if (start == NULL) {
@@ -95,10 +94,10 @@
 	for (j = 0; j < i; j++) {
 		/*
 		 * Check whether the device exists and is valid.
-		 * console_assign() also calls search_device(),
+		 * console_assign() also calls console_search_dev(),
 		 * but I need the pointer to the device.
 		 */
-		dev = search_device(io_flag, start[j]);
+		dev = console_search_dev(io_flag, start[j]);
 		if (dev == NULL)
 			continue;
 		/*
@@ -127,21 +126,25 @@
 	if (cs_idx == 0) {
 		free(cons_set);
 		return 1;
-	} else {
-		/* Works even if console_devices[console] is NULL. */
-		console_devices[console] =
-			(struct stdio_dev **)realloc(console_devices[console],
-			cs_idx * sizeof(struct stdio_dev *));
-		if (console_devices[console] == NULL) {
-			free(cons_set);
-			return 1;
-		}
-		memcpy(console_devices[console], cons_set, cs_idx *
-			sizeof(struct stdio_dev *));
-
-		cd_count[console] = cs_idx;
 	}
-	free(cons_set);
+
+	old_set = console_devices[console];
+	repeat = cd_count[console];
+
+	console_devices[console] = cons_set;
+	cd_count[console] = cs_idx;
+
+	/* Stop dropped consoles */
+	for (i = 0; i < repeat; i++) {
+		for (j = 0; j < cs_idx; j++) {
+			if (old_set[i] == cons_set[j])
+				break;
+		}
+		if (j == cs_idx)
+			console_stop(console, old_set[i]);
+	}
+
+	free(old_set);
 	return 0;
 }
 #endif /* CONSOLE_MUX */
diff --git a/common/log.c b/common/log.c
index ce39918..767f0fe 100644
--- a/common/log.c
+++ b/common/log.c
@@ -198,9 +198,10 @@
  * @rec:	log record to dispatch
  * Return:	0 msg sent, 1 msg not sent while already dispatching another msg
  */
-static int log_dispatch(struct log_rec *rec)
+static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args)
 {
 	struct log_device *ldev;
+	char buf[CONFIG_SYS_CBSIZE];
 
 	/*
 	 * When a log driver writes messages (e.g. via the network stack) this
@@ -214,8 +215,13 @@
 	gd->processing_msg = true;
 	list_for_each_entry(ldev, &gd->log_head, sibling_node) {
 		if ((ldev->flags & LOGDF_ENABLE) &&
-		    log_passes_filters(ldev, rec))
+		    log_passes_filters(ldev, rec)) {
+			if (!rec->msg) {
+				vsnprintf(buf, sizeof(buf), fmt, args);
+				rec->msg = buf;
+			}
 			ldev->drv->emit(ldev, rec);
+		}
 	}
 	gd->processing_msg = false;
 	return 0;
@@ -224,10 +230,12 @@
 int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 	 int line, const char *func, const char *fmt, ...)
 {
-	char buf[CONFIG_SYS_CBSIZE];
 	struct log_rec rec;
 	va_list args;
 
+	if (!gd)
+		return -ENOSYS;
+
 	/* Check for message continuation */
 	if (cat == LOGC_CONT)
 		cat = gd->logc_prev;
@@ -240,19 +248,29 @@
 	rec.file = file;
 	rec.line = line;
 	rec.func = func;
-	va_start(args, fmt);
-	vsnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
-	rec.msg = buf;
-	if (!gd || !(gd->flags & GD_FLG_LOG_READY)) {
-		if (gd)
-			gd->log_drop_count++;
+	rec.msg = NULL;
+
+	if (!(gd->flags & GD_FLG_LOG_READY)) {
+		gd->log_drop_count++;
+
+		/* display dropped traces with console puts and DEBUG_UART */
+		if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) {
+			char buf[CONFIG_SYS_CBSIZE];
+
+			va_start(args, fmt);
+			vsnprintf(buf, sizeof(buf), fmt, args);
+			puts(buf);
+			va_end(args);
+		}
+
 		return -ENOSYS;
 	}
-	if (!log_dispatch(&rec)) {
+	va_start(args, fmt);
+	if (!log_dispatch(&rec, fmt, args)) {
 		gd->logc_prev = cat;
 		gd->logl_prev = level;
 	}
+	va_end(args);
 
 	return 0;
 }
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6b01867..7561335 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -126,7 +126,7 @@
 
 config HANDOFF
 	bool "Pass hand-off information from SPL to U-Boot proper"
-	depends on BLOBLIST
+	depends on SPL && BLOBLIST
 	help
 	  It is useful to be able to pass information from SPL to U-Boot
 	  proper to preserve state that is known in SPL and is needed in U-Boot.
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 795e292..a6ad094 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -684,8 +684,11 @@
 
 		ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 					 &image_info);
-		if (ret < 0)
-			continue;
+		if (ret < 0) {
+			printf("%s: can't load image loadables index %d (ret = %d)\n",
+			       __func__, index, ret);
+			return ret;
+		}
 
 		if (!spl_fit_image_get_os(fit, node, &os_type))
 			debug("Loadable is %s\n", genimg_get_os_name(os_type));
diff --git a/common/stdio.c b/common/stdio.c
index a15f308..abf9b1e 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -181,7 +181,7 @@
 		 * 'stdout', which may include a list of devices separate by
 		 * commas. Obviously this is not going to work, so we ignore
 		 * that case. The call path in that case is
-		 * console_init_r() -> search_device() -> stdio_get_by_name()
+		 * console_init_r() -> console_search_dev() -> stdio_get_by_name()
 		 */
 		if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
 		    !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
@@ -332,7 +332,7 @@
 		/*
 		 * If the console setting is not in environment variables then
 		 * console_init_r() will not be calling iomux_doenv() (which
-		 * calls search_device()). So we will not dynamically add
+		 * calls console_search_dev()). So we will not dynamically add
 		 * devices by calling stdio_probe_device().
 		 *
 		 * So just probe all video devices now so that whichever one is
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 04f5310..f431925 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -18,6 +18,8 @@
 #include <command.h>
 #include <ide.h>
 #include <memalign.h>
+#include <asm/unaligned.h>
+#include <linux/compiler.h>
 #include "part_dos.h"
 #include <part.h>
 
@@ -29,22 +31,11 @@
  * to use large numbers of partitions */
 #define MAX_EXT_PARTS 256
 
-/* Convert char[4] in little endian format to the host format integer
- */
-static inline unsigned int le32_to_int(unsigned char *le32)
-{
-    return ((le32[3] << 24) +
-	    (le32[2] << 16) +
-	    (le32[1] << 8) +
-	     le32[0]
-	   );
-}
-
 static inline int is_extended(int part_type)
 {
-    return (part_type == 0x5 ||
-	    part_type == 0xf ||
-	    part_type == 0x85);
+    return (part_type == DOS_PART_TYPE_EXTENDED ||
+	    part_type == DOS_PART_TYPE_EXTENDED_LBA ||
+	    part_type == DOS_PART_TYPE_EXTENDED_LINUX);
 }
 
 static int get_bootable(dos_partition_t *p)
@@ -61,8 +52,8 @@
 static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector,
 			   int part_num, unsigned int disksig)
 {
-	lbaint_t lba_start = ext_part_sector + le32_to_int (p->start4);
-	lbaint_t lba_size  = le32_to_int (p->size4);
+	lbaint_t lba_start = ext_part_sector + get_unaligned_le32(p->start4);
+	lbaint_t lba_size  = get_unaligned_le32(p->size4);
 
 	printf("%3d\t%-10" LBAFlength "u\t%-10" LBAFlength
 		"u\t%08x-%02x\t%02x%s%s\n",
@@ -171,7 +162,7 @@
 	}
 
 	if (!ext_part_sector)
-		disksig = le32_to_int(&buffer[DOS_PART_DISKSIG_OFFSET]);
+		disksig = get_unaligned_le32(&buffer[DOS_PART_DISKSIG_OFFSET]);
 
 	/* Print all primary/logical partitions */
 	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
@@ -198,7 +189,7 @@
 	for (i = 0; i < 4; i++, pt++) {
 		if (is_extended (pt->sys_ind)) {
 			lbaint_t lba_start
-				= le32_to_int (pt->start4) + relative;
+				= get_unaligned_le32 (pt->start4) + relative;
 
 			print_partition_extended(dev_desc, lba_start,
 				ext_part_sector == 0  ? lba_start : relative,
@@ -244,7 +235,7 @@
 
 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
 	if (!ext_part_sector)
-		disksig = le32_to_int(&buffer[DOS_PART_DISKSIG_OFFSET]);
+		disksig = get_unaligned_le32(&buffer[DOS_PART_DISKSIG_OFFSET]);
 #endif
 
 	/* Print all primary/logical partitions */
@@ -260,8 +251,8 @@
 		    (ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) {
 			info->blksz = DOS_PART_DEFAULT_SECTOR;
 			info->start = (lbaint_t)(ext_part_sector +
-					le32_to_int(pt->start4));
-			info->size  = (lbaint_t)le32_to_int(pt->size4);
+					get_unaligned_le32(pt->start4));
+			info->size  = (lbaint_t)get_unaligned_le32(pt->size4);
 			part_set_generic_name(dev_desc, part_num,
 					      (char *)info->name);
 			/* sprintf(info->type, "%d, pt->sys_ind); */
@@ -286,7 +277,7 @@
 	for (i = 0; i < 4; i++, pt++) {
 		if (is_extended (pt->sys_ind)) {
 			lbaint_t lba_start
-				= le32_to_int (pt->start4) + relative;
+				= get_unaligned_le32 (pt->start4) + relative;
 
 			return part_get_info_extended(dev_desc, lba_start,
 				 ext_part_sector == 0 ? lba_start : relative,
@@ -312,13 +303,13 @@
 	return -1;
 }
 
-void part_print_dos(struct blk_desc *dev_desc)
+static void __maybe_unused part_print_dos(struct blk_desc *dev_desc)
 {
 	printf("Part\tStart Sector\tNum Sectors\tUUID\t\tType\n");
 	print_partition_extended(dev_desc, 0, 0, 1, 0);
 }
 
-int part_get_info_dos(struct blk_desc *dev_desc, int part,
+static int __maybe_unused part_get_info_dos(struct blk_desc *dev_desc, int part,
 		      struct disk_partition *info)
 {
 	return part_get_info_extended(dev_desc, 0, 0, 1, part, info, 0);
@@ -329,7 +320,174 @@
 	return test_block_type(buf) == DOS_MBR ? 0 : -1;
 }
 
-int write_mbr_partition(struct blk_desc *dev_desc, void *buf)
+#if CONFIG_IS_ENABLED(CMD_MBR)
+static void lba_to_chs(lbaint_t lba, unsigned char *rc, unsigned char *rh,
+		       unsigned char *rs)
+{
+	unsigned int c, h, s;
+	/* use fixed CHS geometry */
+	unsigned int sectpertrack = 63;
+	unsigned int heads = 255;
+
+	c = (lba + 1) / sectpertrack / heads;
+	h = (lba + 1) / sectpertrack - c * heads;
+	s = (lba + 1) - (c * heads + h) * sectpertrack;
+
+	if (c > 1023) {
+		c = 1023;
+		h = 254;
+		s = 63;
+	}
+
+	*rc = c & 0xff;
+	*rh = h;
+	*rs = s + ((c & 0x300) >> 2);
+}
+
+static void mbr_fill_pt_entry(dos_partition_t *pt, lbaint_t start,
+		lbaint_t relative, lbaint_t size, uchar sys_ind, bool bootable)
+{
+	pt->boot_ind = bootable ? 0x80 : 0x00;
+	pt->sys_ind = sys_ind;
+	lba_to_chs(start, &pt->cyl, &pt->head, &pt->sector);
+	lba_to_chs(start + size - 1, &pt->end_cyl, &pt->end_head, &pt->end_sector);
+	put_unaligned_le32(relative, &pt->start4);
+	put_unaligned_le32(size, &pt->size4);
+}
+
+int write_mbr_partitions(struct blk_desc *dev,
+		struct disk_partition *p, int count, unsigned int disksig)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev->blksz);
+	lbaint_t ext_part_start = 0, ext_part_size = 0, ext_part_sect = 0;
+	dos_partition_t *pt;
+	int i;
+
+	memset(buffer, 0, dev->blksz);
+	buffer[DOS_PART_MAGIC_OFFSET] = 0x55;
+	buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa;
+	put_unaligned_le32(disksig, &buffer[DOS_PART_DISKSIG_OFFSET]);
+	pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+
+	/* create all primary partitions */
+	for (i = 0; i < 4 && i < count; i++, pt++) {
+		mbr_fill_pt_entry(pt, p[i].start, p[i].start, p[i].size,
+				  p[i].sys_ind, p[i].bootable);
+		if (is_extended(p[i].sys_ind)) {
+			ext_part_start = p[i].start;
+			ext_part_size = p[i].size;
+			ext_part_sect = p[i].start;
+		}
+	}
+
+	if (i < count && !ext_part_start) {
+		printf("%s: extended partition is needed for more than 4 partitions\n",
+		        __func__);
+		return -1;
+	}
+
+	/* write MBR */
+	if (blk_dwrite(dev, 0, 1, buffer) != 1) {
+		printf("%s: failed writing 'MBR' (1 blks at 0x0)\n",
+		       __func__);
+		return -1;
+	}
+
+	/* create extended volumes */
+	for (; i < count; i++) {
+		lbaint_t next_ebr = 0;
+
+		memset(buffer, 0, dev->blksz);
+		buffer[DOS_PART_MAGIC_OFFSET] = 0x55;
+		buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa;
+		pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+
+		mbr_fill_pt_entry(pt, p[i].start, p[i].start - ext_part_sect,
+				  p[i].size, p[i].sys_ind, p[i].bootable);
+
+		if (i + 1 < count) {
+			pt++;
+			next_ebr = p[i].start + p[i].size;
+			mbr_fill_pt_entry(pt, next_ebr,
+					  next_ebr - ext_part_start,
+					  p[i+1].start + p[i+1].size - next_ebr,
+					  DOS_PART_TYPE_EXTENDED, 0);
+		}
+
+		/* write EBR */
+		if (blk_dwrite(dev, ext_part_sect, 1, buffer) != 1) {
+			printf("%s: failed writing 'EBR' (1 blks at 0x%lx)\n",
+			       __func__, ext_part_sect);
+			return -1;
+		}
+		ext_part_sect = next_ebr;
+	}
+
+	return 0;
+}
+
+int layout_mbr_partitions(struct disk_partition *p, int count,
+			  lbaint_t total_sectors)
+{
+	struct disk_partition *ext = NULL;
+	int i, j;
+	lbaint_t ext_vol_start;
+
+	/* calculate primary partitions start and size if needed */
+	if (!p[0].start)
+		p[0].start = DOS_PART_DEFAULT_GAP;
+	for (i = 0; i < 4 && i < count; i++) {
+		if (!p[i].start)
+			p[i].start = p[i - 1].start + p[i - 1].size;
+		if (!p[i].size) {
+			lbaint_t end = total_sectors;
+			lbaint_t allocated = 0;
+
+			for (j = i + 1; j < 4 && j < count; j++) {
+				if (p[j].start) {
+					end = p[j].start;
+					break;
+				}
+				allocated += p[j].size;
+			}
+			p[i].size = end - allocated - p[i].start;
+		}
+		if (p[i].sys_ind == 0x05)
+			ext = &p[i];
+	}
+
+	if (i >= 4 && !ext) {
+		printf("%s: extended partition is needed for more than 4 partitions\n",
+		        __func__);
+		return -1;
+	}
+
+	/* calculate extended volumes start and size if needed */
+	ext_vol_start = ext->start;
+	for (i = 4; i < count; i++) {
+		if (!p[i].start)
+			p[i].start = ext_vol_start + DOS_PART_DEFAULT_GAP;
+		if (!p[i].size) {
+			lbaint_t end = ext->start + ext->size;
+			lbaint_t allocated = 0;
+
+			for (j = i + 1; j < count; j++) {
+				if (p[j].start) {
+					end = p[j].start - DOS_PART_DEFAULT_GAP;
+					break;
+				}
+				allocated += p[j].size + DOS_PART_DEFAULT_GAP;
+			}
+			p[i].size = end - allocated - p[i].start;
+		}
+		ext_vol_start = p[i].start + p[i].size;
+	}
+
+	return 0;
+}
+#endif
+
+int write_mbr_sector(struct blk_desc *dev_desc, void *buf)
 {
 	if (is_valid_dos_buf(buf))
 		return -1;
diff --git a/disk/part_dos.h b/disk/part_dos.h
index 434b021..5055822 100644
--- a/disk/part_dos.h
+++ b/disk/part_dos.h
@@ -15,6 +15,11 @@
 #define DOS_PBR_MEDIA_TYPE_OFFSET	0x15
 #define DOS_MBR	0
 #define DOS_PBR	1
+#define DOS_PART_TYPE_EXTENDED		0x05
+#define DOS_PART_TYPE_EXTENDED_LBA	0x0F
+#define DOS_PART_TYPE_EXTENDED_LINUX	0x85
+
+#define DOS_PART_DEFAULT_GAP		2048
 
 typedef struct dos_partition {
 	unsigned char boot_ind;		/* 0x80 - active			*/
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 60b1c1d7..2f92266 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -247,10 +247,11 @@
 		uuid_bin = (unsigned char *)gpt_pte[i].partition_type_guid.b;
 		uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
 		printf("\ttype:\t%s\n", uuid);
-#ifdef CONFIG_PARTITION_TYPE_GUID
-		if (!uuid_guid_get_str(uuid_bin, uuid))
-			printf("\ttype:\t%s\n", uuid);
-#endif
+		if (CONFIG_IS_ENABLED(PARTITION_TYPE_GUID)) {
+			const char *type = uuid_guid_get_str(uuid_bin);
+			if (type)
+				printf("\ttype:\t%s\n", type);
+		}
 		uuid_bin = (unsigned char *)gpt_pte[i].unique_partition_guid.b;
 		uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
 		printf("\tguid:\t%s\n", uuid);
diff --git a/doc/README.gpt b/doc/README.gpt
index facd7af..ac975f6 100644
--- a/doc/README.gpt
+++ b/doc/README.gpt
@@ -251,22 +251,24 @@
 	type=0FC63DAF-8483-4772-8E79-3D69D8477DE4;"
 
 Some strings can be also used at the place of known GUID :
-	"system" = PARTITION_SYSTEM_GUID
-	           (C12A7328-F81F-11D2-BA4B-00A0C93EC93B)
-	"mbr"    = LEGACY_MBR_PARTITION_GUID
-	           (024DEE41-33E7-11D3-9D69-0008C781F39F)
-	"msft"   = PARTITION_MSFT_RESERVED_GUID
-	           (E3C9E316-0B5C-4DB8-817D-F92DF00215AE)
-	"data"   = PARTITION_BASIC_DATA_GUID
-	            (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7)
-	"linux"  = PARTITION_LINUX_FILE_SYSTEM_DATA_GUID
-	           (0FC63DAF-8483-4772-8E79-3D69D8477DE4)
-	"raid"   = PARTITION_LINUX_RAID_GUID
-	           (A19D880F-05FC-4D3B-A006-743F0F84911E)
-	"swap"   = PARTITION_LINUX_SWAP_GUID
-	           (0657FD6D-A4AB-43C4-84E5-0933C84B4F4F)
-	"lvm"    = PARTITION_LINUX_LVM_GUID
-	           (E6D6D379-F507-44C2-A23C-238F2A3DF928)
+	"system"          = PARTITION_SYSTEM_GUID
+	                    (C12A7328-F81F-11D2-BA4B-00A0C93EC93B)
+	"mbr"             = LEGACY_MBR_PARTITION_GUID
+	                    (024DEE41-33E7-11D3-9D69-0008C781F39F)
+	"msft"            = PARTITION_MSFT_RESERVED_GUID
+	                    (E3C9E316-0B5C-4DB8-817D-F92DF00215AE)
+	"data"            = PARTITION_BASIC_DATA_GUID
+	                     (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7)
+	"linux"           = PARTITION_LINUX_FILE_SYSTEM_DATA_GUID
+	                    (0FC63DAF-8483-4772-8E79-3D69D8477DE4)
+	"raid"            = PARTITION_LINUX_RAID_GUID
+	                    (A19D880F-05FC-4D3B-A006-743F0F84911E)
+	"swap"            = PARTITION_LINUX_SWAP_GUID
+	                    (0657FD6D-A4AB-43C4-84E5-0933C84B4F4F)
+	"lvm"             = PARTITION_LINUX_LVM_GUID
+	                    (E6D6D379-F507-44C2-A23C-238F2A3DF928)
+	"u-boot-env"      = PARTITION_U_BOOT_ENVIRONMENT
+	                    (3DE21764-95BD-54BD-A5C3-4ABE786F38A8)
 
     "uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
 	name=kernel,size=60MiB,uuid=...,type=linux;"
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index ada0df0..6def250 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -17,4 +17,5 @@
    bootefi
    bootmenu
    button
+   mbr
    pstore
diff --git a/doc/usage/mbr.rst b/doc/usage/mbr.rst
new file mode 100644
index 0000000..bddf2f6
--- /dev/null
+++ b/doc/usage/mbr.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+mbr command
+===========
+
+Synopsis
+--------
+
+::
+
+    mbr verify [interface] [device no] [partition list]
+    mbr write [interface] [device no] [partition list]
+
+Description
+-----------
+
+The mbr command lets users create or verify the MBR (Master Boot Record)
+partition layout based on the provided text description. The partition
+layout is alternatively read from the 'mbr_parts' environment variable.
+This can be used in scripts to help system image flashing tools to ensure
+proper partition layout.
+
+The syntax of the text description of the partition list is similar to
+the one used by the 'gpt' command.
+
+Supported partition parameters are:
+
+* name (currently ignored)
+* start (partition start offset in bytes)
+* size (in bytes or '-' to expand it to the whole free area)
+* bootable (boolean flag)
+* id (MBR partition type)
+
+If one wants to create more than 4 partitions, an 'Extended' primary
+partition (with 0x05 ID) has to be explicitly provided as a one of the
+first 4 entries.
+
+Here is an example how to create a 6 partitions (3 on the 'extended
+volume'), some of the predefined sizes:
+
+::
+
+    => setenv mbr_parts 'name=boot,start=4M,size=128M,bootable,id=0x0e;
+        name=rootfs,size=3072M,id=0x83;
+        name=system-data,size=512M,id=0x83;
+        name=[ext],size=-,id=0x05;
+        name=user,size=-,id=0x83;
+        name=modules,size=100M,id=0x83;
+        name=ramdisk,size=8M,id=0x83'
+    => mbr write mmc 0
+
+To check if the layout on the MMC #0 storage device matches the provided
+text description one has to issue following command (assuming that
+mbr_parts environment variable is set):
+
+::
+
+    => mbr verify mmc 0
+
+The verify sub-command is especially useful in the system update scripts:
+
+::
+
+    => if mbr verify mmc 0; then
+         echo MBR layout needs to be updated
+         ...
+       fi
+
+The 'mbr write' command returns 0 on success write or 1 on failure.
+
+The 'mbr verify' returns 0 if the layout matches the one on the storage
+device or 1 if not.
+
+Configuration
+-------------
+
+To use the mbr command you must specify CONFIG_CMD_MBR=y.
+
+Return value
+------------
+
+The variable *$?* takes the following values
+
++---+------------------------------+
+| 0 | mbr write was succesful      |
++---+------------------------------+
+| 1 | mbr write failed             |
++---+------------------------------+
+| 0 | mbr verify was succesful     |
++---+------------------------------+
+| 1 | mbr verify was not succesful |
++---+------------------------------+
+|-1 | invalid arguments            |
++---+------------------------------+
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index cdb975d..f38122d 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -757,6 +757,25 @@
 }
 #endif
 
+int uclass_probe_all(enum uclass_id id)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device(id, &dev);
+	if (ret || !dev)
+		return ret;
+
+	/* Scanning uclass to probe all devices */
+	while (dev) {
+		ret = uclass_next_device(&dev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 UCLASS_DRIVER(nop) = {
 	.id		= UCLASS_NOP,
 	.name		= "nop",
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index ae8e8e5..4e26cef 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -508,7 +508,7 @@
 			fastboot_fail("invalid MBR partition", response);
 			return;
 		}
-		if (write_mbr_partition(dev_desc, download_buffer)) {
+		if (write_mbr_sector(dev_desc, download_buffer)) {
 			printf("%s: writing MBR partition failed\n", __func__);
 			fastboot_fail("writing MBR partition failed",
 				      response);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1a4dec3..0d1f94c 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -9,8 +9,6 @@
  */
 
 #ifndef __UBOOT__
-#include <log.h>
-#include <dm/devres.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c
index ba97a54..59a32c4 100644
--- a/drivers/net/phy/miiphybb.c
+++ b/drivers/net/phy/miiphybb.c
@@ -105,7 +105,7 @@
 			  sizeof(bb_miiphy_buses[0]);
 #endif
 
-void bb_miiphy_init(void)
+int bb_miiphy_init(void)
 {
 	int i;
 
@@ -124,6 +124,8 @@
 			bb_miiphy_buses[i].init(&bb_miiphy_buses[i]);
 		}
 	}
+
+	return 0;
 }
 
 static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 4cdd06b..ba65f47 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1842,7 +1842,7 @@
 	.of_match	= pci_generic_ids,
 };
 
-void pci_init(void)
+int pci_init(void)
 {
 	struct udevice *bus;
 
@@ -1855,4 +1855,6 @@
 	     uclass_next_device_check(&bus)) {
 		;
 	}
+
+	return 0;
 }
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 664e837..a7453e5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -454,16 +454,18 @@
 	return pci_hose_scan_bus(hose, hose->current_busno);
 }
 
-void pci_init(void)
+int pci_init(void)
 {
 	hose_head = NULL;
 
 	/* allow env to disable pci init/enum */
 	if (env_get("pcidisable") != NULL)
-		return;
+		return 0;
 
 	/* now call board specific pci_init()... */
 	pci_init_board();
+
+	return 0;
 }
 
 /* Returns the address of the requested capability structure within the
diff --git a/drivers/pci_endpoint/pci_ep-uclass.c b/drivers/pci_endpoint/pci_ep-uclass.c
index 38a5f08..aa89701 100644
--- a/drivers/pci_endpoint/pci_ep-uclass.c
+++ b/drivers/pci_endpoint/pci_ep-uclass.c
@@ -210,7 +210,7 @@
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 
-void pci_ep_init(void)
+int pci_ep_init(void)
 {
 	struct udevice *dev;
 
@@ -219,4 +219,6 @@
 	     uclass_next_device_check(&dev)) {
 		;
 	}
+
+	return 0;
 }
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index d431102..fbbea18 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -18,7 +18,7 @@
 
 config SPL_DM_REGULATOR
 	bool "Enable regulators for SPL"
-	depends on DM_REGULATOR
+	depends on DM_REGULATOR && SPL_POWER_SUPPORT
 	---help---
 	Regulators are seldom needed in SPL. Even if they are accessed, some
 	code space can be saved by accessing the PMIC registers directly.
diff --git a/drivers/ram/k3-j721e/lpddr4.c b/drivers/ram/k3-j721e/lpddr4.c
index fc80fb1..68043d7 100644
--- a/drivers/ram/k3-j721e/lpddr4.c
+++ b/drivers/ram/k3-j721e/lpddr4.c
@@ -719,7 +719,7 @@
 
 		/* MISRA compliance (Shifting operation) check */
 		if (fieldshift < WORD_SHIFT) {
-			if (((ctlirqstatus >> fieldshift) & BIT_MASK) > 0U) {
+			if ((ctlirqstatus >> fieldshift) & LPDDR4_BIT_MASK) {
 				*irqstatus = true;
 			} else {
 				*irqstatus = false;
@@ -746,11 +746,11 @@
 		if (localinterrupt > WORD_SHIFT) {
 			localinterrupt =
 			    (localinterrupt - (uint32_t) WORD_SHIFT);
-			regval = ((uint32_t) BIT_MASK << localinterrupt);
+			regval = (uint32_t)LPDDR4_BIT_MASK << localinterrupt;
 			CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_1__REG),
 				      regval);
 		} else {
-			regval = ((uint32_t) BIT_MASK << localinterrupt);
+			regval = (uint32_t)LPDDR4_BIT_MASK << localinterrupt;
 			CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_0__REG),
 				      regval);
 		}
@@ -823,7 +823,7 @@
 		phyindepirqstatus =
 		    CPS_REG_READ(&(ctlregbase->LPDDR4__PI_INT_STATUS__REG));
 		*irqstatus =
-		    (((phyindepirqstatus >> (uint32_t) intr) & BIT_MASK) > 0U);
+		    !!((phyindepirqstatus >> (uint32_t)intr) & LPDDR4_BIT_MASK);
 	}
 	return result;
 }
@@ -841,7 +841,7 @@
 		lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase;
 
 		/* Write 1 to the requested bit to ACk the interrupt */
-		regval = ((uint32_t) BIT_MASK << ui32shiftinterrupt);
+		regval = (uint32_t)LPDDR4_BIT_MASK << ui32shiftinterrupt;
 		CPS_REG_WRITE(&(ctlregbase->LPDDR4__PI_INT_ACK__REG), regval);
 	}
 
@@ -894,7 +894,7 @@
 	    (volatile uint32_t
 	     *)(&(ctlregbase->LPDDR4__PHY_WRLVL_ERROR_OBS_0__REG));
 	/* PHY_WRLVL_ERROR_OBS_X[1:0] should be zero */
-	errbitmask = (BIT_MASK << 1) | (BIT_MASK);
+	errbitmask = (LPDDR4_BIT_MASK << 1) | LPDDR4_BIT_MASK;
 	for (snum = 0U; snum < DSLICE_NUM; snum++) {
 		regval = CPS_REG_READ(regaddress);
 		if ((regval & errbitmask) != 0U) {
@@ -1054,7 +1054,7 @@
 			     lpddr4_debuginfo * debuginfo, bool * errfoundptr)
 {
 
-	uint32_t errbitmask = (BIT_MASK << 0x1U) | (BIT_MASK);
+	uint32_t errbitmask = (LPDDR4_BIT_MASK << 0x1U) | LPDDR4_BIT_MASK;
 	/* Check PLL observation registers for PLL lock errors */
 
 	debuginfo->pllerror =
diff --git a/drivers/ram/k3-j721e/lpddr4_private.h b/drivers/ram/k3-j721e/lpddr4_private.h
index 42c9234..3d5017e 100644
--- a/drivers/ram/k3-j721e/lpddr4_private.h
+++ b/drivers/ram/k3-j721e/lpddr4_private.h
@@ -14,9 +14,9 @@
 #define VERSION_0  (0x54d5da40U)
 #define VERSION_1  (0xc1865a1U)
 
-#define BIT_MASK    (0x1U)
-#define BYTE_MASK   (0xffU)
-#define NIBBLE_MASK (0xfU)
+#define LPDDR4_BIT_MASK	(0x1U)
+#define BYTE_MASK	(0xffU)
+#define NIBBLE_MASK	(0xfU)
 
 #define WORD_SHIFT (32U)
 #define WORD_MASK (0xffffffffU)
@@ -46,11 +46,15 @@
 #define IO_CALIB_DONE ((uint32_t)0x1U << 23U)
 #define IO_CALIB_FIELD ((uint32_t)NIBBLE_MASK << 28U)
 #define IO_CALIB_STATE ((uint32_t)0xBU << 28U)
-#define RX_CAL_DONE ((uint32_t)BIT_MASK << 4U)
-#define CA_TRAIN_RL (((uint32_t)BIT_MASK << 5U) | ((uint32_t)BIT_MASK << 4U))
+#define RX_CAL_DONE ((uint32_t)LPDDR4_BIT_MASK << 4U)
+#define CA_TRAIN_RL (((uint32_t)LPDDR4_BIT_MASK << 5U) | \
+		     ((uint32_t)LPDDR4_BIT_MASK << 4U))
 #define WR_LVL_STATE (((uint32_t)NIBBLE_MASK) << 13U)
-#define GATE_LVL_ERROR_FIELDS (((uint32_t)BIT_MASK << 7U) | ((uint32_t)BIT_MASK << 6U))
-#define READ_LVL_ERROR_FIELDS ((((uint32_t)NIBBLE_MASK) << 28U) | (((uint32_t)BYTE_MASK) << 16U))
-#define DQ_LVL_STATUS (((uint32_t)BIT_MASK << 26U) | (((uint32_t)BYTE_MASK) << 18U))
+#define GATE_LVL_ERROR_FIELDS (((uint32_t)LPDDR4_BIT_MASK << 7U) | \
+			       ((uint32_t)LPDDR4_BIT_MASK << 6U))
+#define READ_LVL_ERROR_FIELDS ((((uint32_t)NIBBLE_MASK) << 28U) | \
+			       (((uint32_t)BYTE_MASK) << 16U))
+#define DQ_LVL_STATUS (((uint32_t)LPDDR4_BIT_MASK << 26U) | \
+		       (((uint32_t)BYTE_MASK) << 18U))
 
 #endif  /* LPDDR4_PRIV_H */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b4805a2..1294943 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -134,6 +134,22 @@
 
 	  If unsure, say N.
 
+config SERIAL_PROBE_ALL
+	bool "Probe all available serial devices"
+	depends on DM_SERIAL
+	default n
+	help
+	  The serial subsystem only probes for a single serial device,
+	  but does not probe for other remaining serial devices.
+	  With this option set, we make probing and searching for
+	  all available devices optional.
+	  Normally, U-Boot talks to one serial port at a time, but SBSA
+	  compliant UART devices like PL011 require initialization
+	  by firmware and to let the kernel use serial port for sending
+	  and receiving the characters.
+
+	  If unsure, say N.
+
 config SPL_DM_SERIAL
 	bool "Enable Driver Model for serial drivers in SPL"
 	depends on DM_SERIAL && SPL_DM
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 58a6541..ead0193 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -172,6 +172,15 @@
 /* Called after relocation */
 int serial_initialize(void)
 {
+	/* Scanning uclass to probe devices */
+	if (IS_ENABLED(CONFIG_SERIAL_PROBE_ALL)) {
+		int ret;
+
+		ret  = uclass_probe_all(UCLASS_SERIAL);
+		if (ret)
+			return ret;
+	}
+
 	return serial_init();
 }
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d39d9b2..d782eb8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -199,7 +199,7 @@
 
 config SIMPLE_PANEL
 	bool "Enable simple panel support"
-	depends on PANEL
+	depends on PANEL && BACKLIGHT
 	default y
 	help
 	  This turns on a simple panel driver that enables a compatible
diff --git a/drivers/xen/hypervisor.c b/drivers/xen/hypervisor.c
index 178c206..2560894 100644
--- a/drivers/xen/hypervisor.c
+++ b/drivers/xen/hypervisor.c
@@ -232,7 +232,7 @@
 	synch_clear_bit(port, &s->evtchn_pending[0]);
 }
 
-void xen_init(void)
+int xen_init(void)
 {
 	debug("%s\n", __func__);
 
@@ -240,6 +240,8 @@
 	init_events();
 	init_xenbus();
 	init_gnttab();
+
+	return 0;
 }
 
 void xen_fini(void)
diff --git a/dts/Makefile b/dts/Makefile
index 94967cf..cb31113 100644
--- a/dts/Makefile
+++ b/dts/Makefile
@@ -33,7 +33,7 @@
 $(DTB): arch-dtbs
 	$(Q)test -e $@ || (						\
 	echo >&2;							\
-	echo >&2 "Device Tree Source is not correctly specified.";	\
+	echo >&2 "Device Tree Source ($@) is not correctly specified.";	\
 	echo >&2 "Please define 'CONFIG_DEFAULT_DEVICE_TREE'";		\
 	echo >&2 "or build with 'DEVICE_TREE=<device_tree>' argument";	\
 	echo >&2;							\
diff --git a/include/api.h b/include/api.h
index 84d81dc..83412a7 100644
--- a/include/api.h
+++ b/include/api.h
@@ -7,6 +7,14 @@
 #ifndef __API_H
 #define __API_H
 
-void api_init(void);
+/**
+ * api_init() - Initialize API for external applications
+ *
+ * Initialize API for external (standalone) applications running on top of
+ * U-Boot. It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int api_init(void);
 
 #endif
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index efa09a1..19f7039 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -412,12 +412,12 @@
 	 * @new_bloblist: relocated blob list information
 	 */
 	struct bloblist_hdr *new_bloblist;
-# ifdef CONFIG_SPL
+#endif
+#if CONFIG_IS_ENABLED(HANDOFF)
 	/**
 	 * @spl_handoff: SPL hand-off information
 	 */
 	struct spl_handoff *spl_handoff;
-# endif
 #endif
 #if defined(CONFIG_TRANSLATION_OFFSET)
 	/**
diff --git a/include/console.h b/include/console.h
index 432f892..7e628c0 100644
--- a/include/console.h
+++ b/include/console.h
@@ -8,6 +8,7 @@
 #define __CONSOLE_H
 
 #include <stdbool.h>
+#include <stdio_dev.h>
 #include <linux/errno.h>
 
 extern char console_buffer[];
@@ -15,6 +16,8 @@
 /* common/console.c */
 int console_init_f(void);	/* Before relocation; uses the serial  stuff */
 int console_init_r(void);	/* After  relocation; uses the console stuff */
+int console_start(int file, struct stdio_dev *sdev);	/* Start a console device */
+void console_stop(int file, struct stdio_dev *sdev);	/* Stop a console device */
 int console_assign(int file, const char *devname);	/* Assign the console */
 int ctrlc(void);
 int had_ctrlc(void);	/* have we had a Control-C since last clear? */
@@ -22,6 +25,18 @@
 int disable_ctrlc(int);	/* 1 to disable, 0 to enable Control-C detect */
 int confirm_yesno(void);        /*  1 if input is "y", "Y", "yes" or "YES" */
 
+/**
+ * console_search_dev() - search for stdio device with given flags and name
+ * @flags: device flags as per input/output/system
+ * @name: device name
+ *
+ * Iterates over registered STDIO devices and match them with given @flags
+ * and @name.
+ *
+ * @return pointer to the &struct stdio_dev if found, or NULL otherwise
+ */
+struct stdio_dev *console_search_dev(int flags, const char *name);
+
 #ifdef CONFIG_CONSOLE_RECORD
 /**
  * console_record_init() - set up the console recording buffers
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index b5f066d..d956837 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -377,6 +377,17 @@
 				struct udevice **devp);
 
 /**
+ * uclass_probe_all() - Probe all devices based on an uclass ID
+ *
+ * This function probes all devices associated with a uclass by
+ * looking for its ID.
+ *
+ * @id: uclass ID to look up
+ * @return 0 if OK, other -ve on error
+ */
+int uclass_probe_all(enum uclass_id id);
+
+/**
  * uclass_id_foreach_dev() - Helper function to iteration through devices
  *
  * This creates a for() loop which works through the available devices in
diff --git a/include/exports.h b/include/exports.h
index b300554..faf0f59 100644
--- a/include/exports.h
+++ b/include/exports.h
@@ -15,8 +15,14 @@
 struct cmd_tbl;
 struct spi_slave;
 
-/* Set up the jump table for use by the API */
-void jumptable_init(void);
+/**
+ * jumptable_init() - Set up the jump table for use by the API
+ *
+ * It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int jumptable_init(void);
 
 /* These are declarations of exported functions available in C code */
 unsigned long get_version(void);
diff --git a/include/init.h b/include/init.h
index 0f48ccb..980be27 100644
--- a/include/init.h
+++ b/include/init.h
@@ -164,6 +164,41 @@
 int setup_bdinfo(void);
 
 /**
+ * cpu_secondary_init_r() - CPU-specific secondary initialization
+ *
+ * After non-volatile devices, environment and cpu code are setup, have
+ * another round to deal with any initialization that might require
+ * full access to the environment or loading of some image (firmware)
+ * from a non-volatile device.
+ *
+ * It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int cpu_secondary_init_r(void);
+
+/**
+ * pci_ep_init() - Initialize pci endpoint devices
+ *
+ * It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int pci_ep_init(void);
+
+/**
+ * pci_init() - Enumerate pci devices
+ *
+ * It is called during the generic post-relocation init sequence to enumerate
+ * pci buses. This is needed, for instance, in the case of DM PCI-based
+ * Ethernet devices, which will not be detected without having the enumeration
+ * performed earlier.
+ *
+ * Return: 0 if OK
+ */
+int pci_init(void);
+
+/**
  * init_cache_f_r() - Turn on the cache in preparation for relocation
  *
  * Return: 0 if OK, -ve on error
@@ -234,8 +269,6 @@
 int set_cpu_clk_info(void);
 int update_flash_size(int flash_size);
 int arch_early_init_r(void);
-void pci_init(void);
-void pci_ep_init(void);
 int misc_init_r(void);
 #if defined(CONFIG_VID)
 int init_func_vid(void);
@@ -267,7 +300,15 @@
 /* TODO(sjg@chromium.org): Drop this when DM_PCI migration is completed */
 void pci_init_board(void);
 
-void trap_init(unsigned long reloc_addr);
+/**
+ * arch_initr_trap() - Init traps
+ *
+ * Arch specific routine for initializing traps. It is called during the
+ * generic board init sequence, after relocation.
+ *
+ * Return: 0 if OK
+ */
+int arch_initr_trap(void);
 
 /**
  * main_loop() - Enter the main loop of U-Boot
diff --git a/include/iomux.h b/include/iomux.h
index e6e1097..da7ff69 100644
--- a/include/iomux.h
+++ b/include/iomux.h
@@ -26,6 +26,5 @@
 
 int iomux_doenv(const int, const char *);
 void iomux_printdevs(const int);
-struct stdio_dev *search_device(int, const char *);
 
 #endif /* _IO_MUX_H */
diff --git a/include/log.h b/include/log.h
index 6bce560..2d27f9f 100644
--- a/include/log.h
+++ b/include/log.h
@@ -156,6 +156,9 @@
  */
 #if CONFIG_IS_ENABLED(LOG)
 #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL)
+#define log_emer(_fmt...)	log(LOG_CATEGORY, LOGL_EMERG, ##_fmt)
+#define log_alert(_fmt...)	log(LOG_CATEGORY, LOGL_ALERT, ##_fmt)
+#define log_crit(_fmt...)	log(LOG_CATEGORY, LOGL_CRIT, ##_fmt)
 #define log_err(_fmt...)	log(LOG_CATEGORY, LOGL_ERR, ##_fmt)
 #define log_warning(_fmt...)	log(LOG_CATEGORY, LOGL_WARNING, ##_fmt)
 #define log_notice(_fmt...)	log(LOG_CATEGORY, LOGL_NOTICE, ##_fmt)
@@ -163,12 +166,17 @@
 #define log_debug(_fmt...)	log(LOG_CATEGORY, LOGL_DEBUG, ##_fmt)
 #define log_content(_fmt...)	log(LOG_CATEGORY, LOGL_DEBUG_CONTENT, ##_fmt)
 #define log_io(_fmt...)		log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt)
+#define log_cont(_fmt...)	log(LOGC_CONT, LOGL_CONT, ##_fmt)
 #else
 #define _LOG_MAX_LEVEL LOGL_INFO
+#define log_emerg(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
+#define log_alert(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
+#define log_crit(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
 #define log_err(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
 #define log_warning(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
 #define log_notice(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
 #define log_info(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
+#define log_cont(_fmt, ...)	printf(_fmt, ##__VA_ARGS__)
 #define log_debug(_fmt, ...)	debug(_fmt, ##__VA_ARGS__)
 #define log_content(_fmt...)	log_nop(LOG_CATEGORY, \
 					LOGL_DEBUG_CONTENT, ##_fmt)
@@ -217,10 +225,9 @@
 #if !_DEBUG && CONFIG_IS_ENABLED(LOG)
 
 #define debug_cond(cond, fmt, args...)			\
-	do {						\
-		if (1)					\
-			log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \
-	} while (0)
+({							\
+	log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args);	\
+})
 
 #else /* _DEBUG */
 
@@ -229,11 +236,11 @@
  * computed by a preprocessor in the best case, allowing for the best
  * optimization.
  */
-#define debug_cond(cond, fmt, args...)			\
-	do {						\
-		if (cond)				\
-			printf(pr_fmt(fmt), ##args);	\
-	} while (0)
+#define debug_cond(cond, fmt, args...)		\
+({						\
+	if (cond)				\
+		printf(pr_fmt(fmt), ##args);	\
+})
 
 #endif /* _DEBUG */
 
diff --git a/include/miiphy.h b/include/miiphy.h
index 61c136b..8b77bac 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -81,7 +81,15 @@
 extern struct bb_miiphy_bus bb_miiphy_buses[];
 extern int bb_miiphy_buses_num;
 
-void bb_miiphy_init(void);
+/**
+ * bb_miiphy_init() - Initialize bit-banged MII bus driver
+ *
+ * It is called during the generic post-relocation init sequence.
+ *
+ * Return: 0 if OK
+ */
+int bb_miiphy_init(void);
+
 int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg);
 int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
 		    u16 value);
diff --git a/include/part.h b/include/part.h
index 55be724..815515a 100644
--- a/include/part.h
+++ b/include/part.h
@@ -9,6 +9,7 @@
 #include <blk.h>
 #include <ide.h>
 #include <uuid.h>
+#include <linker_lists.h>
 #include <linux/list.h>
 
 struct block_drvr {
@@ -465,16 +466,49 @@
 int is_valid_dos_buf(void *buf);
 
 /**
- * write_mbr_partition() - write DOS MBR
+ * write_mbr_sector() - write DOS MBR
  *
  * @param dev_desc - block device descriptor
  * @param buf - buffer which contains the MBR
  *
  * @return - '0' on success, otherwise error
  */
-int write_mbr_partition(struct blk_desc *dev_desc, void *buf);
+int write_mbr_sector(struct blk_desc *dev_desc, void *buf);
+
+int write_mbr_partitions(struct blk_desc *dev,
+		struct disk_partition *p, int count, unsigned int disksig);
+int layout_mbr_partitions(struct disk_partition *p, int count,
+			  lbaint_t total_sectors);
 
 #endif
 
+#ifdef CONFIG_PARTITIONS
+/**
+ * part_driver_get_count() - get partition driver count
+ *
+ * @return - number of partition drivers
+ */
+static inline int part_driver_get_count(void)
+{
+	return ll_entry_count(struct part_driver, part_driver);
+}
+
+/**
+ * part_driver_get_first() - get first partition driver
+ *
+ * @return - pointer to first partition driver on success, otherwise NULL
+ */
+static inline struct part_driver *part_driver_get_first(void)
+{
+	return ll_entry_start(struct part_driver, part_driver);
+}
+
+#else
+static inline int part_driver_get_count(void)
+{ return 0; }
+
+static inline struct part_driver *part_driver_get_first(void)
+{ return NULL; }
+#endif /* CONFIG_PARTITIONS */
 
 #endif /* _PART_H */
diff --git a/include/part_efi.h b/include/part_efi.h
index 1929e44..c68529b 100644
--- a/include/part_efi.h
+++ b/include/part_efi.h
@@ -56,6 +56,9 @@
 #define PARTITION_LINUX_LVM_GUID \
 	EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
 		0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
+#define PARTITION_U_BOOT_ENVIRONMENT \
+	EFI_GUID( 0x3de21764, 0x95bd, 0x54bd, \
+		0xa5, 0xc3, 0x4a, 0xbe, 0x78, 0x6f, 0x38, 0xa8)
 
 /* linux/include/efi.h */
 typedef u16 efi_char16_t;
diff --git a/include/post.h b/include/post.h
index eb218ac..5695e2b 100644
--- a/include/post.h
+++ b/include/post.h
@@ -107,7 +107,6 @@
 void post_bootmode_init (void);
 int post_bootmode_get (unsigned int * last_test);
 void post_bootmode_clear (void);
-void post_output_backlog ( void );
 int post_run (char *name, int flags);
 int post_info (char *name);
 int post_log (char *format, ...);
@@ -116,6 +115,16 @@
 #endif
 unsigned long post_time_ms (unsigned long base);
 
+/**
+ * post_output_backlog() - Print POST results
+ *
+ * Print POST results during the generic board init sequence, after
+ * relocation.
+ *
+ * Return: 0 if OK
+ */
+int post_output_backlog(void);
+
 extern struct post_test post_list[];
 extern unsigned int post_list_size;
 extern int post_hotkeys_pressed(void);
diff --git a/include/test/ut.h b/include/test/ut.h
index 3f2ee75..17400c7 100644
--- a/include/test/ut.h
+++ b/include/test/ut.h
@@ -338,4 +338,22 @@
  */
 long ut_check_delta(ulong last);
 
+/**
+ * ut_silence_console() - Silence the console if requested by the user
+ *
+ * This stops test output from appear on the console. It is the default on
+ * sandbox, unless the -v flag is given. For other boards, this does nothing.
+ *
+ * @uts: Test state (in case in future we want to keep state here)
+ */
+void ut_silence_console(struct unit_test_state *uts);
+
+/**
+ * ut_unsilence_console() - Unsilence the console after a test
+ *
+ * This restarts console output again and turns off console recording. This
+ * happens on all boards, including sandbox.
+ */
+void ut_unsilence_console(struct unit_test_state *uts);
+
 #endif
diff --git a/include/uuid.h b/include/uuid.h
index 73c5a89..0c653cb 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -39,10 +39,8 @@
 		    int str_format);
 void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
 		     int str_format);
-#ifdef CONFIG_PARTITION_TYPE_GUID
 int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
-int uuid_guid_get_str(const unsigned char *guid_bin, char *guid_str);
-#endif
+const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
 #endif
diff --git a/include/xen.h b/include/xen.h
index a952a2c..8681321 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -11,7 +11,7 @@
  * Map Xen memory pages, initialize event handler and xenbus,
  * setup the grant table.
  */
-void xen_init(void);
+int xen_init(void);
 
 /**
  * xen_fini() - Board cleanup before Linux kernel start
diff --git a/lib/Kconfig b/lib/Kconfig
index a704568..88c43a3 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -695,8 +695,8 @@
 config LIB_ELF
 	bool
 	help
-	  Supoort basic elf loading/validating functions.
-	  This supports fir 32 bit and 64 bit versions.
+	  Support basic elf loading/validating functions.
+	  This supports for 32 bit and 64 bit versions.
 
 endmenu
 
diff --git a/lib/aes.c b/lib/aes.c
index c998aec..05ec235 100644
--- a/lib/aes.c
+++ b/lib/aes.c
@@ -619,7 +619,7 @@
 static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
 {
 #ifdef DEBUG
-	printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+	printf("%s [%d] @0x%p", name, num_bytes, data);
 	print_buffer(0, data, 1, num_bytes, 16);
 #endif
 }
diff --git a/lib/string.c b/lib/string.c
index ae7835f..73b9841 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -567,7 +567,19 @@
 {
 	char *tmp, *s;
 
-	if (dest <= src) {
+	if (dest <= src || (src + count) <= dest) {
+	/*
+	 * Use the fast memcpy implementation (ARCH optimized or lib/string.c) when it is possible:
+	 * - when dest is before src (assuming that memcpy is doing forward-copying)
+	 * - when destination don't overlap the source buffer (src + count <= dest)
+	 *
+	 * WARNING: the first optimisation cause an issue, when __HAVE_ARCH_MEMCPY is defined,
+	 *          __HAVE_ARCH_MEMMOVE is not defined and if the memcpy ARCH-specific
+	 *          implementation is not doing a forward-copying.
+	 *
+	 * No issue today because memcpy is doing a forward-copying in lib/string.c and for ARM32
+	 * architecture; no other arches use __HAVE_ARCH_MEMCPY without __HAVE_ARCH_MEMMOVE.
+	 */
 		memcpy(dest, src, count);
 	} else {
 		tmp = (char *) dest + count;
diff --git a/lib/uuid.c b/lib/uuid.c
index e62d5ca..54a93aa 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -96,7 +96,8 @@
 	{"linux",	PARTITION_LINUX_FILE_SYSTEM_DATA_GUID},
 	{"raid",	PARTITION_LINUX_RAID_GUID},
 	{"swap",	PARTITION_LINUX_SWAP_GUID},
-	{"lvm",		PARTITION_LINUX_LVM_GUID}
+	{"lvm",		PARTITION_LINUX_LVM_GUID},
+	{"u-boot-env",	PARTITION_U_BOOT_ENVIRONMENT},
 };
 
 /*
@@ -122,20 +123,19 @@
  * uuid_guid_get_str() - this function get string for GUID.
  *
  * @param guid_bin - pointer to string with partition type guid [16B]
- * @param guid_str - pointer to allocated partition type string [7B]
+ *
+ * Returns NULL if the type GUID is not known.
  */
-int uuid_guid_get_str(const unsigned char *guid_bin, char *guid_str)
+const char *uuid_guid_get_str(const unsigned char *guid_bin)
 {
 	int i;
 
-	*guid_str = 0;
 	for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
 		if (!memcmp(list_guid[i].guid.b, guid_bin, 16)) {
-			strcpy(guid_str, list_guid[i].string);
-			return 0;
+			return list_guid[i].string;
 		}
 	}
-	return -ENODEV;
+	return NULL;
 }
 #endif
 
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
index 1fe58d5..6347335 100644
--- a/lib/zlib/deflate.c
+++ b/lib/zlib/deflate.c
@@ -1284,7 +1284,7 @@
     }
     if (z_verbose > 1) {
         fprintf(stderr,"\\[%d,%d]", start-match, length);
-        do { putc(s->window[start++], stderr); } while (--length != 0);
+	do { putc(s->window[start++]); } while (--length != 0);
     }
 }
 #else
diff --git a/lib/zlib/trees.c b/lib/zlib/trees.c
index 3e09517..700c62f 100644
--- a/lib/zlib/trees.c
+++ b/lib/zlib/trees.c
@@ -38,7 +38,7 @@
 #include "deflate.h"
 
 #ifdef DEBUG
-#  include <ctype.h>
+#  include <linux/ctype.h>
 #endif
 
 /* ===========================================================================
diff --git a/post/post.c b/post/post.c
index 0f1fe8d..7d6a647 100644
--- a/post/post.c
+++ b/post/post.c
@@ -128,7 +128,7 @@
 }
 
 /* ... and the messages are output once we are relocated */
-void post_output_backlog(void)
+int post_output_backlog(void)
 {
 	int j;
 
@@ -143,6 +143,8 @@
 			}
 		}
 	}
+
+	return 0;
 }
 
 static void post_bootmode_test_on(unsigned int last_test)
diff --git a/test/Makefile b/test/Makefile
index d4323f9..3c7bc8b 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,7 +2,7 @@
 #
 # (C) Copyright 2012 The Chromium Authors
 
-ifneq ($(CONFIG_SANDBOX),)
+ifneq ($(CONFIG_$(SPL_)BLOBLIST),)
 obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
 endif
 obj-$(CONFIG_$(SPL_)CMDLINE) += bootm.o
diff --git a/test/bloblist.c b/test/bloblist.c
index 0bb9e2d..900299d 100644
--- a/test/bloblist.c
+++ b/test/bloblist.c
@@ -7,7 +7,6 @@
 #include <bloblist.h>
 #include <log.h>
 #include <mapmem.h>
-#include <asm/state.h>
 #include <test/suites.h>
 #include <test/test.h>
 #include <test/ut.h>
@@ -240,7 +239,6 @@
 /* Test the 'bloblist info' command */
 static int bloblist_test_cmd_info(struct unit_test_state *uts)
 {
-	struct sandbox_state *state = state_get_current();
 	struct bloblist_hdr *hdr;
 	char *data, *data2;
 
@@ -250,8 +248,7 @@
 	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
 
 	console_record_reset_enable();
-	if (!state->show_test_output)
-		gd->flags |= GD_FLG_SILENT;
+	ut_silence_console(uts);
 	console_record_reset();
 	run_command("bloblist info", 0);
 	ut_assert_nextline("base:     %lx", (ulong)map_to_sysmem(hdr));
@@ -259,7 +256,7 @@
 	ut_assert_nextline("alloced:  70     112 Bytes");
 	ut_assert_nextline("free:     390    912 Bytes");
 	ut_assert_console_end();
-	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+	ut_unsilence_console(uts);
 
 	return 0;
 }
@@ -268,7 +265,6 @@
 /* Test the 'bloblist list' command */
 static int bloblist_test_cmd_list(struct unit_test_state *uts)
 {
-	struct sandbox_state *state = state_get_current();
 	struct bloblist_hdr *hdr;
 	char *data, *data2;
 
@@ -278,8 +274,7 @@
 	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
 
 	console_record_reset_enable();
-	if (!state->show_test_output)
-		gd->flags |= GD_FLG_SILENT;
+	ut_silence_console(uts);
 	console_record_reset();
 	run_command("bloblist list", 0);
 	ut_assert_nextline("Address       Size  Tag Name");
@@ -288,7 +283,7 @@
 	ut_assert_nextline("%08lx  %8x    2 SPL hand-off",
 			   (ulong)map_to_sysmem(data2), TEST_SIZE2);
 	ut_assert_console_end();
-	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+	ut_unsilence_console(uts);
 
 	return 0;
 }
diff --git a/test/cmd/mem.c b/test/cmd/mem.c
index fa6770e..fbaa8a4 100644
--- a/test/cmd/mem.c
+++ b/test/cmd/mem.c
@@ -15,6 +15,6 @@
 	struct unit_test *tests = ll_entry_start(struct unit_test, mem_test);
 	const int n_ents = ll_entry_count(struct unit_test, mem_test);
 
-	return cmd_ut_category("cmd_mem", "cmd_mem_", tests, n_ents, argc,
+	return cmd_ut_category("cmd_mem", "mem_test_", tests, n_ents, argc,
 			       argv);
 }
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 98a9abf..97c11e3 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,7 +7,7 @@
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
 obj-y += lmb.o
-obj-y += test_print.o
+obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
 obj-y += string.o
 obj-$(CONFIG_ERRNO_STR) += test_errno_str.o
diff --git a/test/log/Makefile b/test/log/Makefile
index 88bc573..afdafa5 100644
--- a/test/log/Makefile
+++ b/test/log/Makefile
@@ -8,6 +8,7 @@
 ifdef CONFIG_UT_LOG
 
 obj-y += test-main.o
+obj-y += pr_cont_test.o
 
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_LOG_SYSLOG) += syslog_test.o
diff --git a/test/log/log_test.c b/test/log/log_test.c
index ea4fc6b..82234a6 100644
--- a/test/log/log_test.c
+++ b/test/log/log_test.c
@@ -15,29 +15,44 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 /* emit some sample log records in different ways, for testing */
-static int do_log_run(int cat, const char *file)
+static int do_log_run(struct unit_test_state *uts, int cat, const char *file)
 {
 	int i;
+	int ret, expected_ret;
+
+	if (gd->flags & GD_FLG_LOG_READY)
+		expected_ret = 0;
+	else
+		expected_ret = -ENOSYS;
 
 	gd->log_fmt = LOGF_TEST;
 	debug("debug\n");
 	for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
 		log(cat, i, "log %d\n", i);
-		_log(log_uc_cat(cat), i, file, 100 + i, "func", "_log %d\n",
-		     i);
+		ret = _log(log_uc_cat(cat), i, file, 100 + i,
+			   "func", "_log %d\n", i);
+		ut_asserteq(ret, expected_ret);
+	}
+	/* test with LOGL_COUNT flag */
+	for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
+		ret = _log(log_uc_cat(cat), i | LOGL_FORCE_DEBUG, file, 100 + i,
+			   "func", "_log force %d\n", i);
+		ut_asserteq(ret, expected_ret);
 	}
 
 	gd->log_fmt = log_get_default_format();
 	return 0;
 }
 
-#define log_run_cat(cat) do_log_run(cat, "file")
-#define log_run_file(file) do_log_run(UCLASS_SPI, file)
-#define log_run() do_log_run(UCLASS_SPI, "file")
+#define log_run_cat(cat) do_log_run(uts, cat, "file")
+#define log_run_file(file) do_log_run(uts, UCLASS_SPI, file)
+#define log_run() do_log_run(uts, UCLASS_SPI, "file")
 
 #define EXPECT_LOG BIT(0)
 #define EXPECT_DIRECT BIT(1)
 #define EXPECT_EXTRA BIT(2)
+#define EXPECT_FORCE BIT(3)
+#define EXPECT_DEBUG BIT(4)
 
 static int do_check_log_entries(struct unit_test_state *uts, int flags, int min,
 				int max)
@@ -49,11 +64,22 @@
 			ut_assert_nextline("do_log_run() log %d", i);
 		if (flags & EXPECT_DIRECT)
 			ut_assert_nextline("func() _log %d", i);
+		if (flags & EXPECT_DEBUG) {
+			ut_assert_nextline("log %d", i);
+			ut_assert_nextline("_log %d", i);
+		}
 	}
 	if (flags & EXPECT_EXTRA)
 		for (; i <= LOGL_MAX ; i++)
 			ut_assert_nextline("func() _log %d", i);
 
+	for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
+		if (flags & EXPECT_FORCE)
+			ut_assert_nextline("func() _log force %d", i);
+		if (flags & EXPECT_DEBUG)
+			ut_assert_nextline("_log force %d", i);
+	}
+
 	ut_assert_console_end();
 	return 0;
 }
@@ -66,10 +92,10 @@
 
 #define check_log_entries_flags(flags) \
 	check_log_entries_flags_levels(flags, LOGL_FIRST, _LOG_MAX_LEVEL)
-#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT)
+#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE)
 #define check_log_entries_extra() \
-	check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA)
-#define check_log_entries_none() check_log_entries_flags(0)
+	check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE)
+#define check_log_entries_none() check_log_entries_flags(EXPECT_FORCE)
 
 /* Check a category filter using the first category */
 int log_test_cat_allow(struct unit_test_state *uts)
@@ -126,7 +152,7 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run_file("file");
-	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
+	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE);
 
 	ut_assertok(console_record_reset_enable());
 	log_run_file("file2");
@@ -147,7 +173,7 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run_file("file2");
-	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
+	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE);
 
 	ut_assertok(log_remove_filter("console", filt));
 	return 0;
@@ -182,8 +208,8 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run();
-	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, LOGL_FIRST,
-				       LOGL_WARNING);
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
+				       LOGL_FIRST, LOGL_WARNING);
 
 	ut_assertok(log_remove_filter("console", filt));
 	return 0;
@@ -351,7 +377,7 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run();
-	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
 				       LOGL_WARNING + 1, _LOG_MAX_LEVEL);
 
 	ut_assertok(log_remove_filter("console", filt1));
@@ -374,7 +400,7 @@
 
 	ut_assertok(console_record_reset_enable());
 	log_run();
-	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
 				       LOGL_WARNING, LOGL_INFO - 1);
 
 	ut_assertok(log_remove_filter("console", filt1));
@@ -382,3 +408,23 @@
 	return 0;
 }
 LOG_TEST_FLAGS(log_test_min, UT_TESTF_CONSOLE_REC);
+
+/* Check dropped traces */
+int log_test_dropped(struct unit_test_state *uts)
+{
+	/* force LOG not ready */
+	gd->flags &= ~(GD_FLG_LOG_READY);
+	gd->log_drop_count = 0;
+
+	ut_assertok(console_record_reset_enable());
+	log_run();
+
+	ut_asserteq(gd->log_drop_count, 3 * (LOGL_COUNT - LOGL_FIRST - 1));
+	check_log_entries_flags_levels(EXPECT_DEBUG, LOGL_FIRST, CONFIG_LOG_DEFAULT_LEVEL);
+
+	gd->flags |= GD_FLG_LOG_READY;
+	gd->log_drop_count = 0;
+
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_dropped, UT_TESTF_CONSOLE_REC);
diff --git a/test/log/pr_cont_test.c b/test/log/pr_cont_test.c
new file mode 100644
index 0000000..236eff4
--- /dev/null
+++ b/test/log/pr_cont_test.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test continuation of log messages using pr_cont().
+ */
+
+#include <common.h>
+#include <console.h>
+#include <test/log.h>
+#include <test/test.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include <linux/printk.h>
+
+#define BUFFSIZE 64
+
+#undef CONFIG_LOGLEVEL
+#define CONFIG_LOGLEVEL 4
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int log_test_pr_cont(struct unit_test_state *uts)
+{
+	int log_fmt;
+	int log_level;
+
+	log_fmt = gd->log_fmt;
+	log_level = gd->default_log_level;
+
+	/* Write two messages, the second continuing the first */
+	gd->log_fmt = BIT(LOGF_MSG);
+	gd->default_log_level = LOGL_INFO;
+	console_record_reset_enable();
+	pr_err("ea%d ", 1);
+	pr_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, "ea1 cc2"));
+	ut_assertok(ut_check_console_end(uts));
+
+	return 0;
+}
+LOG_TEST(log_test_pr_cont);
diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py
index 387b392..f889120 100644
--- a/test/py/tests/test_log.py
+++ b/test/py/tests/test_log.py
@@ -36,3 +36,14 @@
         run_with_format('FLfm', 'file.c:123-func() msg')
         run_with_format('lm', 'NOTICE. msg')
         run_with_format('m', 'msg')
+
+@pytest.mark.buildconfigspec('debug_uart')
+@pytest.mark.boardspec('sandbox')
+def test_log_dropped(u_boot_console):
+    """Test dropped 'log' message when debug_uart is activated"""
+
+    cons = u_boot_console
+    cons.restart_uboot()
+    output = cons.get_spawn_output().replace('\r', '')
+    assert 'sandbox: starting...' in output
+    assert (not 'debug: main' in output)
diff --git a/test/str_ut.c b/test/str_ut.c
index ef1205d..cd50455 100644
--- a/test/str_ut.c
+++ b/test/str_ut.c
@@ -19,7 +19,7 @@
 /* Declare a new str test */
 #define STR_TEST(_name, _flags)		UNIT_TEST(_name, _flags, str_test)
 
-static int str_test_upper(struct unit_test_state *uts)
+static int str_upper(struct unit_test_state *uts)
 {
 	char out[TEST_STR_SIZE];
 
@@ -55,7 +55,7 @@
 
 	return 0;
 }
-STR_TEST(str_test_upper, 0);
+STR_TEST(str_upper, 0);
 
 static int run_strtoul(struct unit_test_state *uts, const char *str, int base,
 		       ulong expect_val, int expect_endp_offset, bool upper)
diff --git a/test/ut.c b/test/ut.c
index 95bdd66..44ed1ba 100644
--- a/test/ut.c
+++ b/test/ut.c
@@ -8,6 +8,9 @@
 #include <common.h>
 #include <console.h>
 #include <malloc.h>
+#ifdef CONFIG_SANDBOX
+#include <asm/state.h>
+#endif
 #include <test/test.h>
 #include <test/ut.h>
 
@@ -114,3 +117,18 @@
 
 	return upto == total_bytes ? 0 : 1;
 }
+
+void ut_silence_console(struct unit_test_state *uts)
+{
+#ifdef CONFIG_SANDBOX
+	struct sandbox_state *state = state_get_current();
+
+	if (!state->show_test_output)
+		gd->flags |= GD_FLG_SILENT;
+#endif
+}
+
+void ut_unsilence_console(struct unit_test_state *uts)
+{
+	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+}