Serial console on a motherboard with no serial ports

Hello,

I have a motherboard without serial ports and I wonder whether it is possible to get a serial console (server side) on it with a PCIe RS232 card or a USB-to-RS232 adapter. So far I had no luck. I can get a console that works once the system finished booting (once getty process start as per /etc/ttys). But what I really need is a console to interact with loader, get kernel messages and interact in single user mode. I don't think this is supported with USB device (happy to be corrected here) but I was hoping that PCIe card will work.

I have in my /boot/loader.conf
Code:
boot_serial="YES"
console="comconsole"

The card I have:

Code:
uart0@pci0:1:0:0:    class=0x070002 rev=0x00 hdr=0x00 vendor=0x125b device=0x9100 subvendor=0xa000 subdevice=0x1000
    vendor     = 'Asix Electronics Corporation'
    device     = 'AX99100 PCIe to Multi I/O Controller'
    class      = simple comms
    subclass   = UART
uart1@pci0:1:0:1:    class=0x070002 rev=0x00 hdr=0x00 vendor=0x125b device=0x9100 subvendor=0xa000 subdevice=0x1000
    vendor     = 'Asix Electronics Corporation'
    device     = 'AX99100 PCIe to Multi I/O Controller'
    class      = simple comms
    subclass   = UART

Can be seen during boot as

Code:
uart0: <ASIX AX99100 PCIe 1/2/3/4-port RS-232/422/485> port 0x3010-0x3017 mem 0x70b03000-0x70b03fff,0x70b02000-0x70b02fff at device 0.0 on pci1
uart1: <ASIX AX99100 PCIe 1/2/3/4-port RS-232/422/485> port 0x3000-0x3007 mem 0x70b01000-0x70b01fff,0x70b00000-0x70b00fff at device 0.1 on pci1

I tried adding
Code:
hint.uart.0.at="pci0:1:0:0"
hint.uart.0.flags="0x10"
to /boot/device.hints but flags still does not appear in the boot entries above. With boot_serial="YES"/console="comconsole" in the loader.conf console disappears from HDMI output until the boot finishes, but still does not appear on the serial port.

Has anyone ever managed to get something like this to work? I will appreciate any suggestions!
 
So... No responses. I guess I'm either asking something stupid or something very boring. And it also seems not possible. A short recap for anyone who might be looking for the same.

