[coreboot] [PATCH 1/2] SerialICE files, receive function for romcc_console, bootblock_simple example

Tadas Slotkus devtadas at gmail.com
Mon Jul 4 20:46:28 CEST 2011


Copy required SerialICE files (not patched yet), add receive byte
function to romcc_console, add SerialICE to bootblock_simple

SerialICE revision: 107

Signed-off-by: Tadas Slotkus <devtadas at gmail.com>
---
 src/arch/x86/SerialICE/io.h          |  195 ++++++++++++++++++++++++++
 src/arch/x86/SerialICE/serial.c      |  187 ++++++++++++++++++++++++
 src/arch/x86/SerialICE/serialice.c   |  257
++++++++++++++++++++++++++++++++++
 src/arch/x86/init/bootblock_simple.c |    2 +
 src/arch/x86/lib/romcc_console.c     |    7 +
 5 files changed, 648 insertions(+), 0 deletions(-)
 create mode 100644 src/arch/x86/SerialICE/io.h
 create mode 100644 src/arch/x86/SerialICE/serial.c
 create mode 100644 src/arch/x86/SerialICE/serialice.c

diff --git a/src/arch/x86/SerialICE/io.h b/src/arch/x86/SerialICE/io.h
new file mode 100644
index 0000000..a47feef
--- /dev/null
+++ b/src/arch/x86/SerialICE/io.h
@@ -0,0 +1,195 @@
+/*
+ * SerialICE 
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#ifndef IO_H
+#define IO_H
+
+/* Memory functions */
+
+static inline u8 read8(unsigned long addr)
+{
+	return *((volatile u8 *)(addr));
+}
+
+static inline u16 read16(unsigned long addr)
+{
+	return *((volatile u16 *)(addr));
+}
+
+static inline u32 read32(unsigned long addr)
+{
+	return *((volatile u32 *)(addr));
+}
+
+static inline void write8(unsigned long addr, u8 value)
+{
+	*((volatile u8 *)(addr)) = value;
+}
+
+static inline void write16(unsigned long addr, u16 value)
+{
+	*((volatile u16 *)(addr)) = value;
+}
+
+static inline void write32(unsigned long addr, u32 value)
+{
+	*((volatile u32 *)(addr)) = value;
+}
+
+/* IO functions */
+
+#if defined( __ROMCC__ ) && !defined (__GNUC__)
+static inline void outb(u8 value, u16 port)
+{
+	__builtin_outb(value, port);
+}
+
+static inline void outw(u16 value, u16 port)
+{
+	__builtin_outw(value, port);
+}
+
+static inline void outl(u32 value, u16 port)
+{
+	__builtin_outl(value, port);
+}
+
+static inline u8 inb(u16 port)
+{
+	return __builtin_inb(port);
+}
+
+static inline u16 inw(u16 port)
+{
+	return __builtin_inw(port);
+}
+
+static inline u32 inl(u16 port)
+{
+	return __builtin_inl(port);
+}
+#else
+static inline void outb(u8 value, u16 port)
+{
+	__asm__ __volatile__("outb %b0, %w1"::"a"(value), "Nd"(port));
+}
+
+static inline void outw(u16 value, u16 port)
+{
+	__asm__ __volatile__("outw %w0, %w1"::"a"(value), "Nd"(port));
+}
+
+static inline void outl(u32 value, u16 port)
+{
+	__asm__ __volatile__("outl %0, %w1"::"a"(value), "Nd"(port));
+}
+
+static inline u8 inb(u16 port)
+{
+	u8 value;
+	__asm__ __volatile__("inb %w1, %b0":"=a"(value): "Nd"(port));
+	return value;
+}
+
+static inline u16 inw(u16 port)
+{
+	u16 value;
+	__asm__ __volatile__("inw %w1, %w0":"=a"(value): "Nd"(port));
+	return value;
+}
+
+static inline u32 inl(u16 port)
+{
+	u32 value;
+	__asm__ __volatile__("inl %w1, %0":"=a"(value): "Nd"(port));
+	return value;
+}
+#endif /* __ROMCC__ && !__GNUC__ */
+
+/* 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 eax, ebx;
+
+        __asm__("cpuid"
+                : "=b" (ebx)
+                : "a" (op), "c" (op2)
+                : "edx");
+        return ebx;
+}
+
+static inline u32 cpuid_ecx(u32 op, u32 op2)
+{
+        u32 eax, ecx;
+
+        __asm__("cpuid"
+                : "=c" (ecx)
+                : "a" (op), "c" (op2)
+                : "ebx", "edx" );
+        return ecx;
+}
+
+static inline u32 cpuid_edx(u32 op, u32 op2)
+{
+        u32 eax, edx;
+
+        __asm__("cpuid"
+                : "=d" (edx)
+                : "a" (op), "c" (op2)
+                : "ebx");
+        return edx;
+}
+
+#endif
diff --git a/src/arch/x86/SerialICE/serial.c
b/src/arch/x86/SerialICE/serial.c
new file mode 100644
index 0000000..9aaecb6
--- /dev/null
+++ b/src/arch/x86/SerialICE/serial.c
@@ -0,0 +1,187 @@
+/*
+ * SerialICE 
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+/* SIO functions */
+
+static void sio_init(void)
+{
+	int divisor = 115200 / SIO_SPEED;
+	int lcs = 3;
+	outb(0x00, SIO_PORT + UART_IER);
+	outb(0x01, SIO_PORT + UART_FCR);
+	outb(0x03, SIO_PORT + UART_MCR);
+	outb(0x80 | lcs, SIO_PORT + UART_LCR);
+	outb(divisor & 0xff, SIO_PORT + UART_DLL);
+	outb((divisor >> 8) & 0xff, SIO_PORT + UART_DLM);
+	outb(lcs, SIO_PORT + UART_LCR);
+}
+
+static void sio_putc(u8 data)
+{
+	while (!(inb(SIO_PORT + UART_LSR) & 0x20)) ;
+	outb(data, SIO_PORT + UART_TBR);
+	while (!(inb(SIO_PORT + UART_LSR) & 0x40)) ;
+}
+
+static u8 sio_getc(void)
+{
+	u8 val;
+	while (!(inb(SIO_PORT + UART_LSR) & 0x01)) ;
+
+	val = inb(SIO_PORT + UART_RBR);
+
+#if ECHO_MODE
+	sio_putc(val);
+#endif
+	return val;
+}
+
+/* SIO helpers */
+
+static void sio_putstring(char *string)
+{
+	/* Very simple, no %d, %x etc. */
+	while (*string) {
+		if (*string == '\n')
+			sio_putc('\r');
+		sio_putc(*string);
+		string++;
+	}
+}
+
+#define sio_put_nibble(nibble)	\
+	if (nibble > 9)		\
+		nibble += ('a' - 10);	\
+	else			\
+		nibble += '0';	\
+	sio_putc(nibble)
+
+static void sio_put8(u8 data)
+{
+	int i;
+	u8 c;
+		
+	c = (data >> 4) & 0xf;
+	sio_put_nibble(c);
+
+	c = data & 0xf;
+	sio_put_nibble(c);
+}
+
+static void sio_put16(u16 data)
+{
+	int i;
+	for (i=12; i >= 0; i -= 4) {
+		u8 c = (data >> i) & 0xf;
+		sio_put_nibble(c);
+	}
+}
+
+static void sio_put32(u32 data)
+{
+	int i;
+	for (i=28; i >= 0; i -= 4) {
+		u8 c = (data >> i) & 0xf;
+		sio_put_nibble(c);
+	}
+}
+
+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;
+}
+
+
diff --git a/src/arch/x86/SerialICE/serialice.c
b/src/arch/x86/SerialICE/serialice.c
new file mode 100644
index 0000000..35531dc
--- /dev/null
+++ b/src/arch/x86/SerialICE/serialice.c
@@ -0,0 +1,257 @@
+/*
+ * SerialICE 
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#include <types.h>
+#include <serialice.h>
+#include <io.h>
+
+/* SIO functions */
+#include "serial.c"
+
+/* Hardware specific functions */
+
+#include "chipset.c"
+
+/* Accessor functions */
+
+static void serialice_read_memory(void)
+{
+	u8 width;
+	u32 addr;
+
+	// Format:
+	// *rm00000000.w
+	addr = 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 = 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)
+{
+	sio_putc('\r'); sio_putc('\n');
+
+	/* must be defined in mainboard/<boardname>.c */
+	sio_putstring(boardname);
+}
+
+static void serialice_version(void)
+{
+	sio_putstring("\nSerialICE v" VERSION " (" __DATE__ ")\n");
+}
+
+int main(void)
+{
+	chipset_init();
+
+	sio_init();
+
+	serialice_version();
+
+	while(1) {
+		u16 c;
+		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;
+		}
+	}
+
+	// Never get here:
+	return 0;
+}
diff --git a/src/arch/x86/init/bootblock_simple.c
b/src/arch/x86/init/bootblock_simple.c
index 5d7c611..8386868 100644
--- a/src/arch/x86/init/bootblock_simple.c
+++ b/src/arch/x86/init/bootblock_simple.c
@@ -1,4 +1,5 @@
 #include <bootblock_common.h>
+#include "../SerialICE/serialice.c"
 
 static void main(unsigned long bist)
 {
@@ -12,6 +13,7 @@ static void main(unsigned long bist)
 	sanitize_cmos();
 #endif
 
+	serialice_main();
 	const char* target1 = "fallback/romstage";
 	unsigned long entry;
 	entry = findstage(target1);
diff --git a/src/arch/x86/lib/romcc_console.c
b/src/arch/x86/lib/romcc_console.c
index 13ee1f0..3747136 100644
--- a/src/arch/x86/lib/romcc_console.c
+++ b/src/arch/x86/lib/romcc_console.c
@@ -48,6 +48,13 @@ static void __console_tx_byte(unsigned char byte)
 #endif
 }
 
+static unsigned char __console_rx_byte(void)
+{
+#if CONFIG_CONSOLE_SERIAL8250
+	return uart8250_rx_byte(CONFIG_TTYS0_BASE);
+#endif
+}
+
 static void __console_tx_nibble(unsigned nibble)
 {
 	unsigned char digit;
-- 
1.7.0.4






More information about the coreboot mailing list