[coreboot] [PATCH] v3: printk buffer
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Mon Feb 11 03:01:39 CET 2008
On 10.02.2008 23:21, Carl-Daniel Hailfinger wrote:
> On 10.02.2008 23:09, Carl-Daniel Hailfinger wrote:
>
>> 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>
>>
>>
>
> A few side 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.
>
New version, without the recently merged stuff.
If you want to dump the buffer from the Qemu monitor after CAR has been
disabled, use this command:
memsave 0x90000 65536 memdump.bin
Tested on Qemu, should work on LX. Code needs to get in mergeable shape
before commit, but I'd appreciate testers on LX with FS2.
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 587)
+++ 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,6 +48,17 @@
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);
Index: LinuxBIOSv3-printkbuffer/include/arch/x86/cpu.h
===================================================================
--- LinuxBIOSv3-printkbuffer/include/arch/x86/cpu.h (Revision 587)
+++ 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,11 @@
__asm__ __volatile__("hlt" : : : "memory");
}
+SHARED(bottom_of_stack, void *, void);
+
+#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 /* ARCH_X86_CPU_H */
Index: LinuxBIOSv3-printkbuffer/lib/console.c
===================================================================
--- LinuxBIOSv3-printkbuffer/lib/console.c (Revision 587)
+++ 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/geodelx/stage0.S
===================================================================
--- LinuxBIOSv3-printkbuffer/arch/x86/geodelx/stage0.S (Revision 587)
+++ LinuxBIOSv3-printkbuffer/arch/x86/geodelx/stage0.S (Arbeitskopie)
@@ -361,6 +361,11 @@
movw %ax, %ss
lout:
+ /* Store pointer to start of printk buffer, should really use
+ * PRINTK_BUF_ADDR_CAR instead.
+ */
+ movl $CONFIG_CARBASE, %eax
+ pushl %eax /* printk buffer */
/* Restore the BIST result. */
movl %ebp, %eax
Index: LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S
===================================================================
--- LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S (Revision 587)
+++ LinuxBIOSv3-printkbuffer/arch/x86/stage0_i586.S (Arbeitskopie)
@@ -433,7 +433,11 @@
movw %ax, %ss
lout:
-
+ /* Store pointer to start of printk buffer, should really use
+ * PRINTK_BUF_ADDR_CAR instead.
+ */
+ movl $CONFIG_CARBASE, %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 587)
+++ 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 ...
@@ -67,6 +68,13 @@
}
+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 +137,9 @@
// We have cache as ram running and can start executing code in C.
+ /* Initialize the printk buffer. */
+ printk_buffer_init();
+
hardware_stage1();
//
@@ -173,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