From 7497b81e5bd8ca2725ed274b20422414e549f9ee Mon Sep 17 00:00:00 2001 From: Stanislav Motylkov Date: Fri, 16 Aug 2019 21:00:25 +0300 Subject: [PATCH] [FREELDR] Add Serial ports detection in DetectIsaBios() (#1829) CORE-16216 --- boot/freeldr/freeldr/arch/i386/machpc.c | 40 +++++++++------- boot/freeldr/freeldr/arch/i386/machxbox.c | 48 +++++++++++++++++++ .../freeldr/include/arch/i386/machxbox.h | 15 ++++++ .../freeldr/include/arch/pc/hardware.h | 4 ++ 4 files changed, 91 insertions(+), 16 deletions(-) diff --git a/boot/freeldr/freeldr/arch/i386/machpc.c b/boot/freeldr/freeldr/arch/i386/machpc.c index ede5441dfae..1929be4a93e 100644 --- a/boot/freeldr/freeldr/arch/i386/machpc.c +++ b/boot/freeldr/freeldr/arch/i386/machpc.c @@ -636,17 +636,32 @@ DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, } } -static +ULONG +PcGetSerialPort(ULONG Index, PULONG Irq) +{ + static const ULONG PcIrq[MAX_COM_PORTS] = {4, 3, 4, 3}; + PUSHORT BasePtr; + + /* + * The BIOS data area 0x400 holds the address of the first valid COM port. + * Each COM port address is stored in a 2-byte field. + * Infos at: http://www.bioscentral.com/misc/bda.htm + */ + BasePtr = (PUSHORT)0x400; + *Irq = PcIrq[Index]; + + return (ULONG) *(BasePtr + Index); +} + VOID -DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey) +DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count) { PCM_PARTIAL_RESOURCE_LIST PartialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_SERIAL_DEVICE_DATA SerialDeviceData; - ULONG Irq[MAX_COM_PORTS] = {4, 3, 4, 3}; + ULONG Irq; ULONG Base; CHAR Buffer[80]; - PUSHORT BasePtr; ULONG ControllerNumber = 0; PCONFIGURATION_COMPONENT_DATA ControllerKey; ULONG i; @@ -654,16 +669,9 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey) TRACE("DetectSerialPorts()\n"); - /* - * The BIOS data area 0x400 holds the address of the first valid COM port. - * Each COM port address is stored in a 2-byte field. - * Infos at: http://www.bioscentral.com/misc/bda.htm - */ - BasePtr = (PUSHORT)0x400; - - for (i = 0; i < MAX_COM_PORTS; i++, BasePtr++) + for (i = 0; i < Count; i++) { - Base = (ULONG) * BasePtr; + Base = MachGetSerialPort(i, &Irq); if ((Base == 0) || !CpDoesPortExist(UlongToPtr(Base))) continue; @@ -703,8 +711,8 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey) PartialDescriptor->Type = CmResourceTypeInterrupt; PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = Irq[i]; - PartialDescriptor->u.Interrupt.Vector = Irq[i]; + PartialDescriptor->u.Interrupt.Level = Irq; + PartialDescriptor->u.Interrupt.Vector = Irq; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; /* Set serial data (device specific) */ @@ -1319,7 +1327,7 @@ DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) /* Detect ISA/BIOS devices */ DetectBiosDisks(SystemKey, BusKey); - DetectSerialPorts(BusKey); + DetectSerialPorts(BusKey, PcGetSerialPort, MAX_COM_PORTS); DetectParallelPorts(BusKey); DetectKeyboardController(BusKey); DetectPS2Mouse(BusKey); diff --git a/boot/freeldr/freeldr/arch/i386/machxbox.c b/boot/freeldr/freeldr/arch/i386/machxbox.c index 4b96228f1cf..b3cd4f5616e 100644 --- a/boot/freeldr/freeldr/arch/i386/machxbox.c +++ b/boot/freeldr/freeldr/arch/i386/machxbox.c @@ -35,6 +35,53 @@ XboxFindPciBios(PPCI_REGISTRY_INFO BusData) return TRUE; } +extern +VOID +DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, PUCHAR Base); + +static +ULONG +XboxGetSerialPort(ULONG Index, PULONG Irq) +{ + /* + * Xbox may have maximum two Serial COM ports + * if the Super I/O chip is connected via LPC + */ + static const UCHAR Device[MAX_XBOX_COM_PORTS] = {LPC_DEVICE_SERIAL_PORT_1, LPC_DEVICE_SERIAL_PORT_2}; + ULONG ComBase = 0; + + // Enter Configuration + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_ENTER_CONFIG_KEY); + + // Select serial device + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_NUMBER); + WRITE_PORT_UCHAR(LPC_IO_BASE + 1, Device[Index]); + + // Check if selected device is active + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_ACTIVATE); + if (READ_PORT_UCHAR(LPC_IO_BASE + 1) == 1) + { + // Read LSB + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW); + ComBase = READ_PORT_UCHAR(LPC_IO_BASE + 1); + // Read MSB + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH); + ComBase |= (READ_PORT_UCHAR(LPC_IO_BASE + 1) << 8); + // Read IRQ + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_INTERRUPT); + *Irq = READ_PORT_UCHAR(LPC_IO_BASE + 1); + } + + // Exit Configuration + WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_EXIT_CONFIG_KEY); + + return ComBase; +} + +extern +VOID +DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count); + VOID XboxGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize) { @@ -155,6 +202,7 @@ DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) /* Detect ISA/BIOS devices */ DetectBiosDisks(SystemKey, BusKey); + DetectSerialPorts(BusKey, XboxGetSerialPort, MAX_XBOX_COM_PORTS); /* FIXME: Detect more ISA devices */ } diff --git a/boot/freeldr/freeldr/include/arch/i386/machxbox.h b/boot/freeldr/freeldr/include/arch/i386/machxbox.h index d1c42a40bae..f481bbde8f9 100644 --- a/boot/freeldr/freeldr/include/arch/i386/machxbox.h +++ b/boot/freeldr/freeldr/include/arch/i386/machxbox.h @@ -22,6 +22,21 @@ #include "mm.h" #endif +#define MAX_XBOX_COM_PORTS 2 + +#define LPC_IO_BASE 0x2E +#define LPC_ENTER_CONFIG_KEY 0x55 +#define LPC_EXIT_CONFIG_KEY 0xAA + +#define LPC_DEVICE_SERIAL_PORT_1 0x4 +#define LPC_DEVICE_SERIAL_PORT_2 0x5 + +#define LPC_CONFIG_DEVICE_NUMBER 0x07 +#define LPC_CONFIG_DEVICE_ACTIVATE 0x30 +#define LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH 0x60 +#define LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW 0x61 +#define LPC_CONFIG_DEVICE_INTERRUPT 0x70 + extern UCHAR XboxFont8x16[256 * 16]; VOID XboxMachInit(const char *CmdLine); diff --git a/boot/freeldr/freeldr/include/arch/pc/hardware.h b/boot/freeldr/freeldr/include/arch/pc/hardware.h index bc6aad11971..56e6028ed06 100644 --- a/boot/freeldr/freeldr/include/arch/pc/hardware.h +++ b/boot/freeldr/freeldr/include/arch/pc/hardware.h @@ -44,6 +44,10 @@ BOOLEAN extern FIND_PCI_BIOS FindPciBios; +typedef +ULONG +(*GET_SERIAL_PORT)(ULONG Index, PULONG Irq); + VOID DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey, PCONFIGURATION_COMPONENT_DATA BusKey); -- 2.17.1