mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
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 <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Peter Stuge <peter@stuge.se> Acked-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Marc Jones <marc.jones@amd.com> git-svn-id: svn://coreboot.org/repository/coreboot-v3@590 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
parent
fd7c529003
commit
5d11489d74
7 changed files with 135 additions and 3 deletions
|
@ -361,6 +361,13 @@ DCacheSetupGood:
|
|||
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
|
||||
|
||||
|
|
|
@ -433,7 +433,13 @@ clear_fixed_var_mtrr_out:
|
|||
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 */
|
||||
|
|
|
@ -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 init_archive(struct mem_file *archive)
|
|||
|
||||
}
|
||||
|
||||
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 @@ void __attribute__((stdcall)) stage1_main(u32 bist)
|
|||
|
||||
// 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 @@ void __attribute__((stdcall)) stage1_main(u32 bist)
|
|||
|
||||
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.");
|
||||
|
|
|
@ -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 @@ static inline __attribute__((always_inline)) void hlt(void)
|
|||
__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 */
|
||||
|
|
|
@ -37,6 +37,10 @@ void console_tx_flush(void);
|
|||
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 @@ struct console_driver {
|
|||
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);
|
||||
|
|
|
@ -223,5 +223,12 @@ config CONSOLE_PREFIX
|
|||
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
|
||||
|
||||
|
|
|
@ -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 @@ static int console_loglevel(void)
|
|||
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 @@ void console_tx_byte(unsigned char byte, void *arg)
|
|||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
uart8250_tx_byte(TTYSx_BASE, byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
int printk(int msg_level, const char *fmt, ...)
|
||||
|
|
Loading…
Add table
Reference in a new issue