[FREELDR] Add KD support

Some limitations:
- only debug output is supported
- NOT tested with WinDBG
This commit is contained in:
Hervé Poussineau 2022-06-26 14:06:27 +02:00
parent db271c2228
commit 5fee9d2e41
7 changed files with 248 additions and 14 deletions

View file

@ -33,7 +33,8 @@ list(APPEND FREELDR_BOOTLIB_SOURCE
lib/cache/blocklist.c
lib/cache/cache.c
lib/comm/rs232.c
## add KD support
../../../drivers/base/kdnet/kdnet.c
lib/kdstub.c
lib/fs/btrfs.c
lib/fs/ext2.c
lib/fs/fat.c

View file

@ -23,6 +23,6 @@
BOOLEAN Rs232PortInitialize(ULONG ComPort, ULONG BaudRate);
BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived);
// BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived);
BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived);
VOID Rs232PortPutByte(UCHAR ByteToSend);
BOOLEAN Rs232PortInUse(PUCHAR Base);

View file

@ -65,6 +65,7 @@
#include <disk.h>
#include <fs.h>
#include <inifile.h>
#include <kd.h>
#include <keycodes.h>
#include <linux.h>
#include <custom.h>

View file

@ -0,0 +1,15 @@
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Kernel debugger header file for the FreeLoader
* COPYRIGHT: Copyright 2001-2003 Brian Palmer <brianp@sginet.com>
* Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
*/
#pragma once
#include <windbgkd.h>
#include <kddll.h>
#include <kdnetextensibility.h>
VOID DebugPrintChar(UCHAR Character);

View file

@ -121,13 +121,11 @@ BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived)
return (CpGetByte(&Rs232ComPortInfo, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS);
}
/*
BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived)
{
if (Rs232ComPort == 0) return FALSE;
return (CpGetByte(&Rs232ComPortInfo, ByteReceived, FALSE, FALSE) == CP_GET_SUCCESS);
}
*/
VOID Rs232PortPutByte(UCHAR ByteToSend)
{

View file

@ -194,6 +194,13 @@ Done:
if (!Rs232PortInitialize(ComPort, BaudRate))
DebugPort &= ~RS232;
}
{
LOADER_PARAMETER_BLOCK LoaderBlock = {0};
LoaderBlock.LoadOptions = (PCHAR)CmdLineGetDebugString();
KdDebuggerInitialize0(&LoaderBlock);
KdDebuggerInitialize1(&LoaderBlock);
}
}
VOID DebugPrintChar(UCHAR Character)
@ -218,12 +225,32 @@ VOID DebugPrintChar(UCHAR Character)
}
}
VOID
DbgPrintString(
_In_ PCHAR Buffer,
_In_ ULONG Length)
{
DBGKD_DEBUG_IO DebugIo = {0};
STRING MessageHeader;
STRING MessageData;
/* Prepare packet to send to debugger */
DebugIo.ApiNumber = DbgKdPrintStringApi;
DebugIo.u.PrintString.LengthOfString = Length;
MessageHeader.Buffer = (PCHAR)&DebugIo;
MessageHeader.Length = sizeof(DebugIo);
MessageData.Buffer = Buffer;
MessageData.Length = Length;
/* Send packet to debugger */
KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, &MessageHeader, &MessageData, NULL);
}
ULONG
DbgPrint(const char *Format, ...)
{
va_list ap;
int Length;
char* ptr;
CHAR Buffer[512];
va_start(ap, Format);
@ -240,9 +267,7 @@ DbgPrint(const char *Format, ...)
Length = sizeof(Buffer);
}
ptr = Buffer;
while (Length--)
DebugPrintChar(*ptr++);
DbgPrintString(Buffer, Length);
return 0;
}
@ -252,7 +277,7 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, .
{
va_list ap;
char Buffer[2096];
char *ptr = Buffer;
int Length;
/* Mask out unwanted debug messages */
if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS))
@ -285,13 +310,10 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, .
}
va_start(ap, Format);
vsprintf(Buffer, Format, ap);
Length = vsprintf(Buffer, Format, ap);
va_end(ap);
while (*ptr)
{
DebugPrintChar(*ptr++);
}
DbgPrintString(Buffer, Length);
}
VOID

View file