According to loader(8) (or loader_simp(8) in FreeBSD 14) PCIe card is supposed to work with comconsole_pcidev="bus:device:function" except that this appears to be unsupported in EFI mode (https://cgit.freebsd.org/src/tree/stand/i386/libi386/comconsole.c#n218).

I managed to get loader prompt on serial console with EFI drivers by loading TerminalDxe.efi and PciSioSerialDxe.efi (from EDK 2). However this won't work much further than loader prompt.

So I suppose I have to live without console for now and hopefully I'll be able to replace the motherboard later.
 
I guess I'm either asking something stupid or something very boring.
No as dumb as it may seem. FreeBSD has no working PCIe Serial Cards. You must compile driver.

So FreeBSD "The Power To Serve" anything except a serial port server!

 
No as dumb as it may seem. FreeBSD has no working PCIe Serial Cards. You must compile driver.

So FreeBSD "The Power To Serve" anything except a serial port server!


Hold on a sec. I have a 16x serial card that I am pretty sure I used under FreeBSD.
 
FreeBSD has no working PCIe Serial Cards.

Depends on how "working" is defined. The card I have (see identification above, labeled as "Digitus DS-30000-1") works perfectly once the system has finished booting. No need to compile any extra drivers. However my primary interest is in getting a console for loader, kernel boot messages and single user mode. And this is where the problem is. Loader and kernel expect a card that work via I/O ports, but my card is memory mapped. I have tried adding
Code:
hw.uart.console="mm:0x70b02000"
to /boot/loader.conf but that didn't work for me. I have also tried (as mentioned above)
Code:
comconsole_pcidev="1:0:0"
. But trying to assign this in the loader gives an error. I think this is because in EFI
Code:
comconsole_pcidev
is not supported.
 
So... No responses. I guess I'm either asking something stupid or something very boring.
Or something difficult. If you want to see something on a serial before the kernel is fully loaded, you cannot use the kernel device drivers and facilities. You can only use what is either present in the BIOS, or coded into the loader.
Neither the BIOS nor the loader has any reason to talk to an USB-embedded serial and convert it to a system COM3.
I have also not yet seem a BIOS that would be able to find these puc or whatever PCIe cards and convert such to a COM3, so probably the loader would need to do that low-level without using BIOS interrupts. Ugly...

The reason why nobody cares about this is, it doesn't help you much. With such a feature you could handle the kernel boot from the beginning, and maybe parts of the loader dialogue. But that's not what one usually wants - one wants to talk to the BIOS as well.
And the BIOS does such things usually with IPMI/BMC. That is, the BIOS uses a network interface for some emulated serial protocol and pushes it's dialogues onto that, and then hands this channel up to the booting OS as a virtual system console. Then anybody on the network can use a proper client to interface that, and no need for serial wiring.
 
try setting console="EFI" if efi supports the device
I must say a huge thank you! While setting console="EFI" in /boot/loader.conf didn't work (output stopped on "EFI framebuffer information"), it encouraged me to give it one more try and surprisingly it eventually worked!

I wanted to collect the output with console="EFI" and decided to try setting
Code:
hw.uart.console="mm:ADDRESS"
again. For that I checked once again dmesg output to identify memory address and I was surprised to notice the
Code:
port 0x3010-0x3017
part. I can also see it in my original post but I was 100% sure it was originally missing which means that I either missed it or did something (I don't know what) that make it appear there. So in any case, I set hw.uart.console="io:0x3010,br:115200" and now I have serial console! I also have it at the loader prompt with EFI drivers.

Here are full details for anyone who may have to do the same:

There are two parts to this setup:
1. Configure EFI
2. Configure FreeBSD

1. EFI

1.1 Build (no need to install) sysutils/edk2. You will need to specify a FALVOUR, I think any of xen_x64, bhyve or qemu_x64 should produce required files. I was using qemu_x64 for no particular reason:
sudo make FLAVORS="qemu_x64"

1.2 Copy Shell.efi (need to rename this one) and PciSioSerialDxe.efi to /boot/efi:
Code:
cp ./work-qemu_x64/Build/OvmfX64/RELEASE_GCC5/X64/Shell.efi /boot/efi/shellx64.efi
cp ./work-qemu_x64/Build/OvmfX64/RELEASE_GCC5/X64/PciSioSerialDxe.efi /boot/efi/

1.3 Create /boot/efi/startup.nsh:
Code:
fs0:
load terminaldxe.efi pcisioserialdxe.efi
connect -r
setvar ConOutDev =P"/PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Uart(115200,8,N,1)/VenVt100()"
setvar ConInDev =P"/PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Uart(115200,8,N,1)/VenVt100()"
fs0:\efi\boot\bootx64.efi
The values for ConOutDev and ConInDev I found by booting without this commands and inspecting values of corresponding EFI variables using efivar command.

1.4 Add a new boot entry for EFI shell. My BIOS/EFI UI provides an option to launch EFI shell from EFI partition, I used it and then used bcfg boot command to add corresponding boot entry. I think this is also possible with efibootmgr. This is what I currently have there:
Code:
% sudo efibootmgr -v
Boot to FW : false
BootCurrent: 0001
Timeout    : 5 seconds
BootOrder  : 0001, 0005, 0004, 0000
+Boot0001* EFI Shell PciRoot(0x0)/Pci(0x17,0x0)/Sata(0x4,0xffff,0x0)/HD(1,GPT,207c1f24-9feb-11ed-81e8-79f5a4f3e215,0x28,0x82000)/File(\shellx64.efi)
                        ada0p1:/shellx64.efi /boot/efi//shellx64.efi
 Boot0005* UEFI OS HD(1,GPT,207c1f24-9feb-11ed-81e8-79f5a4f3e215,0x28,0x82000)/File(\EFI\BOOT\BOOTX64.EFI)
                      ada0p1:/EFI/BOOT/BOOTX64.EFI /boot/efi//EFI/BOOT/BOOTX64.EFI
 Boot0004* FreeBSD HD(1,GPT,207c1f24-9feb-11ed-81e8-79f5a4f3e215,0x28,0x82000)/File(\efi\freebsd\loader.efi)
                      ada0p1:/efi/freebsd/loader.efi /boot/efi//efi/freebsd/loader.efi
 Boot0000* Winds Boot Manager HD(1,GPT,783ea522-a7a3-4cd9-8284-31e06b37de15,0x800,0x32000)/File(\EFI\MICROSOFT\BOOT\BOOTMGFW.EFI)

This should result in a system which automatically boots FreeBSD via EFI shell with EFI shell loading TerminalDxe.efi PciSioSerialdxe.efi drivers, connects them to relevant devices and setting ConOutDev and ConInDev variables.

2. FreeBSD

Identify the location of the I/O ports by checking the output of dmesg and add
Code:
hw.uart.console="io:0x3010,br:115200"
to /boot/loader.conf. I took the value for io parameter from dmesg | grep uart (make sure to pick the correct port) and I set speed (br: parameter) to 115200 because that's the default in my EFI and it is quite slow anyway. You may also want to set
Code:
beastie_disable="YES"
due to serial console being slow.
 
Or something difficult. If you want to see something on a serial before the kernel is fully loaded, you cannot use the kernel device drivers and facilities. You can only use what is either present in the BIOS, or coded into the loader.
Neither the BIOS nor the loader has any reason to talk to an USB-embedded serial and convert it to a system COM3.
I have also not yet seem a BIOS that would be able to find these puc or whatever PCIe cards and convert such to a COM3, so probably the loader would need to do that low-level without using BIOS interrupts. Ugly...

To be honest I did not expect USB to work (you can see I said this in my original post). I had higher hopes for PCIe devices though. I understand all the problems and complexity arising here however PCI devices appear to be supported (with comconsole_pcidev) only not with EFI. And in fact with EFI I even found EFI driver for FTDI chip which made one of my USB/TTL boards work with loader.

The reason why nobody cares about this is, it doesn't help you much. With such a feature you could handle the kernel boot from the beginning, and maybe parts of the loader dialogue. But that's not what one usually wants - one wants to talk to the BIOS as well.
And the BIOS does such things usually with IPMI/BMC. That is, the BIOS uses a network interface for some emulated serial protocol and pushes it's dialogues onto that, and then hands this channel up to the booting OS as a virtual system console. Then anybody on the network can use a proper client to interface that, and no need for serial wiring.

I'm well aware of a more functional way of getting a full remote console access and advantages of IPMI or even just IP KVM. I certainly cannot speak for everyone but for me this simple serial console while less functional has two adwantages: it is more affordable (also I think a bit more accessible - there are not that many mITX motherboards with IPMI). And it also allows me to capture kernel messages on my backup device (Raspberry PI) so that in the event of a crash I have console logs even if those were not saved anywhere. So far it worked perfect: I have a small home server located in place unsuitable for a monitor and a keyboard. In past 5 years I only needed to access BIOS to make hardware changes in which case I had to disconnect the box and bring it to my desk anyway. But in all other cases when ssh was not available serial console worked perfectly and saved me from having to disconnect and move the box.
 
A small update for anyone repeating my steps. It turned out that neither connect nor both setvar were not needed. At least for me everything works without them. In fact connect started causing issues in loader when I returned server back where it sits and reconnected all devices. Somehow adding connect caused loader to print only ? characters instead of actual output. It looked like it was still sending relevant characters as I could see cursor moving as expected but replaced all of them with question marks.

My startup.nsh currently looks like this:
echo -off
fs0:
load terminaldxe.efi pcisioserialdxe.efi
date
time
echo "Booting fs0:\efi\boot\bootx64.efi in 5 seconds..."
echo "Press Ctrl-C to abort."
echo "Do not use backspace!"
stall 5000000
fs0:\efi\boot\bootx64.efi
 
Back
Top