diff --git a/reactos/ntoskrnl/ex/hdlsterm.c b/reactos/ntoskrnl/ex/hdlsterm.c index ed857f4a69d..c36b0584b01 100644 --- a/reactos/ntoskrnl/ex/hdlsterm.c +++ b/reactos/ntoskrnl/ex/hdlsterm.c @@ -1,9 +1,9 @@ /* * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory + * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: ntoskrnl/ex/hdlsterm.c * PURPOSE: Headless Terminal Support - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * PROGRAMMERS: ReactOS Portable Systems Group */ /* INCLUDES ******************************************************************/ @@ -13,20 +13,127 @@ /* GLOBALS *******************************************************************/ +PHEADLESS_GLOBALS HeadlessGlobals; + /* FUNCTIONS *****************************************************************/ VOID NTAPI -HeadlessInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +HdlspSendStringAtBaud( + IN PCHAR String + ) { - PHEADLESS_LOADER_BLOCK HeadlessBlock; + /* Send every byte */ + while (*String++ != ANSI_NULL) + { + InbvPortPutByte(HeadlessGlobals->TerminalPort, *String); + } +} - /* Get the headless loader block */ - HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock; - if (HeadlessBlock) - { - DPRINT1("ReactOS does not currently have Headless Terminal support!\n"); - } +NTSTATUS +NTAPI +HdlspEnableTerminal( + IN BOOLEAN Enable + ) +{ + /* Enable if requested, as long as this isn't a PCI serial port crashing */ + if ((Enable) && + !(HeadlessGlobals->TerminalEnabled) && + !((HeadlessGlobals->IsMMIODevice) && (HeadlessGlobals->InBugCheck))) + { + /* Initialize the COM port with cportlib */ + HeadlessGlobals->TerminalEnabled = InbvPortInitialize( + HeadlessGlobals->TerminalBaudRate, + HeadlessGlobals->TerminalPortNumber, + HeadlessGlobals->TerminalPortAddress, + &HeadlessGlobals->TerminalPort, + HeadlessGlobals->IsMMIODevice); + if (!HeadlessGlobals->TerminalEnabled) return STATUS_UNSUCCESSFUL; + + /* Cleanup the screen and reset the cursor */ + HdlspSendStringAtBaud("\x1B[2J"); + HdlspSendStringAtBaud("\x1B[H"); + + /* Enable FIFO */ + InbvPortEnableFifo(HeadlessGlobals->TerminalPort, TRUE); + } + else if (!Enable) + { + /* Specific case when headless is being disabled */ + InbvPortTerminate(HeadlessGlobals->TerminalPort); + HeadlessGlobals->TerminalPort = 0; + HeadlessGlobals->TerminalEnabled = FALSE; + } + return STATUS_SUCCESS; +} + +VOID +NTAPI +HeadlessInit( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + PHEADLESS_LOADER_BLOCK HeadlessBlock; + + HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock; + if (!HeadlessBlock) return; + if ((HeadlessBlock->PortNumber > 4) && (HeadlessBlock->UsedBiosSettings)) return; + + HeadlessGlobals = ExAllocatePoolWithTag( + NonPagedPool, + sizeof(HEADLESS_GLOBALS), + 'sldH'); + if (!HeadlessGlobals) return; + + /* Zero and copy loader data */ + RtlZeroMemory(HeadlessGlobals, sizeof(HEADLESS_GLOBALS)); + HeadlessGlobals->TerminalPortNumber = HeadlessBlock->PortNumber; + HeadlessGlobals->TerminalPortAddress = HeadlessBlock->PortAddress; + HeadlessGlobals->TerminalBaudRate = HeadlessBlock->BaudRate; + HeadlessGlobals->TerminalParity = HeadlessBlock->Parity; + HeadlessGlobals->TerminalStopBits = HeadlessBlock->StopBits; + HeadlessGlobals->UsedBiosSettings = HeadlessBlock->UsedBiosSettings; + HeadlessGlobals->IsMMIODevice = HeadlessBlock->IsMMIODevice; + HeadlessGlobals->TerminalType = HeadlessBlock->TerminalType; + HeadlessGlobals->SystemGUID = HeadlessBlock->SystemGUID; + + /* These two are opposites of each other */ + if (HeadlessGlobals->IsMMIODevice) HeadlessGlobals->IsNonLegacyDevice = TRUE; + + /* Check for a PCI device, warn that this isn't supported */ + if (HeadlessBlock->PciDeviceId != PCI_INVALID_VENDORID) + { + DPRINT1("PCI Serial Ports not supported\n"); + } + + /* Log entries are not yet supported */ + DPRINT1("FIXME: No Headless logging support\n"); + + /* Windows seems to apply some special hacks for 9600 bps */ + if (HeadlessGlobals->TerminalBaudRate == 9600) + { + DPRINT1("Please use other baud rate than 9600bps for now\n"); + } + + /* Enable the terminal */ + HdlspEnableTerminal(TRUE); +} + +/* + * @unimplemented + */ +NTSTATUS +NTAPI +HeadlessDispatch( + IN HEADLESS_CMD Command, + IN PVOID InputBuffer, + IN SIZE_T InputBufferSize, + OUT PVOID OutputBuffer, + OUT PSIZE_T OutputBufferSize + ) +{ + //UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } /* EOF */ diff --git a/reactos/ntoskrnl/inbv/inbv.c b/reactos/ntoskrnl/inbv/inbv.c index cdae54a32f6..a324fadfe95 100644 --- a/reactos/ntoskrnl/inbv/inbv.c +++ b/reactos/ntoskrnl/inbv/inbv.c @@ -259,8 +259,13 @@ InbvDisplayString(IN PCHAR String) /* Make sure we're installed and display the string */ if (InbvBootDriverInstalled) VidDisplayString((PUCHAR) String); - /* Call Headless (We don't support headless for now) - HeadlessDispatch(DISPLAY_STRING); */ + /* Print the string on the EMS port */ + HeadlessDispatch( + HeadlessCmdPutString, + String, + strlen(String) + sizeof(ANSI_NULL), + NULL, + NULL); /* Release the lock */ InbvReleaseLock(); diff --git a/reactos/ntoskrnl/inbv/inbvport.c b/reactos/ntoskrnl/inbv/inbvport.c new file mode 100644 index 00000000000..839d6fe9779 --- /dev/null +++ b/reactos/ntoskrnl/inbv/inbvport.c @@ -0,0 +1,121 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/inbv/inbvport.c + * PURPOSE: Serial Port Boot Driver for Headless Terminal Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* GLOBALS *******************************************************************/ + +CPPORT Port[4] = +{ + {NULL, 0, TRUE}, + {NULL, 0, TRUE}, + {NULL, 0, TRUE}, + {NULL, 0, TRUE} +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +InbvPortEnableFifo( + IN ULONG PortId, + IN BOOLEAN Enable + ) +{ + /* Set FIFO as requested */ + CpEnableFifo(Port[PortId].Address, Enable); +} + +VOID +NTAPI +InbvPortPutByte( + IN ULONG PortId, + IN BOOLEAN Output + ) +{ + /* Send the byte */ + CpPutByte(&Port[PortId], Output); +} + +VOID +NTAPI +InbvPortTerminate( + IN ULONG PortId + ) +{ + /* The port is now available */ + Port[PortId].Address = NULL; +} + +BOOLEAN +NTAPI +InbvPortInitialize( + IN ULONG BaudRate, + IN ULONG PortNumber, + IN PUCHAR PortAddress, + OUT PULONG PortId, + IN BOOLEAN IsMMIODevice + ) +{ + /* Not yet supported */ + ASSERT(IsMMIODevice == FALSE); + + /* Set default baud rate */ + if (BaudRate == 0) BaudRate = 19200; + + /* Check if port or address given */ + if (PortNumber) + { + /* Pick correct address for port */ + if (!PortAddress) + { + switch (PortNumber) + { + case 1: + PortAddress = (PUCHAR)0x3F8; + break; + + case 2: + PortAddress = (PUCHAR)0x2F8; + break; + + case 3: + PortAddress = (PUCHAR)0x3E8; + break; + + default: + PortNumber = 4; + PortAddress = (PUCHAR)0x2E8; + } + } + } + else + { + /* Pick correct port for address */ + PortAddress = (PUCHAR)0x2F8; + if (CpDoesPortExist(PortAddress)) + { + PortNumber = 2; + } + else + { + PortAddress = (PUCHAR)0x3F8; + if (!CpDoesPortExist(PortAddress)) return FALSE; + PortNumber = 1; + } + } + + /* Initialize the port unless it's already up, and then return it */ + if (Port[PortNumber - 1].Address) return FALSE; + CpInitialize(&Port[PortNumber - 1], PortAddress, BaudRate); + *PortId = PortNumber - 1; + return TRUE; +} diff --git a/reactos/ntoskrnl/include/internal/hdl.h b/reactos/ntoskrnl/include/internal/hdl.h new file mode 100644 index 00000000000..5afd40fa6d0 --- /dev/null +++ b/reactos/ntoskrnl/include/internal/hdl.h @@ -0,0 +1,144 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/include/internal/hdl.h + * PURPOSE: Internal header for the Configuration Manager + * PROGRAMMERS: ReactOS Portable Systems Group + */ +#define _HDL_ +#include + +// +// Define this if you want debugging support +// +#define _HDL_DEBUG_ 0x00 + +// +// These define the Debug Masks Supported +// +#define HDL_XXX_DEBUG 0x01 + +// +// Debug/Tracing support +// +#if _HDL_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define HDLTRACE DbgPrintEx +#else +#define HDLTRACE(x, ...) \ + if (x & HdlpTraceLevel) DbgPrint(__VA_ARGS__) +#endif +#else +#define HDLTRACE(x, ...) DPRINT(__VA_ARGS__) +#endif + +// +// Headless Log Entry +// +typedef struct _HEADLESS_LOG_ENTRY +{ + SYSTEM_TIMEOFDAY_INFORMATION TimeOfEntry; + PWCHAR String; +} HEADLESS_LOG_ENTRY, *PHEADLESS_LOG_ENTRY; + +// +// Headless Bugcheck Information +// +typedef struct _HEADLESS_BLUE_SCREEN_DATA +{ + PUCHAR Property; + PUCHAR XMLData; + struct _HEADLESS_BLUE_SCREEN_DATA *Next; +} HEADLESS_BLUE_SCREEN_DATA, * PHEADLESS_BLUE_SCREEN_DATA; + +// +// Headless Control Structure, mostly for !SAC +// +typedef struct _HEADLESS_GLOBALS +{ + KSPIN_LOCK SpinLock; + HANDLE PageLockHandle; + PHEADLESS_LOG_ENTRY LogEntries; + PUCHAR TmpBuffer; + PUCHAR InputBuffer; + PHEADLESS_BLUE_SCREEN_DATA BlueScreenData; + union + { + struct + { + ULONG TerminalEnabled:1; + ULONG InBugCheck:1; + ULONG NewLogEntryAdded:1; + ULONG UsedBiosSettings:1; + ULONG InputProcessing:1; + ULONG InputLineDone:1; + ULONG ProcessingCmd:1; + ULONG TerminalParity:1; + ULONG TerminalStopBits:1; + ULONG TerminalPortNumber:3; + ULONG IsNonLegacyDevice:1; + }; + ULONG AllFlags; + }; + ULONG TerminalBaudRate; + ULONG TerminalPort; + PUCHAR TerminalPortAddress; + LARGE_INTEGER DelayTime; + ULONG MicroSecondsDelayTime; + UCHAR TerminalType; + SIZE_T InputBufferIndex; + USHORT LogEntryLast; + USHORT LogEntryStart; + GUID SystemGUID; + BOOLEAN IsMMIODevice; + BOOLEAN IsLastCharCR; +} HEADLESS_GLOBALS, *PHEADLESS_GLOBALS; + +// +// FIXME: A public header in the NDK? Ask Alex +// +typedef enum _HEADLESS_CMD +{ + HeadlessCmdEnableTerminal = 1, + HeadlessCmdCheckForReboot, + HeadlessCmdPutString, + HeadlessCmdClearDisplay, + HeadlessCmdClearToEndOfDisplay, + HeadlessCmdClearToEndOfLine, + HeadlessCmdDisplayAttributesOff, + HeadlessCmdDisplayInverseVideo, + HeadlessCmdSetColor, + HeadlessCmdPositionCursor, + HeadlessCmdTerminalPoll, + HeadlessCmdGetByte, + HeadlessCmdGetLine, + HeadlessCmdStartBugCheck, + HeadlessCmdDoBugCheckProcessing, + HeadlessCmdQueryInformation, + HeadlessCmdAddLogEntry, + HeadlessCmdDisplayLog, + HeadlessCmdSetBlueScreenData, + HeadlessCmdSendBlueScreenData, + HeadlessCmdQueryGUID, + HeadlessCmdPutData +} HEADLESS_CMD, *PHEADLESS_CMD; + +NTSTATUS +NTAPI +HeadlessDispatch( + IN HEADLESS_CMD Command, + IN PVOID InputBuffer, + IN SIZE_T InputBufferSize, + OUT PVOID OutputBuffer, + OUT PSIZE_T OutputBufferSize +); + +// +// Global variables accessible from all of Hdl +// +extern PHEADLESS_GLOBALS HeadlessGlobals; + +// +// Inlined functions +// +//#include "hdl_x.h" diff --git a/reactos/ntoskrnl/include/internal/inbv.h b/reactos/ntoskrnl/include/internal/inbv.h index eb87f83e216..9d9e737e690 100644 --- a/reactos/ntoskrnl/include/internal/inbv.h +++ b/reactos/ntoskrnl/include/internal/inbv.h @@ -71,4 +71,34 @@ InbvIndicateProgress( VOID ); +VOID +NTAPI +InbvPortEnableFifo( + IN ULONG PortId, + IN BOOLEAN Enable +); + +VOID +NTAPI +InbvPortPutByte( + IN ULONG PortId, + IN BOOLEAN Output +); + +VOID +NTAPI +InbvPortTerminate( + IN ULONG PortId +); + +BOOLEAN +NTAPI +InbvPortInitialize( + IN ULONG BaudRate, + IN ULONG PortNumber, + IN PUCHAR PortAddress, + OUT PULONG PortId, + IN BOOLEAN IsMMIODevice +); + extern BOOLEAN InbvBootDriverInstalled; diff --git a/reactos/ntoskrnl/include/internal/ntoskrnl.h b/reactos/ntoskrnl/include/internal/ntoskrnl.h index 004ce9a03ba..f5354eea293 100644 --- a/reactos/ntoskrnl/include/internal/ntoskrnl.h +++ b/reactos/ntoskrnl/include/internal/ntoskrnl.h @@ -88,6 +88,7 @@ #include "inbv.h" #include "vdm.h" #include "hal.h" +#include "hdl.h" #include "arch/intrin_i.h" /* diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index 6b7cc84eca8..2dfca5053de 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -31,6 +31,7 @@ bootvid wdmguid ioevent + cportlib bugcodes ntoskrnl.h @@ -263,6 +264,7 @@ inbv.c + inbvport.c