@ -0,0 +1,197 @@
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: I/O functions for the freeldr debugger
* COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
*/
#include <freeldr.h>
static UCHAR KdTxMessageBuffer[4096];
static UCHAR KdRxMessageBuffer[4096];
static NTSTATUS
NTAPI
KdpGetRxPacketWinKD(
_In_ PVOID Adapter,
_Out_ PULONG Handle,
_Out_ PVOID *Packet,
_Out_ PULONG Length)
{
ULONG DataLength = 0;
ULONG Retries;
do
{
for (Retries = 100; Retries > 0; Retries--)
{
if (Rs232PortPollByte(&KdRxMessageBuffer[DataLength]))
{
DataLength++;
break;
}
}
} while (Retries > 0);
if (DataLength == 0)
return STATUS_IO_TIMEOUT;
*Handle = 1;
*Packet = KdRxMessageBuffer;
*Length = DataLength;
return STATUS_SUCCESS;
}
static NTSTATUS
NTAPI
KdpGetRxPacketDirectOutput(
_In_ PVOID Adapter,
_Out_ PULONG Handle,
_Out_ PVOID *Packet,
_Out_ PULONG Length)
{
*(PULONG)(KdRxMessageBuffer + 0) = PACKET_LEADER;
*(PUSHORT)(KdRxMessageBuffer + 4) = PACKET_TYPE_KD_ACKNOWLEDGE;
*(PUSHORT)(KdRxMessageBuffer + 6) = 0; // ByteCount
*(PULONG)(KdRxMessageBuffer + 8) = INITIAL_PACKET_ID; // PacketId
*(PULONG)(KdRxMessageBuffer + 12) = 0; // CheckSum
*(KdRxMessageBuffer + 16) = PACKET_TRAILING_BYTE;
*Handle = 1;
*Packet = KdRxMessageBuffer;
*Length = 17;
return STATUS_SUCCESS;
}
static VOID
NTAPI
KdpReleaseRxPacket(
_In_ PVOID Adapter,
_In_ ULONG Handle)
{
}
static NTSTATUS
NTAPI
KdpGetTxPacket(
_In_ PVOID Adapter,
_Out_ PULONG Handle)
{
*Handle = 0;
return STATUS_SUCCESS;
}
static NTSTATUS
NTAPI
KdpSendTxPacketWinKD(
_In_ PVOID Adapter,
_In_ ULONG Handle,
_In_ ULONG Length)
{
PUCHAR ByteBuffer = KdTxMessageBuffer;
while (Length-- > 0)
{
Rs232PortPutByte(*ByteBuffer++);
}
return STATUS_SUCCESS;
}
static NTSTATUS
NTAPI
KdpSendTxPacketDirectOutput(
_In_ PVOID Adapter,
_In_ ULONG Handle,
_In_ ULONG Length)
{
PKD_PACKET Packet = (PKD_PACKET)KdTxMessageBuffer;
PDBGKD_DEBUG_IO DebugIo;
PCHAR Buffer;
ULONG BufferLength, i;
if (Packet->PacketType != PACKET_TYPE_KD_DEBUG_IO)
return STATUS_SUCCESS;
DebugIo = (PDBGKD_DEBUG_IO)(Packet + 1);
if (DebugIo->ApiNumber != DbgKdPrintStringApi)
return STATUS_SUCCESS;
BufferLength = Packet->ByteCount - sizeof(DBGKD_DEBUG_IO);
Buffer = (PCHAR)(DebugIo + 1);
for (i = 0; i < BufferLength; i++)
DebugPrintChar(Buffer[i]);
return STATUS_SUCCESS;
}
static PVOID
NTAPI
KdpGetPacketAddress(
_In_ PVOID Adapter,
_In_ ULONG Handle)
{
if (Handle == 0)
return KdTxMessageBuffer;
else if (Handle == 1)
return KdRxMessageBuffer;
else
return NULL;
}
static ULONG
NTAPI
KdpGetPacketLength(
_In_ PVOID Adapter,
_In_ ULONG Handle)
{
if (Handle == 0)
return sizeof(KdTxMessageBuffer);
else if (Handle == 1)
return sizeof(KdRxMessageBuffer);
else
return 0;
}
static KDNET_EXTENSIBILITY_EXPORTS KdWinKDExports = {
KDNET_EXT_EXPORTS,
NULL,
NULL,
NULL,
KdpGetRxPacketWinKD,
KdpReleaseRxPacket,
KdpGetTxPacket,
KdpSendTxPacketWinKD,
KdpGetPacketAddress,
KdpGetPacketLength,
};
static KDNET_EXTENSIBILITY_EXPORTS KdDirectOutputExports = {
KDNET_EXT_EXPORTS,
NULL,
NULL,
NULL,
KdpGetRxPacketDirectOutput,
KdpReleaseRxPacket,
KdpGetTxPacket,
KdpSendTxPacketDirectOutput,
KdpGetPacketAddress,
KdpGetPacketLength,
};
NTSTATUS
NTAPI
KdInitializeLibrary(
_In_ PKDNET_EXTENSIBILITY_IMPORTS ImportTable,
_In_opt_ PCHAR LoaderOptions,
_Inout_ PDEBUG_DEVICE_DESCRIPTOR Device)
{
#ifdef _WINKD_
if (1)
#else
if (0)
#endif
ImportTable->Exports = &KdWinKDExports;
else
ImportTable->Exports = &KdDirectOutputExports;
return STATUS_SUCCESS;
}