ReactOS 0.4.15-dev-7674-gc0b4db1
hdlsterm.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ex/hdlsterm.c
5 * PURPOSE: Headless Terminal Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <ntoskrnl.h>
12#include <debug.h>
13
14/* GLOBALS ********************************************************************/
15
17
18/* FUNCTIONS ******************************************************************/
19
23{
25
26 /* Don't acquire the lock if we are bugchecking */
28 {
30 }
31 else
32 {
33 OldIrql = 0xFF;
34 }
35
36 return OldIrql;
37}
38
40VOID
42{
43 /* Only release the lock if we aren't bugchecking */
44 if (OldIrql != 0xFF)
45 {
47 }
48 else
49 {
51 }
52}
53
54VOID
57{
58 /* Send every byte */
59 while (*String != ANSI_NULL)
60 {
62 }
63}
64
65VOID
69{
70 ULONG i;
71 for (i = 0; i < DataSize; i++)
72 {
74 }
75}
76
77VOID
80{
82 UCHAR Char = 0;
83
84 /* Scan each character */
85 while (*String != ANSI_NULL)
86 {
87 /* Check for rotate, send existing buffer and restart from where we are */
88 if (Dest >= &HeadlessGlobals->TmpBuffer[79])
89 {
93 }
94 else
95 {
96 /* Get the current character and check for special graphical chars */
97 Char = *String;
98 if (Char & 0x80)
99 {
100 switch (Char)
101 {
102 case 0xB0: case 0xB3: case 0xBA:
103 Char = '|';
104 break;
105 case 0xB1: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
106 Char = '%';
107 break;
108 case 0xB2: case 0xDB:
109 Char = '#';
110 break;
111 case 0xA9: case 0xAA: case 0xBB: case 0xBC: case 0xBF:
112 case 0xC0: case 0xC8: case 0xC9: case 0xD9: case 0xDA:
113 Char = '+';
114 break;
115 case 0xC4:
116 Char = '-';
117 break;
118 case 0xCD:
119 Char = '=';
120 break;
121 }
122 }
123
124 /* Anything else must be Unicode */
125 if (Char & 0x80)
126 {
127 /* Can't do Unicode yet */
129 }
130 else
131 {
132 /* Add the modified char to the temporary buffer */
133 *Dest++ = Char;
134 }
135
136 /* Check the next char */
137 String++;
138 }
139 }
140
141 /* Finish and send */
142 *Dest = ANSI_NULL;
144}
145
147NTAPI
149{
150 /* Enable if requested, as long as this isn't a PCI serial port crashing */
151 if ((Enable) &&
154 {
155 /* Initialize the COM port with cportlib */
162 {
163 DPRINT1("Failed to initialize port through cportlib\n");
164 return STATUS_UNSUCCESSFUL;
165 }
166
167 /* Cleanup the screen and reset the cursor */
168 HdlspSendStringAtBaud((PUCHAR)"\x1B[2J");
169 HdlspSendStringAtBaud((PUCHAR)"\x1B[H");
170
171 /* Enable FIFO */
173 }
174 else if (!Enable)
175 {
176 /* Specific case when headless is being disabled */
180 }
181
182 /* All done */
183 return STATUS_SUCCESS;
184}
185
186CODE_SEG("INIT")
187VOID
188NTAPI
190{
191 PHEADLESS_LOADER_BLOCK HeadlessBlock;
192
193 /* Only initialize further if the loader found EMS enabled */
194 HeadlessBlock = LoaderBlock->Extension->HeadlessLoaderBlock;
195 if (!HeadlessBlock) return;
196
197 /* Ignore invalid EMS settings */
198 if ((HeadlessBlock->PortNumber > 4) && (HeadlessBlock->UsedBiosSettings)) return;
199
200 /* Allocate the global headless data */
202 sizeof(*HeadlessGlobals),
203 'sldH');
204 if (!HeadlessGlobals) return;
205
206 /* Zero and copy loader data */
210 HeadlessGlobals->TerminalBaudRate = HeadlessBlock->BaudRate;
211 HeadlessGlobals->TerminalParity = HeadlessBlock->Parity;
212 HeadlessGlobals->TerminalStopBits = HeadlessBlock->StopBits;
214 HeadlessGlobals->IsMMIODevice = HeadlessBlock->IsMMIODevice;
215 HeadlessGlobals->TerminalType = HeadlessBlock->TerminalType;
216 HeadlessGlobals->SystemGUID = HeadlessBlock->SystemGUID;
217 DPRINT1("EMS on Port %lu (0x%p) at %lu bps\n",
221
222 /* These two are opposites of each other */
224
225 /* Check for a PCI device, warn that this isn't supported */
226 if (HeadlessBlock->PciDeviceId != PCI_INVALID_VENDORID)
227 {
228 DPRINT1("PCI Serial Ports not supported\n");
229 }
230
231 /* Log entries are not yet supported */
232 DPRINT1("FIXME: No Headless logging support\n");
233
234 /* Allocate temporary buffer */
236 if (!HeadlessGlobals->TmpBuffer) return;
237
238 /* Windows seems to apply some special hacks for 9600 bps */
240 {
241 DPRINT1("Please use other baud rate than 9600bps for now\n");
242 }
243
244 /* Enable the terminal */
246}
247
249NTAPI
252 IN SIZE_T InputBufferSize,
254 OUT PSIZE_T OutputBufferSize)
255{
258 PHEADLESS_RSP_QUERY_INFO HeadlessInfo;
259 PHEADLESS_CMD_PUT_STRING PutString;
260 PHEADLESS_CMD_ENABLE_TERMINAL EnableTerminal;
264 UCHAR DataBuffer[80];
265
267 // ASSERT(HeadlessGlobals->PageLockHandle != NULL);
268
269 /* Ignore non-reentrant commands */
274 {
276
278 {
280 return STATUS_UNSUCCESSFUL;
281 }
282
283 /* Don't allow these commands next time */
286 }
287
288 /* Handle each command */
289 switch (Command)
290 {
292 {
293 /* Make sure the caller passed valid data */
294 if (!(InputBuffer) ||
295 (InputBufferSize != sizeof(*EnableTerminal)))
296 {
297 DPRINT1("Invalid buffer\n");
299 break;
300 }
301
302 /* Go and enable it */
303 EnableTerminal = InputBuffer;
304 Status = HdlspEnableTerminal(EnableTerminal->Enable);
305 break;
306 }
307
309 break;
310
312 {
313 /* Validate the existence of an input buffer */
314 if (!InputBuffer)
315 {
317 break;
318 }
319
320 /* Terminal should be on */
322 {
323 /* Print each byte in the string making sure VT100 chars are used */
324 PutString = InputBuffer;
325 HdlspPutString(PutString->String);
326 }
327
328 /* Return success either way */
330 break;
331 }
332
340 {
341 /* By default return success */
343
344 /* Send the VT100 commands only if the terminal is enabled */
346 {
347 PUCHAR CommandStr = NULL;
348
350 CommandStr = (PUCHAR)"\x1B[2J";
352 CommandStr = (PUCHAR)"\x1B[0J";
354 CommandStr = (PUCHAR)"\x1B[0K";
356 CommandStr = (PUCHAR)"\x1B[0m";
358 CommandStr = (PUCHAR)"\x1B[7m";
359 else if (Command == HeadlessCmdSetColor)
360 {
361 /* Make sure the caller passed valid data */
362 if (!InputBuffer ||
363 (InputBufferSize != sizeof(*SetColor)))
364 {
365 DPRINT1("Invalid buffer\n");
367 break;
368 }
369
370 SetColor = InputBuffer;
371 Status = RtlStringCbPrintfA((PCHAR)DataBuffer, sizeof(DataBuffer),
372 "\x1B[%d;%dm",
373 SetColor->BkgdColor,
374 SetColor->TextColor);
375 if (!NT_SUCCESS(Status)) break;
376
377 CommandStr = DataBuffer;
378 }
379 else // if (Command == HeadlessCmdPositionCursor)
380 {
381 /* Make sure the caller passed valid data */
382 if (!InputBuffer ||
383 (InputBufferSize != sizeof(*CursorPos)))
384 {
385 DPRINT1("Invalid buffer\n");
387 break;
388 }
389
390 CursorPos = InputBuffer;
391 /* Cursor position is 1-based */
392 Status = RtlStringCbPrintfA((PCHAR)DataBuffer, sizeof(DataBuffer),
393 "\x1B[%d;%dH",
394 CursorPos->CursorRow + 1,
395 CursorPos->CursorCol + 1);
396 if (!NT_SUCCESS(Status)) break;
397
398 CommandStr = DataBuffer;
399 }
400
401 /* Send the command */
402 HdlspSendStringAtBaud(CommandStr);
403 }
404
405 break;
406 }
407
409 break;
410
412 {
413 /* Make sure the caller passed valid data */
414 if (!(OutputBuffer) ||
415 !(OutputBufferSize) ||
416 (*OutputBufferSize < sizeof(*GetByte)))
417 {
418 DPRINT1("Invalid buffer\n");
420 break;
421 }
422
423 /* Make sure the terminal is enabled */
424 GetByte = OutputBuffer;
426 {
427 /* Poll if something is on the wire */
429 {
430 /* If so, read it */
432 &GetByte->Value);
433 }
434 else
435 {
436 /* Nothing is there, return 0 */
437 GetByte->Value = 0;
438 }
439 }
440 else
441 {
442 /* Otherwise return nothing */
443 GetByte->Value = 0;
444 }
445
446 /* Return success either way */
448 break;
449 }
450
452 break;
454 break;
456 break;
457
459 {
460 /* Make sure the caller passed valid data */
461 if (!(OutputBuffer) ||
462 !(OutputBufferSize) ||
463 (*OutputBufferSize < sizeof(*HeadlessInfo)))
464 {
465 DPRINT1("Invalid buffer\n");
467 break;
468 }
469
470 /* If we got here, headless is enabled -- we know this much */
471 HeadlessInfo = OutputBuffer;
472 HeadlessInfo->PortType = HeadlessSerialPort;
473 HeadlessInfo->Serial.TerminalAttached = TRUE;
474 HeadlessInfo->Serial.UsedBiosSettings = HeadlessGlobals->UsedBiosSettings != 0;
475 HeadlessInfo->Serial.TerminalBaudRate = HeadlessGlobals->TerminalBaudRate;
476 HeadlessInfo->Serial.TerminalType = HeadlessGlobals->TerminalType;
477
478 /* Now check on what port/baud it's enabled on */
481 {
482 /* Get the EMS information */
483 HeadlessInfo->Serial.TerminalPort = HeadlessGlobals->
484 TerminalPortNumber;
485 HeadlessInfo->Serial.TerminalPortBaseAddress = HeadlessGlobals->
486 TerminalPortAddress;
487 }
488 else
489 {
490 /* We don't know for sure */
491 HeadlessInfo->Serial.TerminalPort = SerialPortUndefined;
492 HeadlessInfo->Serial.TerminalPortBaseAddress = 0;
493 }
494
495 /* All done */
497 break;
498 }
499
501 break;
503 break;
504
506 {
507 /* Validate the existence of an input buffer */
508 if (!InputBuffer)
509 {
511 break;
512 }
513
514 /* Lie so that we can get Hdl bringup a little bit further */
517 break;
518 }
519
521 break;
523 break;
524
526 {
527 /* Validate the existence of an input buffer */
528 if (!(InputBuffer) || !(InputBufferSize))
529 {
531 break;
532 }
533
534 /* Terminal should be on */
536 {
537 /* Print each byte in the string making sure VT100 chars are used */
538 PutString = InputBuffer;
539 HdlspPutData(PutString->String, InputBufferSize);
540 }
541
542 /* Return success either way */
544 break;
545 }
546
547 default:
548 break;
549 }
550
551 /* Unset processing state */
556 {
559 }
560
561 /* All done */
562 return Status;
563}
564
565/*
566 * @implemented
567 */
569NTAPI
572 IN SIZE_T InputBufferSize,
574 OUT PSIZE_T OutputBufferSize)
575{
576 /* Check for stubs that will expect something even with headless off */
577 if (!HeadlessGlobals)
578 {
579 /* Don't allow the SAC to connect */
581
582 /* Send bogus reply */
588 {
589 if (!(OutputBuffer) || !(OutputBufferSize))
590 {
592 }
593
594 RtlZeroMemory(OutputBuffer, *OutputBufferSize);
595 }
596
597 return STATUS_SUCCESS;
598 }
599
600 /* Do the real work */
601 return HdlspDispatch(Command,
603 InputBufferSize,
605 OutputBufferSize);
606}
607
608/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: debug.h:115
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ HeadlessCmdPutString
Definition: hdl.h:131
@ HeadlessCmdStartBugCheck
Definition: hdl.h:142
@ HeadlessCmdDisplayInverseVideo
Definition: hdl.h:136
@ HeadlessCmdTerminalPoll
Definition: hdl.h:139
@ HeadlessCmdSetColor
Definition: hdl.h:137
@ HeadlessCmdDisplayAttributesOff
Definition: hdl.h:135
@ HeadlessCmdGetByte
Definition: hdl.h:140
@ HeadlessCmdPutData
Definition: hdl.h:150
@ HeadlessCmdPositionCursor
Definition: hdl.h:138
@ HeadlessCmdEnableTerminal
Definition: hdl.h:129
@ HeadlessCmdClearDisplay
Definition: hdl.h:132
@ HeadlessCmdQueryGUID
Definition: hdl.h:149
@ HeadlessCmdGetLine
Definition: hdl.h:141
@ HeadlessCmdClearToEndOfLine
Definition: hdl.h:134
@ HeadlessCmdDisplayLog
Definition: hdl.h:146
@ HeadlessCmdClearToEndOfDisplay
Definition: hdl.h:133
@ HeadlessCmdAddLogEntry
Definition: hdl.h:145
@ HeadlessCmdDoBugCheckProcessing
Definition: hdl.h:143
@ HeadlessCmdCheckForReboot
Definition: hdl.h:130
@ HeadlessCmdSendBlueScreenData
Definition: hdl.h:148
@ HeadlessCmdSetBlueScreenData
Definition: hdl.h:147
@ HeadlessCmdQueryInformation
Definition: hdl.h:144
enum _HEADLESS_CMD HEADLESS_CMD
@ HeadlessSerialPort
Definition: hdl.h:156
@ SerialPortUndefined
Definition: hdl.h:161
NTSTATUS NTAPI HeadlessDispatch(IN HEADLESS_CMD Command, IN PVOID InputBuffer, IN SIZE_T InputBufferSize, OUT PVOID OutputBuffer, OUT PSIZE_T OutputBufferSize)
Definition: hdlsterm.c:570
PHEADLESS_GLOBALS HeadlessGlobals
Definition: hdlsterm.c:16
NTSTATUS NTAPI HdlspDispatch(IN HEADLESS_CMD Command, IN PVOID InputBuffer, IN SIZE_T InputBufferSize, OUT PVOID OutputBuffer, OUT PSIZE_T OutputBufferSize)
Definition: hdlsterm.c:250
VOID NTAPI HdlspPutString(IN PUCHAR String)
Definition: hdlsterm.c:79
FORCEINLINE VOID HdlspReleaseGlobalLock(IN KIRQL OldIrql)
Definition: hdlsterm.c:41
VOID NTAPI HdlspPutData(IN PUCHAR Data, IN ULONG DataSize)
Definition: hdlsterm.c:67
VOID NTAPI HeadlessInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: hdlsterm.c:189
FORCEINLINE KIRQL HdlspAcquireGlobalLock(VOID)
Definition: hdlsterm.c:22
VOID NTAPI HdlspSendStringAtBaud(IN PUCHAR String)
Definition: hdlsterm.c:56
NTSTATUS NTAPI HdlspEnableTerminal(IN BOOLEAN Enable)
Definition: hdlsterm.c:148
VOID NTAPI InbvPortTerminate(IN ULONG PortId)
Definition: inbvport.c:65
VOID NTAPI InbvPortPutByte(IN ULONG PortId, IN UCHAR Byte)
Definition: inbvport.c:47
BOOLEAN NTAPI InbvPortInitialize(IN ULONG BaudRate, IN ULONG PortNumber, IN PUCHAR PortAddress, OUT PULONG PortId, IN BOOLEAN IsMMIODevice)
Definition: inbvport.c:73
VOID NTAPI InbvPortEnableFifo(IN ULONG PortId, IN BOOLEAN Enable)
Definition: inbvport.c:56
BOOLEAN NTAPI InbvPortGetByte(IN ULONG PortId, OUT PUCHAR Byte)
Definition: inbvport.c:38
BOOLEAN NTAPI InbvPortPollOnly(IN ULONG PortId)
Definition: inbvport.c:28
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define ASSERT(a)
Definition: mode.c:44
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
#define ANSI_NULL
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: shell.h:41
ULONG TerminalEnabled
Definition: hdl.h:96
GUID SystemGUID
Definition: hdl.h:119
ULONG IsNonLegacyDevice
Definition: hdl.h:106
PUCHAR TerminalPortAddress
Definition: hdl.h:112
ULONG TerminalPortNumber
Definition: hdl.h:105
ULONG TerminalPort
Definition: hdl.h:111
ULONG UsedBiosSettings
Definition: hdl.h:99
ULONG TerminalStopBits
Definition: hdl.h:104
BOOLEAN IsMMIODevice
Definition: hdl.h:120
UCHAR TerminalType
Definition: hdl.h:115
ULONG TerminalBaudRate
Definition: hdl.h:110
ULONG TerminalParity
Definition: hdl.h:103
ULONG InBugCheck
Definition: hdl.h:97
PUCHAR TmpBuffer
Definition: hdl.h:89
KSPIN_LOCK SpinLock
Definition: hdl.h:86
ULONG ProcessingCmd
Definition: hdl.h:102
UCHAR IsMMIODevice
Definition: arc.h:367
UCHAR UsedBiosSettings
Definition: arc.h:353
PUCHAR PortAddress
Definition: arc.h:359
USHORT PciDeviceId
Definition: arc.h:360
UCHAR TerminalType
Definition: arc.h:368
struct _HEADLESS_RSP_QUERY_INFO::@1777::@1779 Serial
HEADLESS_TERM_PORT_TYPE PortType
Definition: hdl.h:170
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
#define FORCEINLINE
Definition: wdftypes.h:67
#define PCI_INVALID_VENDORID
Definition: iotypes.h:3601
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
unsigned char UCHAR
Definition: xmlstorage.h:181