Antonello Dettori (dev@dettori.io) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14504
-gerrit
commit 300e7ba06f61b3d902598f679542d068e0f29958 Author: Patrick Rudolph siro@das-labor.org Date: Mon Apr 25 11:00:17 2016 +0200
console/serialice: Add SerialICE
Add Kconfig Option to build SerialICE shell into coreboot stages. You can select between romstage and ramstage. The SerialICE shell will be launched instead of coreboot console. As minimal system initialization is already done in coreboot, it should work on all boards.
Tested with EHCI Debug on Lenovo T520 and Lenovo X60.
Needs tests: * Ramstage * On other boards
Change-Id: I1fa6eb4f40e0f625c8c8302d1580bcd2664d670b Signed-off-by: Patrick Rudolph siro@das-labor.org Signed-off-by: Antonello Dettori dev@dettori.io --- src/Kconfig | 33 +++ src/arch/x86/c_start.S | 2 +- src/arch/x86/exception.c | 7 +- src/console/Makefile.inc | 2 + src/console/console.c | 22 -- src/console/init.c | 3 + src/console/serialice.c | 430 ++++++++++++++++++++++++++++++++++++++++ src/console/serialice_priv.h | 103 ++++++++++ src/include/console/serialice.h | 30 +++ src/include/console/streams.h | 6 - src/include/console/uart.h | 10 +- src/include/console/usb.h | 11 +- src/include/serial-com.h | 24 +++ src/lib/Makefile.inc | 5 + src/lib/serial-com.c | 80 ++++++++ 15 files changed, 719 insertions(+), 49 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 1cb55c9..c13189d 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -1078,6 +1078,39 @@ config DEBUG_COVERAGE If enabled, the code coverage hooks in coreboot will output some information about the coverage data that is dumped.
+config DEBUG_SERIALICE + bool "Enable SerialICE instead normal boot" + default n + depends on ARCH_X86 + depends on CONSOLE_SERIAL || CONSOLE_USB + depends on !GDB_STUB + help + If enabled, SerialICE will be run instead of normal boot. + You need to connect a serial cable or EHCI debug dongle to + communicate with SerialICE shell. + +if DEBUG_SERIALICE + +choice + prompt "SerialICE bootstage" + default DEBUG_SERIALICE_ROMSTAGE + help + Choose the stage SerialICE to start. You can choose between + ROMSTAGE and RAMSTAGE. + +config DEBUG_SERIALICE_ROMSTAGE + bool "Start SerialICE instead of Romstage" + depends on CONSOLE_SERIAL || USBDEBUG_IN_ROMSTAGE + help + Start SerialICE in romstage, right after minimal system initialization. + +config DEBUG_SERIALICE_RAMSTAGE + bool "Start SerialICE instead of Ramstage" + help + Start SerialICE in ramstage. +endchoice + +endif endmenu
# These probably belong somewhere else, but they are needed somewhere. diff --git a/src/arch/x86/c_start.S b/src/arch/x86/c_start.S index 6bda64f..ed6025c 100644 --- a/src/arch/x86/c_start.S +++ b/src/arch/x86/c_start.S @@ -111,7 +111,7 @@ _start: post_code(POST_PRE_HARDWAREMAIN) /* post fe */
#if CONFIG_GDB_WAIT - call gdb_hw_init + call serial_hw_init call gdb_stub_breakpoint #endif call main diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c index b6e6ffb..c8f474f 100644 --- a/src/arch/x86/exception.c +++ b/src/arch/x86/exception.c @@ -14,6 +14,7 @@ #include <console/console.h> #include <console/streams.h> #include <string.h> +#include <serial-com.h>
#if CONFIG_GDB_STUB
@@ -231,17 +232,17 @@ static char out_buffer[BUFMAX];
static inline void stub_putc(int ch) { - gdb_tx_byte(ch); + serial_tx_byte(ch); }
static inline void stub_flush(void) { - gdb_tx_flush(); + serial_tx_flush(); }
static inline int stub_getc(void) { - return gdb_rx_byte(); + return serial_rx_byte(); }
static int hex(char ch) diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index 0fee12a..e3015fe 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -2,6 +2,7 @@ ramstage-y += vtxprintf.c printk.c vsprintf.c ramstage-y += init.c console.c ramstage-y += post.c ramstage-y += die.c +ramstage-$(CONFIG_DEBUG_SERIALICE_RAMSTAGE) += serialice.c
smm-$(CONFIG_DEBUG_SMI) += init.c console.c vtxprintf.c printk.c smm-$(CONFIG_SMM_TSEG) += die.c @@ -17,6 +18,7 @@ romstage-y += vtxprintf.c printk.c romstage-y += init.c console.c romstage-y += post.c romstage-y += die.c +romstage-$(CONFIG_DEBUG_SERIALICE_ROMSTAGE) += serialice.c
postcar-y += vtxprintf.c printk.c postcar-y += init.c console.c diff --git a/src/console/console.c b/src/console/console.c index c4365f3..231b245 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -62,25 +62,3 @@ void console_tx_flush(void) __usb_tx_flush(); }
- -#if CONFIG_GDB_STUB && (ENV_ROMSTAGE || ENV_RAMSTAGE) -void gdb_hw_init(void) -{ - __gdb_hw_init(); -} - -void gdb_tx_byte(unsigned char byte) -{ - __gdb_tx_byte(byte); -} - -void gdb_tx_flush(void) -{ - __gdb_tx_flush(); -} - -unsigned char gdb_rx_byte(void) -{ - return __gdb_rx_byte(); -} -#endif diff --git a/src/console/init.c b/src/console/init.c index 8f40abb..66b751c 100644 --- a/src/console/init.c +++ b/src/console/init.c @@ -16,6 +16,7 @@
#include <console/console.h> #include <console/uart.h> +#include <console/serialice.h> #include <console/streams.h> #include <device/pci.h> #include <option.h> @@ -43,6 +44,8 @@ void console_init(void)
console_hw_init();
+ serialice_main(); + printk(BIOS_INFO, "\n\ncoreboot-%s%s %s " ENV_STRING " starting...\n", coreboot_version, coreboot_extra_version, coreboot_build); } diff --git a/src/console/serialice.c b/src/console/serialice.c new file mode 100644 index 0000000..dc57edb --- /dev/null +++ b/src/console/serialice.c @@ -0,0 +1,430 @@ +/* + * SerialICE + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2016 Patrick Rudolph siro@das-labor.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <console/console.h> +#include <console/serialice.h> +#include <arch/io.h> +#include <serial-com.h> +#include "serialice_priv.h" + +#define VERSION "1.6" + +/* Uart wrapper functions */ + +static void sio_flush(void) +{ + serial_tx_flush(); +} + +static void sio_putc(u8 byte) +{ + serial_tx_byte(byte); +} + +static u8 sio_getc(void) +{ + u8 val = 0; + + val = serial_rx_byte(); + if (val) { +#if ECHO_MODE + sio_putc(val); +#endif + return val; + } + + return 0; +} + +/* String functions */ + +static void sio_putstring(const char *string) +{ + /* Very simple, no %d, %x etc. */ + while (*string) { + if (*string == '\n') + sio_putc('\r'); + sio_putc(*string); + string++; + } + sio_flush(); +} + +static void sio_put8(u8 data) +{ + u8 c; + + c = (data >> 4) & 0xf; + sio_put_nibble(c); + + c = data & 0xf; + sio_put_nibble(c); + sio_flush(); +} + +static void sio_put16(u16 data) +{ + int i; + u8 c; + + for (i = 12; i >= 0; i -= 4) { + c = (data >> i) & 0xf; + sio_put_nibble(c); + } + sio_flush(); +} + +static void sio_put32(u32 data) +{ + int i; + u8 c; + + for (i = 28; i >= 0; i -= 4) { + c = (data >> i) & 0xf; + sio_put_nibble(c); + } + sio_flush(); +} + +static u8 sio_get_nibble(void) +{ + u8 ret = 0; + u8 nibble = sio_getc(); + + if (nibble >= '0' && nibble <= '9') { + ret = (nibble - '0'); + } else if (nibble >= 'a' && nibble <= 'f') { + ret = (nibble - 'a') + 0xa; + } else if (nibble >= 'A' && nibble <= 'F') { + ret = (nibble - 'A') + 0xa; + } else { + sio_putstring("ERROR: parsing number\n"); + } + return ret; +} + +static u8 sio_get8(void) +{ + u8 data; + + data = sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + return data; +} + +static u16 sio_get16(void) +{ + u16 data; + + data = sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + + return data; +} + +static u32 sio_get32(void) +{ + u32 data; + + data = sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + data = data << 4; + data |= sio_get_nibble(); + + return data; +} + +/* SerialICE interface functions */ + +static void serialice_read_memory(void) +{ + u8 width; + u32 *addr; + + // Format: + // *rm00000000.w + addr = (u32 *)sio_get32(); + sio_getc(); // skip . + width = sio_getc(); + + sio_putc('\r'); sio_putc('\n'); + + switch (width) { + case 'b': + sio_put8(read8(addr)); + break; + case 'w': + sio_put16(read16(addr)); + break; + case 'l': + sio_put32(read32(addr)); + break; + } +} + +static void serialice_write_memory(void) +{ + u8 width; + u32 *addr; + u32 data; + + // Format: + // *wm00000000.w=0000 + addr = (u32 *)sio_get32(); + sio_getc(); // skip . + width = sio_getc(); + sio_getc(); // skip = + + switch (width) { + case 'b': + data = sio_get8(); + write8(addr, (u8)data); + break; + case 'w': + data = sio_get16(); + write16(addr, (u16)data); + break; + case 'l': + data = sio_get32(); + write32(addr, (u32)data); + break; + } +} + +static void serialice_read_io(void) +{ + u8 width; + u16 port; + + // Format: + // *ri0000.w + port = sio_get16(); + sio_getc(); // skip . + width = sio_getc(); + + sio_putc('\r'); sio_putc('\n'); + + switch (width) { + case 'b': + sio_put8(inb(port)); + break; + case 'w': + sio_put16(inw(port)); + break; + case 'l': + sio_put32(inl(port)); + break; + } +} + +static void serialice_write_io(void) +{ + u8 width; + u16 port; + u32 data; + + // Format: + // *wi0000.w=0000 + port = sio_get16(); + sio_getc(); // skip . + width = sio_getc(); + sio_getc(); // skip = + + switch (width) { + case 'b': + data = sio_get8(); + outb((u8)data, port); + break; + case 'w': + data = sio_get16(); + outw((u16)data, port); + break; + case 'l': + data = sio_get32(); + outl((u32)data, port); + break; + } +} + +static void serialice_read_msr(void) +{ + u32 addr, key; + msr_t msr; + + // Format: + // *rc00000000.9c5a203a + addr = sio_get32(); + sio_getc(); // skip . + key = sio_get32(); // key in %edi + + sio_putc('\r'); sio_putc('\n'); + + msr = rdmsr(addr, key); + sio_put32(msr.hi); + sio_putc('.'); + sio_put32(msr.lo); +} + +static void serialice_write_msr(void) +{ + u32 addr, key; + msr_t msr; + + // Format: + // *wc00000000.9c5a203a=00000000.00000000 + addr = sio_get32(); + sio_getc(); // skip . + key = sio_get32(); // read key in %edi + sio_getc(); // skip = + msr.hi = sio_get32(); + sio_getc(); // skip . + msr.lo = sio_get32(); + +#ifdef __ROMCC__ + /* Cheat to avoid register outage */ + wrmsr(addr, msr, 0x9c5a203a); +#else + wrmsr(addr, msr, key); +#endif +} + +static void serialice_cpuinfo(void) +{ + u32 eax, ecx; + u32 reg32; + + // Format: + // --EAX--- --ECX--- + // *ci00000000.00000000 + eax = sio_get32(); + sio_getc(); // skip . + ecx = sio_get32(); + + sio_putc('\r'); sio_putc('\n'); + + /* This code looks quite crappy but this way we don't + * have to worry about running out of registers if we + * occupy eax, ebx, ecx, edx at the same time + */ + reg32 = cpuid_eax(eax, ecx); + sio_put32(reg32); + sio_putc('.'); + + reg32 = cpuid_ebx(eax, ecx); + sio_put32(reg32); + sio_putc('.'); + + reg32 = cpuid_ecx(eax, ecx); + sio_put32(reg32); + sio_putc('.'); + + reg32 = cpuid_edx(eax, ecx); + sio_put32(reg32); +} + +static void serialice_mainboard(void) +{ + int i = 0; + const char mb_string[] = CONFIG_MAINBOARD_VENDOR" " + CONFIG_MAINBOARD_PART_NUMBER; + + sio_putc('\r'); sio_putc('\n'); + + while (i < 32 && mb_string[i] > 0) { + sio_putc(mb_string[i]); + i++; + } + while (i < 32) { + sio_putc(' '); + i++; + } + + sio_flush(); +} + +static void serialice_version(void) +{ + sio_putstring("\nSerialICE v" VERSION "\n"); +} + +void serialice_main(void) +{ + u16 c; + + serialice_version(); + + while (1) { + sio_putstring("\n> "); + + c = sio_getc(); + if (c != '*') + continue; + + c = sio_getc() << 8; + c |= sio_getc(); + + switch (c) { + case (('r' << 8)|'m'): // Read Memory *rm + serialice_read_memory(); + break; + case (('w' << 8)|'m'): // Write Memory *wm + serialice_write_memory(); + break; + case (('r' << 8)|'i'): // Read IO *ri + serialice_read_io(); + break; + case (('w' << 8)|'i'): // Write IO *wi + serialice_write_io(); + break; + case (('r' << 8)|'c'): // Read CPU MSR *rc + serialice_read_msr(); + break; + case (('w' << 8)|'c'): // Write CPU MSR *wc + serialice_write_msr(); + break; + case (('c' << 8)|'i'): // Read CPUID *ci + serialice_cpuinfo(); + break; + case (('m' << 8)|'b'): // Read mainboard type *mb + serialice_mainboard(); + break; + case (('v' << 8)|'i'): // Read version info *vi + serialice_version(); + break; + default: + sio_putstring("ERROR\n"); + break; + } + } +} diff --git a/src/console/serialice_priv.h b/src/console/serialice_priv.h new file mode 100644 index 0000000..078ef04 --- /dev/null +++ b/src/console/serialice_priv.h @@ -0,0 +1,103 @@ +/* + * SerialICE + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2016 Patrick Rudolph siro@das-labor.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef CONSOLE_SERIALICE_PRIV_H +#define CONSOLE_SERIALICE_PRIV_H + +/* String functions */ + +#define sio_put_nibble(nibble) \ + do { \ + if (nibble > 9) \ + nibble += ('a' - 10); \ + else \ + nibble += '0'; \ + sio_putc(nibble); \ + } while (0) + +/* MSR functions */ + +typedef struct { u32 lo, hi; } msr_t; + +static inline msr_t rdmsr(u32 index, u32 key) +{ + msr_t result; + + __asm__ __volatile__ ( + "rdmsr" + : "=a" (result.lo), "=d" (result.hi) + : "c" (index), "D" (key) + ); + return result; +} + +static inline void wrmsr(u32 index, msr_t msr, u32 key) +{ + __asm__ __volatile__ ( + "wrmsr" + : /* No outputs */ + : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (key) + ); +} + +/* CPUID functions */ + +static inline u32 cpuid_eax(u32 op, u32 op2) +{ + u32 eax; + + __asm__("cpuid" + : "=a" (eax) + : "a" (op), "c" (op2) + : "ebx", "edx"); + return eax; +} + +static inline u32 cpuid_ebx(u32 op, u32 op2) +{ + u32 ebx; + + __asm__("cpuid" + : "=b" (ebx) + : "a" (op), "c" (op2) + : "edx"); + return ebx; +} + +static inline u32 cpuid_ecx(u32 op, u32 op2) +{ + u32 ecx; + + __asm__("cpuid" + : "=c" (ecx) + : "a" (op), "c" (op2) + : "ebx", "edx"); + return ecx; +} + +static inline u32 cpuid_edx(u32 op, u32 op2) +{ + u32 edx; + + __asm__("cpuid" + : "=d" (edx) + : "a" (op), "c" (op2) + : "ebx"); + return edx; +} + +#endif diff --git a/src/include/console/serialice.h b/src/include/console/serialice.h new file mode 100644 index 0000000..a2b27e7 --- /dev/null +++ b/src/include/console/serialice.h @@ -0,0 +1,30 @@ +/* + * SerialICE + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2016 Patrick Rudolph siro@das-labor.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef CONSOLE_SERIALICE_H +#define CONSOLE_SERIALICE_H + +#define ECHO_MODE 1 + +#if (ENV_RAMSTAGE && CONFIG_DEBUG_SERIALICE_RAMSTAGE) || \ + (ENV_ROMSTAGE && CONFIG_DEBUG_SERIALICE_ROMSTAGE) +void serialice_main(void); +#else +static inline void serialice_main(void) { } +#endif + +#endif diff --git a/src/include/console/streams.h b/src/include/console/streams.h index 35f7999..53bd12d 100644 --- a/src/include/console/streams.h +++ b/src/include/console/streams.h @@ -18,10 +18,4 @@ void console_hw_init(void); void console_tx_byte(unsigned char byte); void console_tx_flush(void);
-/* For remote GDB debugging. */ -void gdb_hw_init(void); -void gdb_tx_byte(unsigned char byte); -void gdb_tx_flush(void); -unsigned char gdb_rx_byte(void); - #endif /* _CONSOLE_STREAMS_H_ */ diff --git a/src/include/console/uart.h b/src/include/console/uart.h index a3d650b..05df8d8 100644 --- a/src/include/console/uart.h +++ b/src/include/console/uart.h @@ -63,18 +63,12 @@ void oxford_remap(unsigned int new_base); static inline void __uart_init(void) { uart_init(CONFIG_UART_FOR_CONSOLE); } static inline void __uart_tx_byte(u8 data) { uart_tx_byte(CONFIG_UART_FOR_CONSOLE, data); } static inline void __uart_tx_flush(void) { uart_tx_flush(CONFIG_UART_FOR_CONSOLE); } +static inline u8 __uart_rx_byte(void) { return uart_rx_byte(CONFIG_UART_FOR_CONSOLE); } #else static inline void __uart_init(void) {} static inline void __uart_tx_byte(u8 data) {} static inline void __uart_tx_flush(void) {} -#endif - -#if CONFIG_GDB_STUB && (ENV_ROMSTAGE || ENV_RAMSTAGE) -#define CONFIG_UART_FOR_GDB CONFIG_UART_FOR_CONSOLE -static inline void __gdb_hw_init(void) { uart_init(CONFIG_UART_FOR_GDB); } -static inline void __gdb_tx_byte(u8 data) { uart_tx_byte(CONFIG_UART_FOR_GDB, data); } -static inline void __gdb_tx_flush(void) { uart_tx_flush(CONFIG_UART_FOR_GDB); } -static inline u8 __gdb_rx_byte(void) { return uart_rx_byte(CONFIG_UART_FOR_GDB); } +static inline u8 __uart_rx_byte(void) { return 0; } #endif
#endif /* __ROMCC__ */ diff --git a/src/include/console/usb.h b/src/include/console/usb.h index b758c03..65e1dee 100644 --- a/src/include/console/usb.h +++ b/src/include/console/usb.h @@ -37,19 +37,12 @@ int usb_can_rx_byte(int idx); static inline void __usbdebug_init(void) { usbdebug_init(); } static inline void __usb_tx_byte(u8 data) { usb_tx_byte(USB_PIPE_FOR_CONSOLE, data); } static inline void __usb_tx_flush(void) { usb_tx_flush(USB_PIPE_FOR_CONSOLE); } +static inline u8 __usb_rx_byte(void) { return usb_rx_byte(USB_PIPE_FOR_CONSOLE); } #else static inline void __usbdebug_init(void) {} static inline void __usb_tx_byte(u8 data) {} static inline void __usb_tx_flush(void) {} -#endif - -/* */ -#if 0 && CONFIG_GDB_STUB && \ - ((ENV_ROMSTAGE && CONFIG_USBDEBUG_IN_ROMSTAGE) || ENV_RAMSTAGE) -static inline void __gdb_hw_init(void) { usbdebug_init(); } -static inline void __gdb_tx_byte(u8 data) { usb_tx_byte(USB_PIPE_FOR_GDB, data); } -static inline void __gdb_tx_flush(void) { usb_tx_flush(USB_PIPE_FOR_GDB); } -static inline u8 __gdb_rx_byte(void) { return usb_rx_byte(USB_PIPE_FOR_GDB); } +static inline u8 __usb_rx_byte(void) { return 0; } #endif
#endif /* _CONSOLE_USB_H_ */ diff --git a/src/include/serial-com.h b/src/include/serial-com.h new file mode 100644 index 0000000..baf75ce --- /dev/null +++ b/src/include/serial-com.h @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +#include <stdint.h> + +void serial_hw_init(void); +void serial_tx_byte(unsigned char byte); +void serial_tx_flush(void); +unsigned char serial_rx_byte(void); + +#endif /* _SERIAL_H_ */ diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 49720a7..989cef4 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -221,6 +221,11 @@ postcar-y += prog_ops.c postcar-y += rmodule.c postcar-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
+romstage-$(CONFIG_DEBUG_SERIALICE_ROMSTAGE) += serial-com.c +ramstage-$(CONFIG_DEBUG_SERIALICE_RAMSTAGE) += serial-com.c +romstage-$(CONFIG_GDB_STUB) += serial-com.c +ramstage-$(CONFIG_GDB_STUB) += serial-com.c + # Use program.ld for all the platforms which use C fo the bootblock. bootblock-$(CONFIG_C_ENVIRONMENT_BOOTBLOCK) += program.ld
diff --git a/src/lib/serial-com.c b/src/lib/serial-com.c new file mode 100644 index 0000000..2354237 --- /dev/null +++ b/src/lib/serial-com.c @@ -0,0 +1,80 @@ +/* + * This file is part of the coreboot project. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <rules.h> +#include <stdint.h> +#include <console/uart.h> +#include <console/usb.h> +#include <serial-com.h> + +#define CONFIG_UART_FOR_GDB CONFIG_UART_FOR_CONSOLE +#define USB_PIPE_FOR_GDB 0 + +#if __CONSOLE_SERIAL_ENABLE__ && !CONFIG_GDB_STUB +static inline void __serial_hw_init(void) { __uart_init(); } +static inline void __serial_tx_byte(u8 data) { __uart_tx_byte(data); } +static inline void __serial_tx_flush(void) { __uart_tx_flush(); } +static inline u8 __serial_rx_byte(void) { return __uart_rx_byte(); } +#elif __CONSOLE_USB_ENABLE__ && !CONFIG_GDB_STUB +static inline void __serial_hw_init(void) { __usbdebug_init(); } +static inline void __serial_tx_byte(u8 data) { __usb_tx_byte(data); } +static inline void __serial_tx_flush(void) { __usb_tx_flush(); } +static inline u8 __serial_rx_byte(void) { return __usb_rx_byte(); } +/* Configure functions to use GDB arguments */ +#elif __CONSOLE_USB_ENABLE__ && CONFIG_GDB_STUB && \ + ((ENV_ROMSTAGE && CONFIG_USBDEBUG_IN_ROMSTAGE) || ENV_RAMSTAGE) +static inline void __serial_hw_init(void) { usbdebug_init(); } +static inline void __serial_tx_byte(u8 data) + { usb_tx_byte(USB_PIPE_FOR_GDB, data); } +static inline void __serial_tx_flush(void) + { usb_tx_flush(USB_PIPE_FOR_GDB); } +static inline u8 __serial_rx_byte(void) + { return usb_rx_byte(USB_PIPE_FOR_GDB); } +#elif __CONSOLE_SERIAL_ENABLE__ && CONFIG_GDB_STUB && \ + (ENV_ROMSTAGE || ENV_RAMSTAGE) +static inline void __serial_hw_init(void) + { uart_init(CONFIG_UART_FOR_GDB); } +static inline void __serial_tx_byte(u8 data) + { uart_tx_byte(CONFIG_UART_FOR_GDB, data); } +static inline void __serial_tx_flush(void) + { uart_tx_flush(CONFIG_UART_FOR_GDB); } +static inline u8 __serial_rx_byte(void) + { return uart_rx_byte(CONFIG_UART_FOR_GDB); } +#else +static inline void __serial_hw_init(void) {} +static inline void __serial_tx_byte(u8 data) {} +static inline void __serial_tx_flush(void) {} +static inline u8 __serial_rx_byte(void) { return 0; } +#endif + + +void serial_hw_init(void) +{ + __serial_hw_init(); +} + +void serial_tx_byte(unsigned char byte) +{ + __serial_tx_byte(byte); +} + +void serial_tx_flush(void) +{ + __serial_tx_flush(); +} + +unsigned char serial_rx_byte(void) +{ + return __serial_rx_byte(); +} +