mirror of
https://github.com/reactos/reactos.git
synced 2024-09-12 05:43:24 +00:00
Patch by Anton Yarotsky:
[FREELDR]: Implement support for /redirect=comX (usebiossettings not yet supported) and /redirectbaudrate. Uses cportlib. Tested, serial output works and kernel reports "Headless support is not yet implemented". Future revisions should support ACPI SRT for PCI-based serial ports on server systems. svn path=/trunk/; revision=48768
This commit is contained in:
parent
1a554af4a0
commit
ef0d280232
|
@ -32,5 +32,6 @@
|
|||
<library>cmlib</library>
|
||||
<library>rtl</library>
|
||||
<library>libcntpr</library>
|
||||
<library>cportlib</library>
|
||||
</module>
|
||||
</ifnot>
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
<file>winldr.c</file>
|
||||
<file>wlmemory.c</file>
|
||||
<file>wlregistry.c</file>
|
||||
<file>headless.c</file>
|
||||
</directory>
|
||||
<file>freeldr.c</file>
|
||||
<file>debug.c</file>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<library>setupldr_main</library>
|
||||
<library>rossym</library>
|
||||
<library>cmlib</library>
|
||||
<library>cportlib</library>
|
||||
<library>rtl</library>
|
||||
<library>libcntpr</library>
|
||||
</module>
|
||||
|
|
313
reactos/boot/freeldr/freeldr/windows/headless.c
Normal file
313
reactos/boot/freeldr/freeldr/windows/headless.c
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Boot Loader
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: boot/freeldr/windows/headless.c
|
||||
* PURPOSE: Provides support for Windows Emergency Management Services
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <freeldr.h>
|
||||
#include <cportlib/cportlib.h>
|
||||
|
||||
/* Note: Move these to some smbios.h header */
|
||||
#define SYSID_TYPE_UUID "_UUID_"
|
||||
#define SYSID_UUID_DATA_SIZE 16
|
||||
#include <pshpack1.h>
|
||||
typedef struct _SYSID_UUID_ENTRY
|
||||
{
|
||||
UCHAR Type[6];
|
||||
UCHAR Checksum;
|
||||
USHORT Length;
|
||||
UCHAR UUID[SYSID_UUID_DATA_SIZE];
|
||||
} SYSID_UUID_ENTRY, *PSYSID_UUID_ENTRY;
|
||||
#include <poppack.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
||||
BOOLEAN WinLdrTerminalConnected;
|
||||
ULONG WinLdrTerminalDeviceId;
|
||||
ULONG WinLdrTerminalDelay;
|
||||
|
||||
CPPORT Port[4] =
|
||||
{
|
||||
{NULL, 0, TRUE},
|
||||
{NULL, 0, TRUE},
|
||||
{NULL, 0, TRUE},
|
||||
{NULL, 0, TRUE}
|
||||
};
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
WinLdrLoadGUID(OUT PGUID SystemGuid)
|
||||
{
|
||||
PSYSID_UUID_ENTRY CurrentAddress;
|
||||
|
||||
CurrentAddress = (PSYSID_UUID_ENTRY)0xE0000;
|
||||
while (CurrentAddress < (PSYSID_UUID_ENTRY)0x100000)
|
||||
{
|
||||
if (RtlCompareMemory(&CurrentAddress->Type, SYSID_TYPE_UUID, 6) == 6)
|
||||
{
|
||||
RtlCopyMemory(SystemGuid, &CurrentAddress->UUID, SYSID_UUID_DATA_SIZE);
|
||||
return;
|
||||
}
|
||||
CurrentAddress = (PSYSID_UUID_ENTRY)((ULONG_PTR)CurrentAddress + 1);
|
||||
}
|
||||
|
||||
RtlZeroMemory(SystemGuid, SYSID_UUID_DATA_SIZE);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
WinLdrPortInitialize(IN ULONG BaudRate,
|
||||
IN ULONG PortNumber,
|
||||
IN PUCHAR PortAddress,
|
||||
IN BOOLEAN TerminalConnected,
|
||||
OUT PULONG PortId)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not yet supported */
|
||||
ASSERT(LoaderRedirectionInformation.IsMMIODevice == FALSE);
|
||||
|
||||
/* Check if port exists */
|
||||
if ((CpDoesPortExist(PortAddress)) || (CpDoesPortExist(PortAddress)))
|
||||
{
|
||||
/* Initialize port for first time, or re-initialize if specified */
|
||||
if (((TerminalConnected) && (Port[PortNumber - 1].Address)) ||
|
||||
!(Port[PortNumber - 1].Address))
|
||||
{
|
||||
/* Initialize the port, return it */
|
||||
CpInitialize(&Port[PortNumber - 1], PortAddress, BaudRate);
|
||||
*PortId = PortNumber - 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
WinLdrPortPutByte(IN ULONG PortId,
|
||||
IN UCHAR Data)
|
||||
{
|
||||
CpPutByte(&Port[PortId], Data);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
WinLdrPortGetByte(IN ULONG PortId,
|
||||
OUT PUCHAR Data)
|
||||
{
|
||||
return CpGetByte(&Port[PortId], Data, TRUE, FALSE) == CP_GET_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
WinLdrPortPollOnly(IN ULONG PortId)
|
||||
{
|
||||
UCHAR Dummy;
|
||||
|
||||
return CpGetByte(&Port[PortId], &Dummy, FALSE, TRUE) == CP_GET_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
WinLdrEnableFifo(IN ULONG PortId,
|
||||
IN BOOLEAN Enable)
|
||||
{
|
||||
CpEnableFifo(Port[PortId].Address, Enable);
|
||||
}
|
||||
|
||||
VOID
|
||||
WinLdrInitializeHeadlessPort(VOID)
|
||||
{
|
||||
ULONG PortNumber, BaudRate;
|
||||
PUCHAR PortAddress;
|
||||
PCHAR AnsiReset = "\x1B[m";
|
||||
ULONG i;
|
||||
|
||||
PortNumber = LoaderRedirectionInformation.PortNumber;
|
||||
PortAddress = LoaderRedirectionInformation.PortAddress;
|
||||
BaudRate = LoaderRedirectionInformation.BaudRate;
|
||||
|
||||
/* Pick a port address */
|
||||
if (PortNumber)
|
||||
{
|
||||
if (!PortAddress)
|
||||
{
|
||||
switch (PortNumber)
|
||||
{
|
||||
case 2:
|
||||
LoaderRedirectionInformation.PortAddress = (PUCHAR)0x2F8;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
LoaderRedirectionInformation.PortAddress = (PUCHAR)0x3E8;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
LoaderRedirectionInformation.PortAddress = (PUCHAR)0x2E8;
|
||||
break;
|
||||
|
||||
default:
|
||||
LoaderRedirectionInformation.PortAddress = (PUCHAR)0x3F8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No number, so no EMS */
|
||||
WinLdrTerminalConnected = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call arch code to initialize the port */
|
||||
PortAddress = LoaderRedirectionInformation.PortAddress;
|
||||
WinLdrTerminalConnected = WinLdrPortInitialize(
|
||||
BaudRate,
|
||||
PortNumber,
|
||||
PortAddress,
|
||||
WinLdrTerminalConnected,
|
||||
&WinLdrTerminalDeviceId);
|
||||
|
||||
if (WinLdrTerminalConnected)
|
||||
{
|
||||
/* Port seems usable, set it up and get the BIOS GUID */
|
||||
WinLdrEnableFifo(WinLdrTerminalDeviceId, TRUE);
|
||||
|
||||
WinLdrLoadGUID(&LoaderRedirectionInformation.SystemGUID);
|
||||
|
||||
/* Calculate delay in us based on the baud, assume 9600 if none given */
|
||||
if (!BaudRate)
|
||||
{
|
||||
BaudRate = 9600;
|
||||
LoaderRedirectionInformation.BaudRate = BaudRate;
|
||||
}
|
||||
|
||||
WinLdrTerminalDelay = (10 * 1000 * 1000) / (BaudRate / 10) / 6;
|
||||
|
||||
/* Sent an ANSI reset sequence to get the terminal up and running */
|
||||
for (i = 0; i < strlen(AnsiReset); i++)
|
||||
{
|
||||
WinLdrPortPutByte(WinLdrTerminalDeviceId, AnsiReset[i]);
|
||||
StallExecutionProcessor(WinLdrTerminalDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The port was bogus, so don't give any information to the kernel */
|
||||
RtlZeroMemory(&LoaderRedirectionInformation, sizeof(HEADLESS_LOADER_BLOCK));
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
WinLdrSetupEms(IN PCHAR BootOptions)
|
||||
{
|
||||
PCHAR RedirectPort;
|
||||
|
||||
/* Use a direction port if one was given, or use ACPI to detect one instead */
|
||||
RedirectPort = strstr(BootOptions, "/redirect=");
|
||||
|
||||
if (RedirectPort)
|
||||
{
|
||||
RedirectPort = strstr(RedirectPort, "com");
|
||||
if (RedirectPort)
|
||||
{
|
||||
RedirectPort += sizeof("com") - 1;
|
||||
LoaderRedirectionInformation.PortNumber = atoi(RedirectPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
RedirectPort = strstr(RedirectPort, "usebiossettings");
|
||||
if (RedirectPort)
|
||||
{
|
||||
UiDrawStatusText("ACPI SRT Table Not Supported...");
|
||||
}
|
||||
else
|
||||
{
|
||||
LoaderRedirectionInformation.PortAddress = (PUCHAR)strtoul(RedirectPort, 0, 16);
|
||||
if (LoaderRedirectionInformation.PortAddress)
|
||||
{
|
||||
LoaderRedirectionInformation.PortNumber = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Use a direction baudrate if one was given */
|
||||
RedirectPort = strstr(BootOptions, "/redirectbaudrate=");
|
||||
if (RedirectPort)
|
||||
{
|
||||
if (strstr(RedirectPort, "115200"))
|
||||
{
|
||||
LoaderRedirectionInformation.BaudRate = 115200;
|
||||
}
|
||||
else if (strstr(RedirectPort, "57600"))
|
||||
{
|
||||
LoaderRedirectionInformation.BaudRate = 57600;
|
||||
}
|
||||
else if (strstr(RedirectPort, "19200"))
|
||||
{
|
||||
LoaderRedirectionInformation.BaudRate = 19200;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoaderRedirectionInformation.BaudRate = 9600;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable headless support if parameters were found */
|
||||
if (LoaderRedirectionInformation.PortNumber)
|
||||
{
|
||||
if (!LoaderRedirectionInformation.BaudRate)
|
||||
{
|
||||
LoaderRedirectionInformation.BaudRate = 9600;
|
||||
}
|
||||
|
||||
WinLdrInitializeHeadlessPort();
|
||||
}
|
||||
}
|
|
@ -514,6 +514,10 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
|||
/* Allocate and minimalistic-initialize LPB */
|
||||
AllocateAndInitLPB(&LoaderBlock);
|
||||
|
||||
/* Setup redirection support */
|
||||
extern void WinLdrSetupEms(IN PCHAR BootOptions);
|
||||
WinLdrSetupEms(BootOptions);
|
||||
|
||||
/* Detect hardware */
|
||||
UseRealHeap = TRUE;
|
||||
LoaderBlock->ConfigurationRoot = MachHwDetect();
|
||||
|
@ -598,6 +602,10 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
|||
/* Save final value of LoaderPagesSpanned */
|
||||
LoaderBlockVA->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
|
||||
|
||||
/* Set headless block pointer */
|
||||
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
||||
LoaderBlockVA->Extension->HeadlessLoaderBlock = PaToVa(&LoaderRedirectionInformation);
|
||||
|
||||
DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
|
||||
KiSystemStartup, LoaderBlockVA);
|
||||
|
||||
|
|
Loading…
Reference in a new issue