2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/freeldr/windows/headless.c
5 * PURPOSE: Provides support for Windows Emergency Management Services
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
12 #include <cportlib/cportlib.h>
14 /* Note: Move these to some smbios.h header */
15 #define SYSID_TYPE_UUID "_UUID_"
16 #define SYSID_UUID_DATA_SIZE 16
18 typedef struct _SYSID_UUID_ENTRY
23 UCHAR UUID
[SYSID_UUID_DATA_SIZE
];
24 } SYSID_UUID_ENTRY
, *PSYSID_UUID_ENTRY
;
27 /* GLOBALS ********************************************************************/
29 HEADLESS_LOADER_BLOCK LoaderRedirectionInformation
;
30 BOOLEAN WinLdrTerminalConnected
;
31 ULONG WinLdrTerminalDeviceId
;
32 ULONG WinLdrTerminalDelay
;
42 /* FUNCTIONS ******************************************************************/
45 WinLdrLoadGUID(OUT PGUID SystemGuid
)
47 PSYSID_UUID_ENTRY CurrentAddress
;
49 CurrentAddress
= (PSYSID_UUID_ENTRY
)0xE0000;
50 while (CurrentAddress
< (PSYSID_UUID_ENTRY
)0x100000)
52 if (RtlCompareMemory(&CurrentAddress
->Type
, SYSID_TYPE_UUID
, 6) == 6)
54 RtlCopyMemory(SystemGuid
, &CurrentAddress
->UUID
, SYSID_UUID_DATA_SIZE
);
57 CurrentAddress
= (PSYSID_UUID_ENTRY
)((ULONG_PTR
)CurrentAddress
+ 1);
60 RtlZeroMemory(SystemGuid
, SYSID_UUID_DATA_SIZE
);
64 WinLdrPortInitialize(IN ULONG BaudRate
,
66 IN PUCHAR PortAddress
,
67 IN BOOLEAN TerminalConnected
,
70 /* Set default baud rate */
71 if (BaudRate
== 0) BaudRate
= 19200;
73 /* Check if port or address given */
76 /* Pick correct address for port */
82 PortAddress
= (PUCHAR
)0x3F8;
86 PortAddress
= (PUCHAR
)0x2F8;
90 PortAddress
= (PUCHAR
)0x3E8;
95 PortAddress
= (PUCHAR
)0x2E8;
101 /* Pick correct port for address */
102 PortAddress
= (PUCHAR
)0x2F8;
103 if (CpDoesPortExist(PortAddress
))
109 PortAddress
= (PUCHAR
)0x3F8;
110 if (!CpDoesPortExist(PortAddress
)) return FALSE
;
115 /* Not yet supported */
116 ASSERT(LoaderRedirectionInformation
.IsMMIODevice
== FALSE
);
118 /* Check if port exists */
119 if ((CpDoesPortExist(PortAddress
)) || (CpDoesPortExist(PortAddress
)))
121 /* Initialize port for first time, or re-initialize if specified */
122 if (((TerminalConnected
) && (Port
[PortNumber
- 1].Address
)) ||
123 !(Port
[PortNumber
- 1].Address
))
125 /* Initialize the port, return it */
126 CpInitialize(&Port
[PortNumber
- 1], PortAddress
, BaudRate
);
127 *PortId
= PortNumber
- 1;
136 WinLdrPortPutByte(IN ULONG PortId
,
139 CpPutByte(&Port
[PortId
], Byte
);
143 WinLdrPortGetByte(IN ULONG PortId
,
146 return CpGetByte(&Port
[PortId
], Byte
, TRUE
, FALSE
) == CP_GET_SUCCESS
;
150 WinLdrPortPollOnly(IN ULONG PortId
)
154 return CpGetByte(&Port
[PortId
], &Dummy
, FALSE
, TRUE
) == CP_GET_SUCCESS
;
158 WinLdrEnableFifo(IN ULONG PortId
,
161 CpEnableFifo(Port
[PortId
].Address
, Enable
);
165 WinLdrInitializeHeadlessPort(VOID
)
167 ULONG PortNumber
, BaudRate
;
169 PCHAR AnsiReset
= "\x1B[m";
172 PortNumber
= LoaderRedirectionInformation
.PortNumber
;
173 PortAddress
= LoaderRedirectionInformation
.PortAddress
;
174 BaudRate
= LoaderRedirectionInformation
.BaudRate
;
176 /* Pick a port address */
184 LoaderRedirectionInformation
.PortAddress
= (PUCHAR
)0x2F8;
188 LoaderRedirectionInformation
.PortAddress
= (PUCHAR
)0x3E8;
192 LoaderRedirectionInformation
.PortAddress
= (PUCHAR
)0x2E8;
196 LoaderRedirectionInformation
.PortAddress
= (PUCHAR
)0x3F8;
203 /* No number, so no EMS */
204 WinLdrTerminalConnected
= FALSE
;
208 /* Call arch code to initialize the port */
209 PortAddress
= LoaderRedirectionInformation
.PortAddress
;
210 WinLdrTerminalConnected
= WinLdrPortInitialize(
214 WinLdrTerminalConnected
,
215 &WinLdrTerminalDeviceId
);
217 if (WinLdrTerminalConnected
)
219 /* Port seems usable, set it up and get the BIOS GUID */
220 WinLdrEnableFifo(WinLdrTerminalDeviceId
, TRUE
);
222 WinLdrLoadGUID(&LoaderRedirectionInformation
.SystemGUID
);
224 /* Calculate delay in us based on the baud, assume 9600 if none given */
228 LoaderRedirectionInformation
.BaudRate
= BaudRate
;
231 WinLdrTerminalDelay
= (10 * 1000 * 1000) / (BaudRate
/ 10) / 6;
233 /* Sent an ANSI reset sequence to get the terminal up and running */
234 for (i
= 0; i
< strlen(AnsiReset
); i
++)
236 WinLdrPortPutByte(WinLdrTerminalDeviceId
, AnsiReset
[i
]);
237 StallExecutionProcessor(WinLdrTerminalDelay
);
243 WinLdrSetupEms(IN PCHAR BootOptions
)
245 PCHAR Settings
, RedirectPort
;
248 RtlZeroMemory(&LoaderRedirectionInformation
, sizeof(HEADLESS_LOADER_BLOCK
));
249 LoaderRedirectionInformation
.PciDeviceId
= PCI_INVALID_VENDORID
;
251 /* Use a direction port if one was given, or use ACPI to detect one instead */
252 Settings
= strstr(BootOptions
, "/redirect=");
255 RedirectPort
= strstr(Settings
, "com");
258 RedirectPort
+= sizeof("com") - 1;
259 LoaderRedirectionInformation
.PortNumber
= atoi(RedirectPort
);
260 LoaderRedirectionInformation
.TerminalType
= 1; // HeadlessSerialPort
264 RedirectPort
= strstr(Settings
, "usebiossettings");
267 UiDrawStatusText("ACPI SRT Table Not Supported...");
272 LoaderRedirectionInformation
.PortAddress
= (PUCHAR
)strtoul(Settings
, 0, 16);
273 if (LoaderRedirectionInformation
.PortAddress
)
275 LoaderRedirectionInformation
.PortNumber
= 3;
281 /* Use a direction baudrate if one was given */
282 Settings
= strstr(BootOptions
, "/redirectbaudrate=");
285 if (strstr(Settings
, "115200"))
287 LoaderRedirectionInformation
.BaudRate
= 115200;
289 else if (strstr(Settings
, "57600"))
291 LoaderRedirectionInformation
.BaudRate
= 57600;
293 else if (strstr(Settings
, "19200"))
295 LoaderRedirectionInformation
.BaudRate
= 19200;
299 LoaderRedirectionInformation
.BaudRate
= 9600;
303 /* Enable headless support if parameters were found */
304 if (LoaderRedirectionInformation
.PortNumber
)
306 if (!LoaderRedirectionInformation
.BaudRate
)
308 LoaderRedirectionInformation
.BaudRate
= 9600;
311 WinLdrInitializeHeadlessPort();