[coreboot] [PATCH] v3: printk buffer

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sun Feb 10 23:09:22 CET 2008


Make printk() log to a buffer.
This only works with qemu for now, but there it works really well.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: LinuxBIOSv3-printkbuffer/include/console.h
===================================================================
--- LinuxBIOSv3-printkbuffer/include/console.h	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/include/console.h	(Arbeitskopie)
@@ -37,6 +37,8 @@
 unsigned char console_rx_byte(void);
 int console_tst_byte(void);
 void die(const char *msg);
+void printk_buffer_init(void);
+void printk_buffer_move(void *newaddr, int newsize);
 
 struct console_driver {
 	void (*init)(void);
@@ -46,8 +48,20 @@
 	int (*tst_byte)(void);
 };
 
+struct printk_buffer {
+	int len;
+	int readoffset;
+	int writeoffset;
+	int realoffset;
+#ifdef CONFIG_CHECK_STACK_USAGE	/* This config variable does not exit yet. */
+	void *loweststack;
+#endif
+	char buffer[];
+};
+
 SHARED_WITH_ATTRIBUTES(printk, int, __attribute__((format (printf, 2, 3))),
 					int msg_level, const char *fmt, ...);
 SHARED(banner, void, int msg_level, const char *msg);
+SHARED(dump_mem_range, void, unsigned char *buf, int size);
 
 #endif /* CONSOLE_H */
Index: LinuxBIOSv3-printkbuffer/include/arch/x86/cpu.h
===================================================================
--- LinuxBIOSv3-printkbuffer/include/arch/x86/cpu.h	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/include/arch/x86/cpu.h	(Arbeitskopie)
@@ -24,6 +24,7 @@
 
 #include <types.h>
 #include <device/device.h>
+#include <shared.h>
 
 #define X86_VENDOR_INTEL	0
 #define X86_VENDOR_CYRIX	1
@@ -196,4 +197,15 @@
 	__asm__ __volatile__("hlt" : : : "memory");
 }
 
+SHARED(bottom_of_stack, void *, void);
+
+#define PRINTK_BUF_SIZE_CAR 2048
+#ifndef CONFIG_CARBASE
+#error CONFIG_CARBASE was not defined
+#else
+#define PRINTK_BUF_ADDR_CAR CONFIG_CARBASE
+#endif
+#define PRINTK_BUF_SIZE_RAM 65536
+#define PRINTK_BUF_ADDR_RAM 0x90000
+
 #endif /* ARCH_X86_CPU_H */
Index: LinuxBIOSv3-printkbuffer/device/device.c
===================================================================
--- LinuxBIOSv3-printkbuffer/device/device.c	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/device/device.c	(Arbeitskopie)
@@ -742,17 +742,16 @@
 	post_code(POST_STAGE2_PHASE2_ENTER);
 	printk(BIOS_DEBUG, "Phase 2: Early setup...\n");
 	for (dev = all_devices; dev; dev = dev->next) {
-		printk(BIOS_SPEW, "%s: dev %s: ", __FUNCTION__, dev->dtsname);
-		printk(BIOS_SPEW, "%s: ops %p ops->phase2_setup_scan_bus %p\n",
-			__FUNCTION__, dev->ops, 
+		printk(BIOS_SPEW,
+			"%s: dev %s: ops %p ops->phase2_setup_scan_bus %p\n",
+			__FUNCTION__, dev->dtsname, dev->ops, 
 			dev->ops? dev->ops->phase2_setup_scan_bus : NULL);
 		if (dev->ops && dev->ops->phase2_setup_scan_bus) {
 			printk(BIOS_SPEW,
-			       "Calling phase2 phase2_setup_scan_bus...");
+			       "Calling phase2 phase2_setup_scan_bus...\n");
 			dev->ops->phase2_setup_scan_bus(dev);
-			printk(BIOS_SPEW, " done");
+			printk(BIOS_SPEW, " done\n");
 		}
-		printk(BIOS_SPEW, "\n");
 	}
 
 	post_code(POST_STAGE2_PHASE2_DONE);
Index: LinuxBIOSv3-printkbuffer/lib/console.c
===================================================================
--- LinuxBIOSv3-printkbuffer/lib/console.c	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/lib/console.c	(Arbeitskopie)
@@ -3,6 +3,7 @@
 #include <console.h>
 #include <uart8250.h>
 #include <stdarg.h>
+#include <string.h>
 
 int vtxprintf(void (*)(unsigned char, void *arg), 
 		void *arg, const char *, va_list);
@@ -12,8 +13,59 @@
 	return CONFIG_DEFAULT_CONSOLE_LOGLEVEL;
 }
 
