mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
359 lines
7.6 KiB
C
359 lines
7.6 KiB
C
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
uartio.c
|
|
|
|
Abstract:
|
|
|
|
This file defines I/O functions and the function pointers used by the serial
|
|
drivers to access the device hardware.
|
|
|
|
--*/
|
|
|
|
// ------------------------------------------------------------------- Includes
|
|
|
|
#include "common.h"
|
|
|
|
// ---------------------------------------------------------------- Definitions
|
|
|
|
//
|
|
// Maximum addressable register width varies with platform architecture.
|
|
//
|
|
|
|
#if defined(_WIN64)
|
|
|
|
# define MAX_REGISTER_WIDTH 64
|
|
|
|
#else
|
|
|
|
# define MAX_REGISTER_WIDTH 32
|
|
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------- Date Types
|
|
|
|
// ------------------------------------------------------------------ Functions
|
|
|
|
//
|
|
// Memory-mapped I/O Routines.
|
|
//
|
|
|
|
static VOID
|
|
WriteRegisterWithIndex8(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PUCHAR Pointer;
|
|
|
|
Pointer = (PUCHAR)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_REGISTER_UCHAR(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadRegisterWithIndex8(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PUCHAR Pointer;
|
|
|
|
Pointer = (PUCHAR)(Port->Address + Index * Port->ByteWidth);
|
|
return READ_REGISTER_UCHAR(Pointer);
|
|
}
|
|
|
|
static VOID
|
|
WriteRegisterWithIndex16(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PUSHORT Pointer;
|
|
|
|
Pointer = (PUSHORT)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_REGISTER_USHORT(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadRegisterWithIndex16(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PUSHORT Pointer;
|
|
|
|
Pointer = (PUSHORT)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_REGISTER_USHORT(Pointer);
|
|
}
|
|
|
|
static VOID
|
|
WriteRegisterWithIndex32(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PULONG Pointer;
|
|
|
|
Pointer = (PULONG)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_REGISTER_ULONG(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadRegisterWithIndex32(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PULONG Pointer;
|
|
|
|
Pointer = (PULONG)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_REGISTER_ULONG(Pointer);
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
|
|
static VOID
|
|
WriteRegisterWithIndex64(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PULONG64 Pointer;
|
|
|
|
Pointer = (PULONG64)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_REGISTER_ULONG64(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadRegisterWithIndex64(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PULONG64 Pointer;
|
|
|
|
Pointer = (PULONG64)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_REGISTER_ULONG64(Pointer);
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Port I/O Functions. (Only available on architectures that have I/O ports.)
|
|
//
|
|
|
|
#if defined(_X86_) || defined(_AMD64_)
|
|
|
|
static VOID
|
|
WritePortWithIndex8(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PUCHAR Pointer;
|
|
|
|
Pointer = (PUCHAR)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_PORT_UCHAR(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadPortWithIndex8(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PUCHAR Pointer;
|
|
|
|
Pointer = (PUCHAR)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_PORT_UCHAR(Pointer);
|
|
}
|
|
|
|
static VOID
|
|
WritePortWithIndex16(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PUSHORT Pointer;
|
|
|
|
Pointer = (PUSHORT)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_PORT_USHORT(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadPortWithIndex16(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PUSHORT Pointer;
|
|
|
|
Pointer = (PUSHORT)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_PORT_USHORT(Pointer);
|
|
}
|
|
|
|
static VOID
|
|
WritePortWithIndex32(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index,
|
|
const UCHAR Value)
|
|
{
|
|
PULONG Pointer;
|
|
|
|
Pointer = (PULONG)(Port->Address + Index * Port->ByteWidth);
|
|
WRITE_PORT_ULONG(Pointer, Value);
|
|
return;
|
|
}
|
|
|
|
static UCHAR
|
|
ReadPortWithIndex32(
|
|
_In_ PCPPORT Port,
|
|
const UCHAR Index)
|
|
{
|
|
PULONG Pointer;
|
|
|
|
Pointer = (PULONG)(Port->Address + Index * Port->ByteWidth);
|
|
return (UCHAR)READ_PORT_ULONG(Pointer);
|
|
}
|
|
|
|
#endif
|
|
|
|
BOOLEAN
|
|
UartpSetAccess(
|
|
_Inout_ PCPPORT Port,
|
|
const BOOLEAN MemoryMapped,
|
|
const UCHAR AccessSize,
|
|
const UCHAR BitWidth)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the access type (port I/O or memory mapped I/O), access
|
|
size and bit width for the given port. This routine must be called before
|
|
attempting to access the UART hardware.
|
|
|
|
Arguments:
|
|
|
|
Port - Supplies a pointer to the structure that holds the port's state.
|
|
|
|
MemoryMapped - TRUE if the port uses MMIO, FALSE if it uses legacy port I/O.
|
|
|
|
AccessSize - Supplies the ACPI Generic Access Size of the register's bus.
|
|
|
|
BitWidth - Supplies the size in bits of the device's registers.
|
|
|
|
Return value:
|
|
|
|
TRUE if the pointers were assigned, FALSE if a parameter was not valid.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR MinRegisterWidth;
|
|
BOOLEAN PowerOfTwo;
|
|
UART_HARDWARE_READ_INDEXED_UCHAR ReadFunction;
|
|
UART_HARDWARE_WRITE_INDEXED_UCHAR WriteFunction;
|
|
|
|
MinRegisterWidth = 8;
|
|
|
|
//
|
|
// Select the appropriate port access routines depending upon whether this
|
|
// serial port is mapped into memory or I/O space.
|
|
//
|
|
|
|
if (MemoryMapped == FALSE)
|
|
{
|
|
switch ((ACPI_GENERIC_ACCESS_SIZE)AccessSize)
|
|
{
|
|
#if defined(_X86_) || defined(_AMD64_)
|
|
|
|
case AcpiGenericAccessSizeLegacy:
|
|
__fallthrough;
|
|
|
|
case AcpiGenericAccessSizeByte:
|
|
WriteFunction = WritePortWithIndex8;
|
|
ReadFunction = ReadPortWithIndex8;
|
|
break;
|
|
|
|
case AcpiGenericAccessSizeWord:
|
|
WriteFunction = WritePortWithIndex16;
|
|
ReadFunction = ReadPortWithIndex16;
|
|
MinRegisterWidth = 16;
|
|
break;
|
|
|
|
case AcpiGenericAccessSizeDWord:
|
|
WriteFunction = WritePortWithIndex32;
|
|
ReadFunction = ReadPortWithIndex32;
|
|
MinRegisterWidth = 32;
|
|
break;
|
|
|
|
//
|
|
// The quad word access size isn't supported for port based I/O.
|
|
//
|
|
|
|
#endif
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ((ACPI_GENERIC_ACCESS_SIZE)AccessSize)
|
|
{
|
|
case AcpiGenericAccessSizeLegacy:
|
|
__fallthrough;
|
|
|
|
case AcpiGenericAccessSizeByte:
|
|
WriteFunction = WriteRegisterWithIndex8;
|
|
ReadFunction = ReadRegisterWithIndex8;
|
|
break;
|
|
|
|
case AcpiGenericAccessSizeWord:
|
|
WriteFunction = WriteRegisterWithIndex16;
|
|
ReadFunction = ReadRegisterWithIndex16;
|
|
MinRegisterWidth = 16;
|
|
break;
|
|
|
|
case AcpiGenericAccessSizeDWord:
|
|
WriteFunction = WriteRegisterWithIndex32;
|
|
ReadFunction = ReadRegisterWithIndex32;
|
|
MinRegisterWidth = 32;
|
|
break;
|
|
|
|
#if defined(_WIN64)
|
|
|
|
case AcpiGenericAccessSizeQWord:
|
|
WriteFunction = WriteRegisterWithIndex64;
|
|
ReadFunction = ReadRegisterWithIndex64;
|
|
MinRegisterWidth = 64;
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate BitWidth parameter.
|
|
//
|
|
|
|
PowerOfTwo = ((BitWidth & (BitWidth - 1)) == 0);
|
|
if ((PowerOfTwo == FALSE) ||
|
|
(BitWidth < MinRegisterWidth) ||
|
|
(BitWidth > MAX_REGISTER_WIDTH))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Port->ByteWidth = BitWidth / 8;
|
|
Port->Write = WriteFunction;
|
|
Port->Read = ReadFunction;
|
|
return TRUE;
|
|
}
|