cbmem: add and use a function to dump console buffer

The new function can be compiled in only when serial console is
disabled.

When invoked, this function initializes the serial interface and dumps
the contents of the CBMEM console buffer to serial output.

BRANCH=none
BUG=chromium:475347
TEST=compiled for different platforms with and without serial console
     enabled. No actual test of this function yet.

Change-Id: Ia8d16649dc9d09798fa6970f2cfd893438e00dc5
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: a38a8254dd788ad188ba2509b9ae117d6f699579
Original-Change-Id: Ib85759a2727e31ba1ca21da7e6c346e434f83b52
Original-Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265293
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/9984
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/src/console/Kconfig b/src/console/Kconfig
index 2807039..7d6fa0e 100644
--- a/src/console/Kconfig
+++ b/src/console/Kconfig
@@ -184,6 +184,15 @@
 	  value (128K or 0x20000 bytes) is large enough to accommodate
 	  even the BIOS_SPEW level.
 
+config CONSOLE_CBMEM_DUMP_TO_UART
+	depends on !CONSOLE_SERIAL
+	bool "Dump CBMEM console on resets"
+	default n
+	help
+	  Enable this to have CBMEM console buffer contents dumped on the
+	  serial output in case serial console is disabled and the device
+	  resets itself while trying to boot the payload.
+
 endif
 
 config CONSOLE_QEMU_DEBUGCON
diff --git a/src/include/console/cbmem_console.h b/src/include/console/cbmem_console.h
index 3431459..8f7fcb2 100644
--- a/src/include/console/cbmem_console.h
+++ b/src/include/console/cbmem_console.h
@@ -43,4 +43,5 @@
 static inline void __cbmemc_tx_byte(u8 data)	{}
 #endif
 
+void cbmem_dump_console(void);
 #endif
diff --git a/src/lib/cbmem_console.c b/src/lib/cbmem_console.c
index 628d3b9..9d292bf 100644
--- a/src/lib/cbmem_console.c
+++ b/src/lib/cbmem_console.c
@@ -19,6 +19,7 @@
 
 #include <console/console.h>
 #include <console/cbmem_console.h>
+#include <console/uart.h>
 #include <cbmem.h>
 #include <arch/early_variables.h>
 #include <symbols.h>
@@ -236,5 +237,21 @@
 	init_console_ptr(cbm_cons_p, size, flags);
 }
 
+#if IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART)
+void cbmem_dump_console(void)
+{
+	struct cbmem_console *cbm_cons_p;
+	int cursor;
+
+	cbm_cons_p = current_console();
+	if (!cbm_cons_p)
+		return;
+
+	uart_init(0);
+	for (cursor = 0; cursor < cbm_cons_p->buffer_cursor; cursor++)
+		uart_tx_byte(0, cbm_cons_p->buffer_body[cursor]);
+}
+#endif
+
 /* Call cbmemc_reinit() at CAR migration time. */
 CAR_MIGRATE(cbmemc_reinit)
diff --git a/src/vendorcode/google/chromeos/vboot.c b/src/vendorcode/google/chromeos/vboot.c
index 44fe9e3..a151f54 100644
--- a/src/vendorcode/google/chromeos/vboot.c
+++ b/src/vendorcode/google/chromeos/vboot.c
@@ -234,6 +234,8 @@
 #if !MOCK_TPM
 	printk(BIOS_ERR, "TPM: Error code 0x%x. Hard reset!\n", result);
 	post_code(POST_TPM_FAILURE);
+	if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART))
+		cbmem_dump_console();
 	hard_reset();
 #endif
 }
diff --git a/src/vendorcode/google/chromeos/vboot_common.c b/src/vendorcode/google/chromeos/vboot_common.c
index bacacd4..2e0ab2b 100644
--- a/src/vendorcode/google/chromeos/vboot_common.c
+++ b/src/vendorcode/google/chromeos/vboot_common.c
@@ -130,6 +130,8 @@
 
 void vboot_reboot(void)
 {
+	if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART))
+		cbmem_dump_console();
 	hard_reset();
 	die("failed to reboot");
 }