From b52bd79196866104604c7e930bef2a52c3ee9736 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Wed, 15 Sep 2010 07:46:28 +0000 Subject: [PATCH] Patch by Anton Yarotsky: [NTOSKRNL]: Implement basic Headless support in the kernel. Implement missing InbvPort routines based on WinLdrPort (using cportlib). Add header for Hdl. Terminal initializes now on COM2. Added misisng code to InbvDisplayString to also display on Headless Terminal (requires unimplemented HeadlessDispatch). Next steps are to implement the kernel log buffer, and HeadlessCmdPutString to see boot strings. svn path=/trunk/; revision=48773 --- reactos/ntoskrnl/ex/hdlsterm.c | 129 +++++++++++++++-- reactos/ntoskrnl/inbv/inbv.c | 9 +- reactos/ntoskrnl/inbv/inbvport.c | 121 ++++++++++++++++ reactos/ntoskrnl/include/internal/hdl.h | 144 +++++++++++++++++++ reactos/ntoskrnl/include/internal/inbv.h | 30 ++++ reactos/ntoskrnl/include/internal/ntoskrnl.h | 1 + reactos/ntoskrnl/ntoskrnl-generic.rbuild | 2 + 7 files changed, 423 insertions(+), 13 deletions(-) create mode 100644 reactos/ntoskrnl/inbv/inbvport.c create mode 100644 reactos/ntoskrnl/include/internal/hdl.h 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 + ) +{ + /* Send every byte */ + while (*String++ != ANSI_NULL) + { + InbvPortPutByte(HeadlessGlobals->TerminalPort, *String); + } +} + +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 + ) { - PHEADLESS_LOADER_BLOCK HeadlessBlock; - - /* Get the headless loader block */ - HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock; - if (HeadlessBlock) - { - DPRINT1("ReactOS does not currently have Headless Terminal support!\n"); - } + //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 -- 2.17.1