mirror of
https://github.com/Idov31/NovaHypervisor
synced 2026-06-06 15:54:26 +00:00
246 lines
6.8 KiB
C++
246 lines
6.8 KiB
C++
#include "pch.h"
|
|
#include "ComLogger.h"
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::Initialize(_In_ USHORT port) noexcept {
|
|
port_ = port;
|
|
|
|
WriteRegister(InterruptEnableRegister, 0x00);
|
|
WriteRegister(LineControlRegister, DivisorLatchAccessBit);
|
|
WriteRegister(0, 0x01);
|
|
WriteRegister(InterruptEnableRegister, 0x00);
|
|
WriteRegister(LineControlRegister, 0x03);
|
|
WriteRegister(FifoControlRegister, 0xC7);
|
|
WriteRegister(ModemControlRegister, 0x0B);
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::Write(_In_ Level level, _In_z_ const char* format, ...) noexcept {
|
|
va_list args;
|
|
va_start(args, format);
|
|
VWrite(level, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::VWrite(_In_ Level level, _In_z_ const char* format, _In_ va_list args) noexcept {
|
|
char message[MessageBufferSize] = { 0 };
|
|
|
|
FormatMessage(message, sizeof(message), format, args);
|
|
|
|
if (!TryAcquireWriteLock())
|
|
return;
|
|
|
|
WriteString(PrefixForLevel(level), MessageBufferSize);
|
|
WriteString(message, sizeof(message));
|
|
WriteString("\r\n", 3);
|
|
ReleaseWriteLock();
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::WriteRegister(_In_ USHORT offset, _In_ UCHAR value) const noexcept {
|
|
__outbyte(static_cast<USHORT>(port_ + offset), value);
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
UCHAR ComLogger::ReadRegister(_In_ USHORT offset) const noexcept {
|
|
return __inbyte(static_cast<USHORT>(port_ + offset));
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
bool ComLogger::WaitUntilTransmitReady() const noexcept {
|
|
for (ULONG attempt = 0; attempt < TransmitReadyRetries; ++attempt) {
|
|
if ((ReadRegister(LineStatusRegister) & LineStatusTransmitEmpty) != 0)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::WriteChar(_In_ char value) const noexcept {
|
|
if (WaitUntilTransmitReady())
|
|
WriteRegister(0, static_cast<UCHAR>(value));
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::WriteString(_In_reads_or_z_(maximumLength) const char* value, _In_ SIZE_T maximumLength) const noexcept {
|
|
if (!value)
|
|
return;
|
|
|
|
for (SIZE_T index = 0; index < maximumLength && value[index] != '\0'; ++index)
|
|
WriteChar(value[index]);
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
bool ComLogger::TryAcquireWriteLock() noexcept {
|
|
for (ULONG attempt = 0; attempt < WriteLockRetries; ++attempt) {
|
|
if (InterlockedCompareExchange(&writeLock_, 1, 0) == 0)
|
|
return true;
|
|
|
|
_mm_pause();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
_IRQL_requires_max_(HIGH_LEVEL)
|
|
void ComLogger::ReleaseWriteLock() noexcept {
|
|
InterlockedExchange(&writeLock_, 0);
|
|
}
|
|
|
|
void ComLogger::AppendChar(_Inout_updates_(bufferSize) char* buffer, _In_ SIZE_T bufferSize,
|
|
_Inout_ SIZE_T& offset, _In_ char value) const noexcept {
|
|
if (!buffer || bufferSize == 0 || offset >= bufferSize - 1)
|
|
return;
|
|
|
|
buffer[offset++] = value;
|
|
buffer[offset] = '\0';
|
|
}
|
|
|
|
void ComLogger::AppendString(_Inout_updates_(bufferSize) char* buffer, _In_ SIZE_T bufferSize,
|
|
_Inout_ SIZE_T& offset, _In_reads_or_z_(maximumLength) const char* value,
|
|
_In_ SIZE_T maximumLength) const noexcept {
|
|
if (!value) {
|
|
value = "(null)";
|
|
maximumLength = 6;
|
|
}
|
|
|
|
for (SIZE_T index = 0; index < maximumLength && value[index] != '\0'; ++index)
|
|
AppendChar(buffer, bufferSize, offset, value[index]);
|
|
}
|
|
|
|
void ComLogger::AppendUnsigned(_Inout_updates_(bufferSize) char* buffer, _In_ SIZE_T bufferSize,
|
|
_Inout_ SIZE_T& offset, _In_ UINT64 value, _In_ ULONG radix,
|
|
_In_ bool uppercase) const noexcept {
|
|
char digits[32] = { 0 };
|
|
SIZE_T digitCount = 0;
|
|
|
|
if (radix < 2 || radix > 16)
|
|
return;
|
|
|
|
do {
|
|
char digit = HexDigits[value % radix];
|
|
if (uppercase && digit >= 'a' && digit <= 'f')
|
|
digit = static_cast<char>(digit - ('a' - 'A'));
|
|
digits[digitCount++] = digit;
|
|
value /= radix;
|
|
} while (value != 0 && digitCount < RTL_NUMBER_OF(digits));
|
|
|
|
while (digitCount > 0) {
|
|
--digitCount;
|
|
|
|
if (digitCount > RTL_NUMBER_OF(digits))
|
|
break;
|
|
AppendChar(buffer, bufferSize, offset, digits[digitCount]);
|
|
}
|
|
}
|
|
|
|
void ComLogger::AppendSigned(_Inout_updates_(bufferSize) char* buffer, _In_ SIZE_T bufferSize,
|
|
_Inout_ SIZE_T& offset, _In_ INT64 value) const noexcept {
|
|
UINT64 magnitude = static_cast<UINT64>(value);
|
|
|
|
if (value < 0) {
|
|
AppendChar(buffer, bufferSize, offset, '-');
|
|
magnitude = 0 - magnitude;
|
|
}
|
|
|
|
AppendUnsigned(buffer, bufferSize, offset, magnitude, 10, false);
|
|
}
|
|
|
|
void ComLogger::FormatMessage(_Out_writes_z_(bufferSize) char* buffer, _In_ SIZE_T bufferSize,
|
|
_In_z_ const char* format, _In_ va_list args) const noexcept {
|
|
SIZE_T offset = 0;
|
|
|
|
if (!buffer || bufferSize == 0)
|
|
return;
|
|
|
|
buffer[0] = '\0';
|
|
|
|
if (!format) {
|
|
AppendString(buffer, bufferSize, offset, "null log format string", MessageBufferSize);
|
|
return;
|
|
}
|
|
|
|
for (SIZE_T index = 0; format[index] != '\0'; ++index) {
|
|
if (format[index] != '%') {
|
|
AppendChar(buffer, bufferSize, offset, format[index]);
|
|
continue;
|
|
}
|
|
|
|
++index;
|
|
|
|
if (format[index] == '%') {
|
|
AppendChar(buffer, bufferSize, offset, '%');
|
|
continue;
|
|
}
|
|
|
|
while (format[index] >= '0' && format[index] <= '9')
|
|
++index;
|
|
|
|
bool longLongArgument = false;
|
|
bool longArgument = false;
|
|
if (format[index] == 'l') {
|
|
longArgument = true;
|
|
++index;
|
|
if (format[index] == 'l') {
|
|
longLongArgument = true;
|
|
++index;
|
|
}
|
|
}
|
|
|
|
switch (format[index]) {
|
|
case 'd':
|
|
case 'i':
|
|
AppendSigned(buffer, bufferSize, offset,
|
|
longLongArgument ? va_arg(args, INT64) :
|
|
longArgument ? va_arg(args, long) : va_arg(args, int));
|
|
break;
|
|
case 'u':
|
|
AppendUnsigned(buffer, bufferSize, offset,
|
|
longLongArgument ? va_arg(args, UINT64) :
|
|
longArgument ? va_arg(args, unsigned long) : va_arg(args, unsigned int), 10, false);
|
|
break;
|
|
case 'x':
|
|
AppendUnsigned(buffer, bufferSize, offset,
|
|
longLongArgument ? va_arg(args, UINT64) :
|
|
longArgument ? va_arg(args, unsigned long) : va_arg(args, unsigned int), 16, false);
|
|
break;
|
|
case 'X':
|
|
AppendUnsigned(buffer, bufferSize, offset,
|
|
longLongArgument ? va_arg(args, UINT64) :
|
|
longArgument ? va_arg(args, unsigned long) : va_arg(args, unsigned int), 16, true);
|
|
break;
|
|
case 'p':
|
|
AppendString(buffer, bufferSize, offset, "0x", 2);
|
|
AppendUnsigned(buffer, bufferSize, offset, reinterpret_cast<UINT64>(va_arg(args, PVOID)), 16, false);
|
|
break;
|
|
case 's':
|
|
AppendString(buffer, bufferSize, offset, va_arg(args, const char*), MessageBufferSize);
|
|
break;
|
|
default:
|
|
AppendChar(buffer, bufferSize, offset, '%');
|
|
if (longArgument) {
|
|
AppendChar(buffer, bufferSize, offset, 'l');
|
|
if (longLongArgument)
|
|
AppendChar(buffer, bufferSize, offset, 'l');
|
|
}
|
|
AppendChar(buffer, bufferSize, offset, format[index]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char* ComLogger::PrefixForLevel(_In_ Level level) const noexcept {
|
|
switch (level) {
|
|
case Level::Debug:
|
|
return "[NovaHypervisor][DEBUG] ";
|
|
case Level::Info:
|
|
return "[NovaHypervisor][INFO] ";
|
|
case Level::Error:
|
|
return "[NovaHypervisor][ERROR] ";
|
|
default:
|
|
return "[NovaHypervisor][ERROR] ";
|
|
}
|
|
}
|