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