Author: hailfinger
Date: 2008-02-13 16:48:37 +0100 (Wed, 13 Feb 2008)
New Revision: 590

Modified:
   coreboot-v3/arch/x86/geodelx/stage0.S
   coreboot-v3/arch/x86/stage0_i586.S
   coreboot-v3/arch/x86/stage1.c
   coreboot-v3/include/arch/x86/cpu.h
   coreboot-v3/include/console.h
   coreboot-v3/lib/Kconfig
   coreboot-v3/lib/console.c
Log:
Make printk() log to a buffer.
Tested on Qemu and Geode LX.
Benefits of this patch:
- printk() now works directly after printk_buffer_init(), even before
the serial port is set up.
- If all you want is a log, you don't have to bother with serial output.
- A payload can read and analyze the log.
- You can build on this and buffer log until serial is available, then
flush the messages buffered so far.

The printk buffer is configurable with a default-on Kconfig variable.

If you want to dump the buffer from the Qemu monitor after CAR has been
disabled, use this command:
memsave 0x90000 65536 memdump.bin

Signed-off-by: Carl-Daniel Hailfinger <[EMAIL PROTECTED]>
Acked-by: Peter Stuge <[EMAIL PROTECTED]>
Acked-by: Stefan Reinauer <[EMAIL PROTECTED]>
Acked-by: Marc Jones <[EMAIL PROTECTED]>


Modified: coreboot-v3/arch/x86/geodelx/stage0.S
===================================================================
--- coreboot-v3/arch/x86/geodelx/stage0.S       2008-02-13 15:35:30 UTC (rev 
589)
+++ coreboot-v3/arch/x86/geodelx/stage0.S       2008-02-13 15:48:37 UTC (rev 
590)
@@ -361,6 +361,13 @@
        movw    %ax, %ss
 
 lout:
+#ifdef CONFIG_CONSOLE_BUFFER
+       /* Store pointer to start of printk buffer, should really use
+        * PRINTK_BUF_ADDR_CAR instead.
+        */
+       movl    $CONFIG_CARBASE, %eax
+       pushl   %eax  /* printk buffer */
+#endif
        /* Restore the BIST result. */
        movl    %ebp, %eax
 

Modified: coreboot-v3/arch/x86/stage0_i586.S
===================================================================
--- coreboot-v3/arch/x86/stage0_i586.S  2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/arch/x86/stage0_i586.S  2008-02-13 15:48:37 UTC (rev 590)
@@ -433,7 +433,13 @@
        movw    %ax, %ss
 
 lout:
-
+#ifdef CONFIG_CONSOLE_BUFFER
+       /* Store pointer to start of printk buffer, should really use
+        * PRINTK_BUF_ADDR_CAR instead.
+        */
+       movl    $CONFIG_CARBASE, %eax
+       pushl   %eax  /* printk buffer */
+#endif
        /* Restore the BIST result */
        movl    %ebp, %eax
        /* We need to set ebp ? No need */

Modified: coreboot-v3/arch/x86/stage1.c
===================================================================
--- coreboot-v3/arch/x86/stage1.c       2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/arch/x86/stage1.c       2008-02-13 15:48:37 UTC (rev 590)
@@ -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 ...
@@ -67,6 +68,12 @@
 
 }
 
+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(int msg_level, unsigned char *buf, int size)
 {
        int i;
@@ -129,6 +136,11 @@
 
        // We have cache as ram running and can start executing code in C.
 
+#ifdef CONFIG_CONSOLE_BUFFER
+       /* Initialize the printk buffer. */
+       printk_buffer_init();
+#endif
+
        hardware_stage1();
 
        //
@@ -173,10 +185,14 @@
 
        printk(BIOS_DEBUG, "Done RAM init code\n");
 
-
        /* Turn off Cache-As-Ram */
        disable_car();
 
+#ifdef CONFIG_CONSOLE_BUFFER
+       /* Move the printk buffer to PRINTK_BUF_ADDR_RAM */
+       printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM);
+#endif
+
        entry = load_file_segments(&archive, "normal/stage2");
        if (entry == (void *)-1)
                die("FATAL: Failed loading stage2.");

Modified: coreboot-v3/include/arch/x86/cpu.h
===================================================================
--- coreboot-v3/include/arch/x86/cpu.h  2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/include/arch/x86/cpu.h  2008-02-13 15:48:37 UTC (rev 590)
@@ -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,13 @@
        __asm__ __volatile__("hlt" : : : "memory");
 }
 
