MBR hack for serial console

remodeler remodeler at alentogroup.org
Wed Aug 26 21:16:59 UTC 2009


I am hoping for input on a patch I want to apply to the MBR of a FreeBSD
8-BETA3 AMD64 server. I need a serial console on this server. The ASUS
motherboard (amibios) has PCI and PCI-e expansion slots, and a Moschip MCS9820
UART (serial board) is installed at pci0:3:5:0. The amibios can be configured
to do the plug-and-play enumeration, or this feature turned off, but there is
no way to assign a particular i/o port to a PCI device in the BIOS, and I
cannot get source for the BIOS to change this behavior. The serial board has a
single Base Address Register at 10h in its pci configuration space. Whether
the PCI bus is probed by the BIOS or FreeBSD, the UART BAR is assigned the
i386 I/O port address of 0xe800. It must be COM1-COM4 (i.e. 0x3F8) to work in
the boot sequence. I need access to the serial console before loader.

I do not expect the hardware configuration to change so a hack is ok. My plan
is to patch the MBR to override the serial card's BAR with 0x3F8. My reasoning
is that the CPU is still in Real mode (allowing direct hardware access) until
loader executes, and the serial console would work for the boot0 and boot2
calls to the terminal. I have experimented with using pciconf to change the
BAR from a command line; curiously the command:

 pciconf -w pci0:3:5:0 16 1016

loads 0x3F9 into the serial card's PCI configuration space instead of 0x3F8,
and I don't understand why. I've worked up this patch and hope someone can
tell me why this would or wouldn't work:

/usr/src/sys/boot/i386/mbr/mbr.s

41,57d40
< # Patch to reconfigure PCI UART's Base Address to COM1
< # I count 40 bytes in opcode                          
< #                                                    
< startcon:     .set PCIADD_PORT,0xcf8          # Load pci config port addy
<               .set PCIDATA_PORT,0xcfc         # Load pci data port addy  
<               .set PCIADD,0x8003e810          # Load pci register identifier
<               .set PCIDATA,0x3f8              # Load pci register data      
<
<               pushad                          # save double registers
<               mov %ax,$PCIADD                 # put pci reg to access in ax
<               mov %dx,$PCIADD_PORT            # put pci config port in dx
<               out %dx,%ax                     # send to cpu i/o space
<               mov %ax,$PCIDATA                # put pci data in ax
<               mov %dx,$PCIDATA_PORT           # put pci data port in dx
<               out %dx,%ax                     # send data to cpu i/o space
<               popad                           # pop saved registers
< #
166,171c149,151
< #
< # Instruction messages reduced to numbers, saves 60 bytes
< #
< msg_pt:       .asciz "1"                      # "Invalid partition table"
< msg_rd:       .asciz "2"                      # "Error loading operating system"
< msg_os:       .asciz "3"                      # "Missing operating system"
---
> msg_pt:       .asciz "Invalid partition table"
> msg_rd:       .asciz "Error loading operating system"
> msg_os:       .asciz "Missing operating system"

Thanks in advance for any help. I am not an assembly coder so am really
uncertain about my patch.


More information about the freebsd-hackers mailing list