xbox-kernel/private/ntos/net/halx.cpp
2020-09-30 17:17:25 +02:00

224 lines
5.9 KiB
C++

// ---------------------------------------------------------------------------------------
// halx.cpp
//
// Copyright (C) Microsoft Corporation
// ---------------------------------------------------------------------------------------
#include "xnp.h"
#include "xnver.h"
#ifdef XNET_FEATURE_XBOX
//
// Linker directive to merge XNET_RD section into XNET section
//
#pragma comment(linker, "/merge:XNET_RD=XNET")
// ---------------------------------------------------------------------------------------
// TCHECK
// ---------------------------------------------------------------------------------------
#ifdef XNET_FEATURE_ASSERT
KIRQL CXnHal::KeRaiseIrqlToDpcLevel()
{
KIRQL kirql = ::KeRaiseIrqlToDpcLevel();
if (kirql == PASSIVE_LEVEL)
{
_fUserDpc = TRUE;
}
return(kirql);
}
void CXnHal::KeLowerIrql(KIRQL kirql)
{
if (kirql == PASSIVE_LEVEL)
{
_fUserDpc = FALSE;
}
::KeLowerIrql(kirql);
}
BOOL CXnHal::HalThreadCheck(UINT uiCheck)
{
KIRQL kirql = KeGetCurrentIrql();
if (kirql != DISPATCH_LEVEL)
return(uiCheck & USER);
else if (_fUserDpc)
return(uiCheck & UDPC);
else
return(uiCheck & SDPC);
}
#endif
// ---------------------------------------------------------------------------------------
// SetInitFlag
// ---------------------------------------------------------------------------------------
void CXnHal::SetInitFlag(DWORD dwFlag)
{
DWORD dwFlagsOld, dwFlagsNew;
while (1)
{
dwFlagsOld = _dwInitFlags;
Assert((dwFlagsOld & dwFlag) == 0);
dwFlagsNew = dwFlagsOld | dwFlag;
if (InterlockedCompareExchange((LONG *)&_dwInitFlags, (LONG)dwFlagsNew, (LONG)dwFlagsOld) == (LONG)dwFlagsOld)
break;
TraceSz(Warning, "CXnHal::SetInitFlag: Thread/DPC contention. Retrying.");
}
}
// ---------------------------------------------------------------------------------------
// QueryTsc, HalQueryTsc
// ---------------------------------------------------------------------------------------
__declspec(naked) static void QueryTsc(LARGE_INTEGER * pli)
{
_asm {
mov ecx, [esp+4]
rdtsc
mov [ecx], eax
mov [ecx+4], edx
ret 4
}
}
void HalQueryTsc(LARGE_INTEGER * pli)
{
QueryTsc(pli);
}
// ---------------------------------------------------------------------------------------
// HalRandGather
// ---------------------------------------------------------------------------------------
struct CRandBytes
{
BYTE * _pb;
UINT _cb;
INLINE void Init(BYTE * pb, UINT cb) { _pb = pb; _cb = cb; }
INLINE void AddDword(DWORD dw) { Add(&dw, sizeof(DWORD)); }
INLINE void AddWord(WORD w) { Add(&w, sizeof(WORD)); }
INLINE void AddByte(BYTE b) { Add(&b, sizeof(BYTE)); }
void Add(void * pv, UINT cb);
};
void CRandBytes::Add(void * pv, UINT cb)
{
AssertSz(_cb >= cb, "HalRandGather has more randomness than the buffer has room");
if (_cb >= cb)
{
memcpy(_pb, pv, cb);
_pb += cb;
_cb -= cb;
}
}
UINT CXnHal::HalRandGather(BYTE * pb, UINT cb)
{
LARGE_INTEGER liPerfCount;
CRandBytes randbytes;
// We shouldn't need to initialize liPerfCount, but the compiler is stupid,
// and if we don't initialize it, the compiler will fail to computs its
// live range and will put it in the same place on the stack as randbytes.
liPerfCount.QuadPart = 0;
randbytes.Init(pb, cb);
// ** indicates US DoD's specific recommendations for password generation
// ** ticks since boot (system clock)
DWORD dwTickBegin = NtGetTickCount();
randbytes.AddDword(dwTickBegin);
// ** system time
LARGE_INTEGER liTime;
KeQuerySystemTime(&liTime);
randbytes.Add(&liTime, sizeof(liTime));
// ** hi-res performance counter (system counters)
QueryTsc(&liPerfCount);
randbytes.AddDword(liPerfCount.LowPart ^ liPerfCount.HighPart);
// memory status
MM_STATISTICS mstMemStat;
MmQueryStatistics(&mstMemStat);
randbytes.AddWord(LOWORD(mstMemStat.AvailablePages));
randbytes.AddWord(LOWORD(mstMemStat.PoolPagesCommitted));
randbytes.AddByte(HIBYTE(LOWORD(mstMemStat.VirtualMemoryBytesReserved)));
#ifndef XNET_FEATURE_XBDM_SERVER
// Free disk space
ULARGE_INTEGER ulintDriveFreeSpace;
ULARGE_INTEGER ulintTemp;
ULARGE_INTEGER ulintDiskFreeSpace;
if (GetDiskFreeSpaceEx("T:", &ulintDriveFreeSpace, &ulintTemp, &ulintDiskFreeSpace))
{
randbytes.Add(&ulintDriveFreeSpace, sizeof(ulintDriveFreeSpace));
randbytes.Add(&ulintDiskFreeSpace, sizeof(ulintDiskFreeSpace));
}
#endif // XBDM
// EEPROM values
BYTE buf[EEPROM_TOTAL_MEMORY_SIZE];
NTSTATUS status;
DWORD type, size;
status = ExQueryNonVolatileSetting(XC_MAX_ALL, &type, buf, sizeof(buf), &size);
if (NT_SUCCESS(status))
{
Assert(type == REG_BINARY);
Assert(size == EEPROM_TOTAL_MEMORY_SIZE);
randbytes.Add(buf, size);
}
// Use hard drive model and serial number
randbytes.Add(HalDiskModelNumber->Buffer, HalDiskModelNumber->Length);
randbytes.Add(HalDiskSerialNumber->Buffer, HalDiskSerialNumber->Length);
return(cb - randbytes._cb);
}
// ---------------------------------------------------------------------------------------
// DbgPrintToKd
// ---------------------------------------------------------------------------------------
#ifdef XNET_FEATURE_XBDM_SERVER
void DbgPrintToKd(const char * psz)
{
STRING st, *pst;
st.Buffer = (PCHAR)psz;
st.Length = (USHORT)strlen(psz);
st.MaximumLength = st.Length + 1;
pst = &st;
_asm {
mov eax, BREAKPOINT_KDPRINT
mov ecx, pst
int 2dh
int 3
}
}
#endif
// ---------------------------------------------------------------------------------------
#endif