+SHARED(bottom_of_stack, void *, void);
+
+#ifdef CONFIG_CONSOLE_BUFFER
+#define PRINTK_BUF_SIZE_CAR (CONFIG_CARSIZE / 2)
+#define PRINTK_BUF_ADDR_CAR CONFIG_CARBASE
+#define PRINTK_BUF_SIZE_RAM 65536
+#define PRINTK_BUF_ADDR_RAM 0x90000
+#endif
+
 #endif /* ARCH_X86_CPU_H */

Modified: coreboot-v3/include/console.h
===================================================================
--- coreboot-v3/include/console.h       2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/include/console.h       2008-02-13 15:48:37 UTC (rev 590)
@@ -37,6 +37,10 @@
 unsigned char console_rx_byte(void);
 int console_tst_byte(void);
 void die(const char *msg);
+#ifdef CONFIG_CONSOLE_BUFFER
+void printk_buffer_init(void);
+void printk_buffer_move(void *newaddr, int newsize);
+#endif
 
 struct console_driver {
        void (*init)(void);
@@ -46,6 +50,15 @@
        int (*tst_byte)(void);
 };
 
+#ifdef CONFIG_CONSOLE_BUFFER
+struct printk_buffer {
+       int len;
+       int readoffset;
+       int writeoffset;
+       char buffer[];
+};
+#endif
+
 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);

Modified: coreboot-v3/lib/Kconfig
===================================================================
--- coreboot-v3/lib/Kconfig     2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/lib/Kconfig     2008-02-13 15:48:37 UTC (rev 590)
@@ -223,5 +223,12 @@
          When you enable this option, coreboot will prefix each line of
          console output with '(LB)'.
 
+config CONSOLE_BUFFER
+       boolean "Console memory buffer support"
+       default y
+       depends CONSOLE
+       help
+         Save coreboot output in a memory buffer.
+
 endmenu
 

Modified: coreboot-v3/lib/console.c
===================================================================
--- coreboot-v3/lib/console.c   2008-02-13 15:35:30 UTC (rev 589)
+++ coreboot-v3/lib/console.c   2008-02-13 15:48:37 UTC (rev 590)
@@ -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,80 @@
        return CONFIG_DEFAULT_CONSOLE_LOGLEVEL;
 }
 
+#ifdef CONFIG_CONSOLE_BUFFER
+void printk_buffer_move(void *newaddr, int newsize)
+{
+       struct printk_buffer **p;
+       struct printk_buffer *oldbuf, *newbuf;
+       int copylen;
+       p = bottom_of_stack();
+       oldbuf = *p;
+       newbuf = newaddr;
+       newbuf->len = newsize;
+       newbuf->readoffset = 0;
+       /* Check for wraparound */
+       if (oldbuf->writeoffset < oldbuf->readoffset) {
+               /* Copy from readoffset to end of buffer. */
+               copylen = oldbuf->len - oldbuf->readoffset;
+       } else {
+               /* Copy from readoffset to writeoffset (exclusive).*/
+               copylen = oldbuf->writeoffset - oldbuf->readoffset;
+       }
+       if (copylen > newsize)
+               copylen = newsize;
+       /* If memcpy() ever uses printk we will see pretty explosions. */
+       memcpy(&newbuf->buffer[0], &oldbuf->buffer[oldbuf->readoffset],
+               copylen);
+       newbuf->writeoffset = copylen;
+       /* Check for wraparound */
+       if (oldbuf->writeoffset < oldbuf->readoffset) {
+               /* Copy from start of buffer to writeoffset (exclusive). */
+               copylen = (copylen + oldbuf->writeoffset > newsize)
+                               ? newsize - copylen : oldbuf->writeoffset;
+               memcpy(&newbuf->buffer[newbuf->writeoffset],
+                       &oldbuf->buffer[0], copylen);
+               newbuf->writeoffset += copylen;
+       }
+       *p = newbuf;
+       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;
+       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;
+       /* Make sure writeoffset is always ahead of readoffset here. */
+       if (buf->writeoffset == buf->readoffset) {
+               buf->readoffset++;
+               buf->readoffset %= buf->len;
+       }
+       return;
+}
+#endif
+
 void console_tx_byte(unsigned char byte, void *arg)
 {
+#ifdef CONFIG_CONSOLE_BUFFER
+       buffer_tx_byte(byte, arg);
+#endif
+#ifdef CONFIG_CONSOLE_SERIAL
        if (byte == '\n') {
                uart8250_tx_byte(TTYSx_BASE, '\r');
 #if defined(CONFIG_CONSOLE_PREFIX) && (CONFIG_CONSOLE_PREFIX == 1)
@@ -26,8 +99,8 @@
                return;
 #endif
        }
-
        uart8250_tx_byte(TTYSx_BASE, byte);
+#endif
 }
 
 int printk(int msg_level, const char *fmt, ...)


-- 
coreboot mailing list
[email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to