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@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@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.");