Coreboot console over Ethernet

Although this article is about Coreboot I start from beginning. Once upon a time (November 2009) there was nice idea to make SerialICE work through the Ethernet link. Reason is simple, it is slow and Ethernet is way faster. I started to investigate if there is some network adapter which can be used without the need of RAM.

If you check the documentation of most Ethernet chips, the packet descriptors are always located in main memory and they  just use DMA to transfer data to/from the FIFO inside the card. I tried some sophisticated google queries to find out if there is some adapter with internal SRAM, and after a while I found one.

The RTL8029AS is NE2000 PCI chip (10Mbit/s). It is just a clone of National Semiconductor NS8390 glued together with PCI interface. What is the best, this card just needs a PIO transfer to put/get data out of 16KB SRAM!

Luckily I own the card, and I started to investigate how to use it. I grabbed the gPXE sources and start to hack out something I could run in plain userspace to test the TX and RX functions. Maciej Pijanka aka Agaran helped me to debug the stuff but we did not finish this to usable state – we tried to read out the MAC instead of use of hardcoded one, and we had in plan to implement the IP checksum function which would work directly in SRAM. No one had time and this idea just went down. If someone with a spare time reads this here is the chance 😉

Why I went back and dust off the idea?  I have a very short serial cable and therefore I had to always connect the Coreboot machine to the notebook which is bit annoying if I sit in front of my workstation. But the Ethernet is already there. This project to use NE2000 for Coreboot console looked much easier.

It was relatively simple. I took the PCI NE2000 driver from last try to make it work with SerialICE, changed all routines to accept the IO base as its argument. There is a probe routine and init routine. For the init routine I just need to find the PCI device and set the BAR0 to something hardcoded (eg 0xe00) and enable the IO decode in PCI command register, afterwards the probe routine can be called which just needs to know the IO address. This is called around same time as init_uart().

It took me some time to find out which uart_tx_byte is used in romstage! There are so many clones of this function, but finaly I found it is in arch/i386/lib 😉 I hacked the uart_tx_byte write the byte to card SRAM and I abuse the the register for multicast MAC to store how many bytes I have written. After printing routine is done, the the packet is constructed with fixed MAC and fixed IP, but with variable length. The IP payload is UDP packet (src port 6667 dest 6666) The UDP payload is our text which is already there. Then invoke the transmit just to transmit it 😉

I was lucky and it worked! However not after cold boot. It was stuck in TX routine and “packed has been sent” was never set. I found out that I call it before I reset/probe the card, and afterwards it worked like a charm too!

Of course just until the end of romstage. We need the console for ramstage too. It was simple too, I just had to hack the console function again (and yes in src/console this time). Yep it worked, until last line when coreboot sets new BAR for the network card… I work around this by writing a simple PCI driver for Coreboot, which just returns the current resources. The resource allocator won’t touch it anymore.

All looks easy, but will it work if the PCI slot is behind some kind of bridge? Answer is YES if the PCI-PCI bridge is doing subtractive decoding (which means if the IO nobody wants I take it). The VT8237S has some bit which can make the PCI bus for slots appear behind PCI-PCI bridge and this is exactly the situation. I did not need to setup anything, it worked out of the box too (the IO decode for the bridge is set automatically after reset, and it does work even if the bus number for subordinate bus is 0).

Here is how it looks in Linux, if the NE2000 is set to fixed 0xe00:
00:13.1 PCI bridge: VIA Technologies, Inc. VT8237A PCI to PCI Bridge (prog-if 01
[Subtractive decode])
Bus: primary=00, secondary=05, subordinate=05, sec-latency=0
I/O behind bridge: 00001000-00001fff
Memory behind bridge: f1200000-f12fffff

05:06.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8029(AS)
Flags: medium devsel, IRQ 16
I/O ports at 0e00 [size=32]
Kernel driver in use: ne2k-pci
Kernel modules: ne2k-pci

And here how it looks if I catch the output with netcat:

$nc -u -l -p 6666
coreboot-4.0-r5577M Sun May 30 20:21:52 CEST 2010 starting...
now booting...
INIT detected from --- { APICID = 00 NODEID = 00 COREID = 00} ---
Issuing SOFT_RESET...
soft reset
coreboot-4.0-r5577M Sun May 30 20:21:52 CEST 2010 starting...
now booting...
Enabling routing table for node 00 done.
Enabling UP settings
Disabling read/write/fill probes for UP... done.
<---- snip ---->
Post relocation: addr: 0x00000000000eca00 memsz: 0x0000000000013600 filesz:
using LZMA
[ 0x00000000000eca00, 0000000000100000, 0x0000000000100000) <- 00000000fff97c70
dest 000eca00, end 00100000, bouncebuffer 1def0000
Loaded segments
Jumping to boot code at fdfae
entry = 0x000fdfae
lb_start = 0x00100000
lb_size = 0x00080000
adjust = 0x1de70000
buffer = 0x1def0000
elf_boot_notes = 0x00118ab0
adjusted_boot_notes = 0x1df88ab0

It goes well through the boot to the payload!. Now the little detail is to make the patch more clean and also somehow handle the SMP so other CPUs do not mess with the card at the same time.

I was wondering also about some option ROM similar to sgabios which could transfer the console over network maybe idea for the kind reader? 😉

PS: This is my first blog post ever, please let me know what I can do better. Or should it be make better? Oh well…

3 thoughts on “Coreboot console over Ethernet”

  1. This is greatstuff, and we must consolidate such alternate ways of getting debug data, expecially now that serial ports are slow and getting obsoleted by the manufacturers, USB2’s EHCI debug port needs additional not-so-cheap adapter hardware, and the future’s not so bright since USB3’s xHCI won’t work unless RAM is initialized so it’s a no-go for coreboot development.

Comments are closed.