+void printk_buffer_move(void *newaddr, int newsize)
+{
+	struct printk_buffer **p;
+	struct printk_buffer *oldbuf, *newbuf;
+	p = bottom_of_stack();
+	oldbuf = *p;
+	*p = newbuf = newaddr;
+	/* FIXME: The memcpy is wrong on so many levels.
+	 * It should deal with wraparounds and with oldbuf->len > newbuf->len
+	 */
+	memcpy(newbuf, oldbuf, sizeof(struct printk_buffer) + oldbuf->len);
+	newbuf->len = newsize;
+	return;
+}
+
+struct printk_buffer *printk_buffer_addr(void)
+{
+	struct printk_buffer **p;
+	p = bottom_of_stack();
+	return *p;
+}
+
+void printk_buffer_init(void)
+{
+	struct printk_buffer *buf = printk_buffer_addr();
+	buf->len = PRINTK_BUF_SIZE_CAR - sizeof(struct printk_buffer);
+	buf->readoffset = 0;
+	buf->writeoffset = 0;
+#ifdef CONFIG_CHECK_STACK_USAGE	/* This config variable does not exit yet. */
+	buf->loweststack = 0;
+#endif
+	return;
+}
+
+void buffer_tx_byte(unsigned char byte, void *arg)
+{
+	struct printk_buffer *buf = printk_buffer_addr();
+	buf->buffer[buf->writeoffset++] = byte;
+	buf->writeoffset %= buf->len;
+#ifdef CONFIG_CHECK_STACK_USAGE	/* This config variable does not exit yet. */
+	int i;
+	/* stack usage checker */
+	for (i = 0; i < 2048; i++)
+		if (buf->buffer[buf->len + i] != 0x0)
+			break;
+	buf->loweststack = &buf->buffer[buf->len + i];
+#endif
+	return;
+}
+
 void console_tx_byte(unsigned char byte, void *arg)
 {
+	buffer_tx_byte(byte, arg);
 	if (byte == '\n') {
 		uart8250_tx_byte(TTYSx_BASE, '\r');
 #if defined(CONFIG_CONSOLE_PREFIX) && (CONFIG_CONSOLE_PREFIX == 1)
Index: LinuxBIOSv3-printkbuffer/arch/x86/Kconfig
===================================================================
--- LinuxBIOSv3-printkbuffer/arch/x86/Kconfig	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/arch/x86/Kconfig	(Arbeitskopie)
@@ -69,4 +69,15 @@
 	  coreboot work correctly on symmetric multi processor
 	  systems.
 	  It is usually set in mainboard/*/Kconfig.
- 
+
+config CARBASE
+	hex
+	default 0x8f000 if CPU_I586
+	help
+	  This option sets the base address of the area used for CAR.
+
+config CARSIZE
+	hex
+	default 0x1000 if CPU_I586
+	help
+	  This option sets the size of the area used for CAR.
Index: LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S
===================================================================
--- LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S	(Arbeitskopie)
@@ -184,14 +184,13 @@
  */
 
 #ifndef CONFIG_CARSIZE
-#define CacheSize 4096
+#error CONFIG_CARSIZE was not defined
 #else
 #define CacheSize CONFIG_CARSIZE
 #endif
 
-/* pick a safer value for default -- i.e. not the C segment! */
 #ifndef CONFIG_CARBASE
-#define CacheBase (0x90000 - CacheSize) 
+#error CONFIG_CARBASE was not defined
 #else
 #define CacheBase CONFIG_CARBASE
 #endif
@@ -442,7 +441,9 @@
 	movw    %ax, %ss
 
 lout:
-
+	/* Store pointer to start of printk buffer */
+	movl	$CacheBase, %eax
+	pushl 	%eax  /* printk buffer */
 	/* Restore the BIST result */
 	movl	%ebp, %eax
 	/* We need to set ebp ? No need */
Index: LinuxBIOSv3-printkbuffer/arch/x86/stage1.c
===================================================================
--- LinuxBIOSv3-printkbuffer/arch/x86/stage1.c	(Revision 584)
+++ LinuxBIOSv3-printkbuffer/arch/x86/stage1.c	(Arbeitskopie)
@@ -26,6 +26,7 @@
 #include <tables.h>
 #include <lib.h>
 #include <mc146818rtc.h>
+#include <cpu.h>
 
 /* ah, well, what a mess! This is a hard code. FIX ME but how? 
  * By getting rid of ELF ...
@@ -66,6 +67,26 @@
 	// FIXME check integrity
 
 }
+
+void *bottom_of_stack(void)
+{
+
+	/* -4-4 because CONFIG_CARBASE + CONFIG_CARSIZE - 4 is initial %esp */
+	return (void *)(CONFIG_CARBASE + CONFIG_CARSIZE - 4 - 4);
+}
+
+void dump_mem_range(unsigned char *buf, int size)
+{
+	int i;
+	printk(BIOS_SPEW, "dump memrange:\n");
+	for (i = 0; i < size; i++) {
+		printk(BIOS_SPEW, "%02x ", buf[i]);
+		if (i % 16 == 15)
+			printk(BIOS_SPEW, "\n");
+	}
+	return;
+}
+
 /* until we get rid of elf */
 int legacy(struct mem_file *archive, char *name, void *where, struct lb_memory *mem)
 {
@@ -116,6 +137,9 @@
 
 	// We have cache as ram running and can start executing code in C.
 
+	/* Initialize the printk buffer. */
+	printk_buffer_init();
+
 	hardware_stage1();
 
 	//
@@ -160,10 +184,12 @@
 
 	printk(BIOS_DEBUG, "Done RAM init code\n");
 
-
 	/* Turn off Cache-As-Ram */
 	disable_car();
 
+	/* Move the printk buffer to PRINTK_BUF_ADDR_RAM */
+	printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM);
+
 	entry = load_file_segments(&archive, "normal/stage2");
 	if (entry == (void *)-1)
 		die("FATAL: Failed loading stage2.");


-- 
http://www.hailfinger.org/





More information about the coreboot mailing list