Oliver Mangold
2016-Oct-09 11:25 UTC
[syslinux] Enumeration of ISA serial ports inconsistent between Linux and Syslinux
Hi, I would like to point out an issue with the enumeration of ISA serial devices in Syslinux. If I interpret the snippet below correctly, Syslinux looks up the device order with the BIOS, while Linux uses the fixed order 3F8,2F8,3E8,2E8. Note that this inconsistency is a real problem, as some motherboards (like e.g. a Supermicro X10DRi with default BIOS settings) have a different order stored in BIOS: --- # hexdump -s 0x400 -n 8 /dev/mem 0000400 02f8 03f8 0000 0000 --- Best regards, Oliver --- /syslinux/core/include/bios.h --- #define SERIAL_BASE 0x0400 /* Base address for 4 serial ports */ ... static inline uint16_t get_serial_port(uint16_t port) { /* Magic array in BIOS memory, contains four entries */ const uint16_t * const serial_ports = (const uint16_t *)SERIAL_BASE; /* * If port > 3 then the port is simply the I/O base address */ if (port > 3) return port; /* Get the I/O port from the BIOS */ return serial_ports[port]; } ---
Gene Cumm
2016-Oct-09 12:49 UTC
[syslinux] Enumeration of ISA serial ports inconsistent between Linux and Syslinux
On Sun, Oct 9, 2016 at 7:25 AM, Oliver Mangold via Syslinux <syslinux at zytor.com> wrote:> Hi, > > I would like to point out an issue with the enumeration of ISA serial > devices in Syslinux. If I interpret the snippet below correctly, Syslinux > looks up the device order with the BIOS, while Linux uses the fixed order > 3F8,2F8,3E8,2E8. > > Note that this inconsistency is a real problem, as some motherboards (like > e.g. a Supermicro X10DRi with default BIOS settings) have a different order > stored in BIOS: > > --- > # hexdump -s 0x400 -n 8 /dev/mem > 0000400 02f8 03f8 0000 0000 > --- > > > Best regards, > > Oliver > > --- /syslinux/core/include/bios.h --- > #define SERIAL_BASE 0x0400 /* Base address for 4 serial ports */ > ... > static inline uint16_t get_serial_port(uint16_t port) > { > /* Magic array in BIOS memory, contains four entries */ > const uint16_t * const serial_ports = (const uint16_t *)SERIAL_BASE; > > /* > * If port > 3 then the port is simply the I/O base address > */ > if (port > 3) > return port; > > /* Get the I/O port from the BIOS */ > return serial_ports[port]; > } > ---Excellent job digging up the differences. Looks like the code comes from commit ID c4fa331 but is much older. The code comes from 7916325 which is derived from the ASM in beaaa4f. It appears to me that it was used to check the presence of a serial port and it was assumed the order at that memory address would be consistent and either the proper value or 0. I'm trying to dig for some documentation like Ralph Brown's Interrupt list. Have you checked for firmware updates? Have you tried experimenting with redoing what serial port is assigned what IO base address to make it consistent between Syslinux and Linux? Alternatively, have you considered specifying the full IO address instead of the low number (like "0x3F8")? -- -Gene
Gene Cumm
2016-Oct-09 13:21 UTC
[syslinux] Enumeration of ISA serial ports inconsistent between Linux and Syslinux
On Sun, Oct 9, 2016 at 8:49 AM, Gene Cumm <gene.cumm at gmail.com> wrote:> On Sun, Oct 9, 2016 at 7:25 AM, Oliver Mangold via Syslinux > <syslinux at zytor.com> wrote: >> Hi, >> >> I would like to point out an issue with the enumeration of ISA serial >> devices in Syslinux. If I interpret the snippet below correctly, Syslinux >> looks up the device order with the BIOS, while Linux uses the fixed order >> 3F8,2F8,3E8,2E8. >> >> Note that this inconsistency is a real problem, as some motherboards (like >> e.g. a Supermicro X10DRi with default BIOS settings) have a different order >> stored in BIOS: >> >> --- >> # hexdump -s 0x400 -n 8 /dev/mem >> 0000400 02f8 03f8 0000 0000 >> --- >> >> >> Best regards, >> >> Oliver >> >> --- /syslinux/core/include/bios.h --- >> #define SERIAL_BASE 0x0400 /* Base address for 4 serial ports */ >> ... >> static inline uint16_t get_serial_port(uint16_t port) >> { >> /* Magic array in BIOS memory, contains four entries */ >> const uint16_t * const serial_ports = (const uint16_t *)SERIAL_BASE; >> >> /* >> * If port > 3 then the port is simply the I/O base address >> */ >> if (port > 3) >> return port; >> >> /* Get the I/O port from the BIOS */ >> return serial_ports[port]; >> } >> --- > > Excellent job digging up the differences. Looks like the code comes > from commit ID c4fa331 but is much older. The code comes from 7916325 > which is derived from the ASM in beaaa4f. It appears to me that it > was used to check the presence of a serial port and it was assumed the > order at that memory address would be consistent and either the proper > value or 0. > > I'm trying to dig for some documentation like Ralph Brown's Interrupt > list. Have you checked for firmware updates? Have you tried > experimenting with redoing what serial port is assigned what IO base > address to make it consistent between Syslinux and Linux? > > Alternatively, have you considered specifying the full IO address > instead of the low number (like "0x3F8")?RBIL MEMORY.LST release 61 starting at line 31: --------S-M00400000-------------------------- MEM 0040h:0000h - BASE I/O ADDRESS OF FIRST SERIAL I/O PORT Size: WORD Notes: the BIOS sets this word to zero if is unable to find any serial ports at the addresses it is programmed to check at boot DOS and BIOS serial device numbers may be redefined by re-assigning these values of the base I/O addresses stored here So the behavior of Syslinux makes sense since the sequence numbers can be re-assigned by the firmware (in this case, the CSM of the EFI firmware) by moving the values around. My inclination would be to use the IO address instead of the sequence number for your desired behavior (as I just suggested). I'd still consider checking for EFI firmware updates and perhaps reporting the issue to the vendor (in this case, Supermicro). HPA, any opinions? -- -Gene
Oliver Mangold
2016-Oct-09 14:04 UTC
[syslinux] Enumeration of ISA serial ports inconsistent between Linux and Syslinux
On 09.10.2016 14:49, Gene Cumm wrote:> Excellent job digging up the differences. Looks like the code comes > from commit ID c4fa331 but is much older. The code comes from 7916325 > which is derived from the ASM in beaaa4f. It appears to me that it > was used to check the presence of a serial port and it was assumed the > order at that memory address would be consistent and either the proper > value or 0. > > I'm trying to dig for some documentation like Ralph Brown's Interrupt > list. Have you checked for firmware updates? Have you tried > experimenting with redoing what serial port is assigned what IO base > address to make it consistent between Syslinux and Linux? > > Alternatively, have you considered specifying the full IO address > instead of the low number (like "0x3F8")? > >Hi, actually I didn't do much with Syslinux myself. I found the issue with Grub2 first, and after I brief exchange about it on the Linux-Serial mailing list I decided to look up how Syslinux handles this, and found it has the same problem as Grub2. So I decided to do a good deed and report it to you, too :) As I understand the Supermicro BIOS, the issue could be fixed in the BIOS settings, by manually changing the ports to the default (Linux) order. Nonetheless the vendor default seems to be COM0=2f8, COM1=3f8. I don't have enough different boards to play with to give you an accurate answer on which SM boards/firmware revisions are affected, but it isn't the first time I have seen something like this.> RBIL MEMORY.LST release 61 starting at line 31: > > --------S-M00400000-------------------------- > MEM 0040h:0000h - BASE I/O ADDRESS OF FIRST SERIAL I/O PORT > Size: WORD > Notes: the BIOS sets this word to zero if is unable to find any serial ports > at the addresses it is programmed to check at boot > DOS and BIOS serial device numbers may be redefined by re-assigning > these values of the base I/O addresses stored here > > > > So the behavior of Syslinux makes sense since the sequence numbers can > be re-assigned by the firmware (in this case, the CSM of the EFI > firmware) by moving the values around.I'm quite aware of this, and I would even tend to agree with you that this behavior makes sense. Unfortunately it seems, though, that both Linux and OpenBSD use the traditional static ordering without looking at the BIOS info, and at least for Linux I get the impression that it is quite unlikely that this will change anytime soon. Here is the thread I started on Linux-Serial, in case you want to read Greg's answer for yourself: http://www.spinics.net/lists/linux-serial/msg23997.html I don't want to stir up any complicated discussion about who is right and who is wrong, but as a user I would prefer the behavior to be consistent between all OSes and bootloaders. Best regards, Oliver
Apparently Analagous Threads
- Enumeration of ISA serial ports inconsistent between Linux and Syslinux
- Enumeration of ISA serial ports inconsistent between Linux and Syslinux
- Enumeration of ISA serial ports inconsistent between Linux and Syslinux
- [PATCH 1/4] purgatory: put variables altered by kexec in .data not .bss
- [PATCH RFC 0/8] xen/arm: initial cubieboard2 support.