1859 lines
54 KiB
C++
1859 lines
54 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// undump.cpp - Minidump Kernel Expander
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
typedef int INT;
|
|
typedef char INT8, *PINT8;
|
|
typedef short INT16, *PINT16;
|
|
typedef long INT32, *PINT32;
|
|
typedef __int64 INT64, *PINT64;
|
|
typedef long LARGEST;
|
|
typedef char CHAR, *PCHAR;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned char UINT8, *PUINT8;
|
|
typedef unsigned short UINT16, *PUINT16;
|
|
typedef unsigned long UINT32, *PUINT32;
|
|
typedef unsigned __int64 UINT64, *PUINT64;
|
|
typedef unsigned long ULARGEST;
|
|
typedef unsigned short WCHAR;
|
|
typedef unsigned char UCHAR;
|
|
typedef int BOOL;
|
|
typedef void *PVOID;
|
|
typedef UINT32 ULONG_PTR;
|
|
typedef UINT32 UINTPTR;
|
|
|
|
#define NULL 0
|
|
#define arrayof(a) (sizeof(a)/sizeof(a[0]))
|
|
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
|
|
|
#define DO_ACPI 1
|
|
//#define DEBUG 1
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
/////////////////////////////////////////// Core types used by runtime system.
|
|
//
|
|
|
|
extern "C" ULONG_PTR _security_cookie = 0;
|
|
|
|
typedef __wchar_t bartok_char;
|
|
|
|
typedef signed char int8;
|
|
typedef signed short int16;
|
|
typedef signed int int32;
|
|
typedef __int64 int64;
|
|
|
|
typedef unsigned char uint8;
|
|
typedef unsigned short uint16;
|
|
typedef unsigned int uint32;
|
|
typedef unsigned __int64 uint64;
|
|
|
|
typedef float float32;
|
|
typedef double float64;
|
|
|
|
typedef int intptr;
|
|
typedef unsigned int uintptr;
|
|
|
|
struct uintPtr
|
|
{
|
|
uintptr value;
|
|
};
|
|
|
|
struct intPtr
|
|
{
|
|
intptr value;
|
|
};
|
|
|
|
typedef struct uintPtr *UIntPtr;
|
|
typedef struct intPtr *IntPtr;
|
|
|
|
/////////////////////////////////////////////////////////////// Static Assert.
|
|
//
|
|
// Compile-time (not run-time) assertion. Code will not compile if
|
|
// expr is false. Note: there is no non-debug version of this; we
|
|
// want this for all builds. The compiler optimizes the code away.
|
|
//
|
|
template <bool x> struct STATIC_ASSERT_FAILURE;
|
|
template <> struct STATIC_ASSERT_FAILURE<true> { };
|
|
template <int x> struct static_assert_test { };
|
|
|
|
#define STATIC_CAT_INNER(x,y) x##y
|
|
#define STATIC_CAT(x,y) STATIC_CAT_INNER(x,y)
|
|
|
|
#define STATIC_ASSERT(condition) \
|
|
typedef static_assert_test< \
|
|
sizeof(STATIC_ASSERT_FAILURE<(bool)(condition)>)> \
|
|
STATIC_CAT(__static_assert_typedef_, __COUNTER__)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
#define OFFSETOF(s,m) ((uintptr)&(((s *)0)->m))
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
#pragma warning(disable: 4103)
|
|
#pragma pack(push, 4)
|
|
#include "halclass.h"
|
|
#pragma pack(pop)
|
|
|
|
#include "winctx.h"
|
|
#include "minidump.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
#define TEST 1
|
|
|
|
#if TEST
|
|
|
|
typedef unsigned int uint;
|
|
typedef unsigned int UINT;
|
|
typedef signed long LARGEST;
|
|
typedef unsigned long ULARGEST;
|
|
|
|
#include "printf.cpp"
|
|
#include "debug.cpp"
|
|
|
|
UINT64 __fastcall RDMSR(UINT32 msr)
|
|
{
|
|
__asm rdmsr;
|
|
}
|
|
|
|
void WRMSR(UINT32 msr, UINT64 value)
|
|
{
|
|
__asm {
|
|
lea ebx, value;
|
|
mov eax, [ebx+0];
|
|
mov edx, [ebx+4];
|
|
mov ecx, msr;
|
|
wrmsr;
|
|
}
|
|
}
|
|
|
|
// Routine to read Pentium time stamp counter
|
|
_inline _declspec( naked ) UINT64 RDTSC()
|
|
{
|
|
__asm {
|
|
rdtsc;
|
|
ret;
|
|
}
|
|
}
|
|
|
|
void CPUID(UINT32 feature, UINT32 *output)
|
|
{
|
|
__asm {
|
|
mov eax, feature;
|
|
cpuid;
|
|
mov edi, output;
|
|
mov [edi+0], eax;
|
|
mov [edi+4], ebx;
|
|
mov [edi+8], ecx;
|
|
mov [edi+12], edx;
|
|
}
|
|
}
|
|
|
|
void IoSpaceWrite8(UINT16 This, UINT8 Value)
|
|
{
|
|
__asm {
|
|
mov dx,This;
|
|
mov al,Value;
|
|
out dx,al;
|
|
}
|
|
}
|
|
|
|
UINT8 IoSpaceRead8(UINT16 Port)
|
|
{
|
|
UINT8 Value;
|
|
__asm {
|
|
mov dx, Port;
|
|
in al, dx;
|
|
mov Value, al;
|
|
}
|
|
return Value;
|
|
}
|
|
|
|
void FpuInit()
|
|
{
|
|
__asm fninit;
|
|
}
|
|
|
|
UINT8 Sum(UINT8 * pbData, int cbData)
|
|
{
|
|
UINT8 sum = 0;
|
|
|
|
while (cbData-- > 0) {
|
|
sum += *pbData++;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
int Checksum(UINT8 * pbData, int cbData)
|
|
{
|
|
return (Sum(pbData, cbData) == 0);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////// Screen Routines.
|
|
//
|
|
static UINT16 s_wAttr = 0x1f00;
|
|
|
|
void Dim()
|
|
{
|
|
s_wAttr = 0x1800;
|
|
}
|
|
|
|
void Yellow()
|
|
{
|
|
s_wAttr = 0x1e00;
|
|
}
|
|
|
|
void Green()
|
|
{
|
|
s_wAttr = 0x1a00;
|
|
}
|
|
|
|
void Red()
|
|
{
|
|
s_wAttr = 0x1c00;
|
|
}
|
|
|
|
void Normal()
|
|
{
|
|
s_wAttr = 0x1f00;
|
|
}
|
|
|
|
static UINT nCursor = 0;
|
|
|
|
void Halt()
|
|
{
|
|
Yellow();
|
|
printf("Halt.");
|
|
__asm hlt;
|
|
}
|
|
|
|
void Cls()
|
|
{
|
|
BdPrintString("-------------------------------------------------------------------------------\n", 80);
|
|
|
|
for (UINT16 n = 0; n < 4000; n++)
|
|
{
|
|
((UINT16*)0xb8000)[n] = s_wAttr | ' ';
|
|
}
|
|
|
|
nCursor = 0;
|
|
}
|
|
|
|
void __cdecl PutChar(char cOut)
|
|
{
|
|
if (cOut == '\r')
|
|
{
|
|
nCursor -= nCursor % 80;
|
|
}
|
|
else if (cOut == '\n')
|
|
{
|
|
do {
|
|
((UINT16*)0xb8000)[nCursor++] = s_wAttr | ' ';
|
|
} while ((nCursor % 80) != 0);
|
|
}
|
|
else
|
|
{
|
|
((UINT16*)0xb8000)[nCursor++] = (UINT16)(s_wAttr | cOut);
|
|
}
|
|
|
|
while (nCursor >= 4000)
|
|
{
|
|
UINT16 n = 0;
|
|
for (; n < 4000 - 80; n++)
|
|
{
|
|
((UINT16*)0xb8000)[n] = ((UINT16*)0xb8000)[n + 80];
|
|
}
|
|
for (; n < 4000; n++)
|
|
{
|
|
((UINT16*)0xb8000)[n] = s_wAttr | ' ';
|
|
}
|
|
nCursor -= 80;
|
|
}
|
|
|
|
IoSpaceWrite8(0x3d4, 0xe);
|
|
IoSpaceWrite8(0x3d5, (UINT8)(nCursor >> 8));
|
|
IoSpaceWrite8(0x3d4, 0xf);
|
|
IoSpaceWrite8(0x3d5, (UINT8)(nCursor & 0xff));
|
|
|
|
static CHAR szBuffer[256];
|
|
static INT nBuffer = 0;
|
|
|
|
szBuffer[nBuffer++] = cOut;
|
|
if (cOut == '\n' || nBuffer >= sizeof(szBuffer) - 1) {
|
|
BdPrintString(szBuffer, nBuffer);
|
|
nBuffer = 0;
|
|
}
|
|
}
|
|
|
|
void Probe(UINT8 * pbData, UINT cbData)
|
|
{
|
|
UINT8 b;
|
|
|
|
for (UINT i = 0; i < cbData; i++) {
|
|
b = pbData[i];
|
|
pbData[i] = b;
|
|
}
|
|
}
|
|
|
|
void Dump(UINT8 * pbData, UINT cbData)
|
|
{
|
|
for (UINT n = 0; n < cbData; n += 16) {
|
|
printf(" %08x:", pbData + n);
|
|
UINT o = n;
|
|
for (; o < n + 16; o++) {
|
|
if (o >= cbData) {
|
|
printf(" ");
|
|
}
|
|
else {
|
|
printf("%02x", pbData[o]);
|
|
}
|
|
if (o % 4 == 3) {
|
|
printf(" ");
|
|
}
|
|
}
|
|
printf(" ");
|
|
for (o = n; o < n + 16; o++) {
|
|
if (o >= cbData) {
|
|
printf(" ");
|
|
}
|
|
else {
|
|
if (pbData[o] >= ' ' && pbData[o] < 127) {
|
|
printf("%c", pbData[o]);
|
|
}
|
|
else {
|
|
printf(".");
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
void Dump(UINT8 * pbData, UINT8 * pbLimit, UINT cbMax)
|
|
{
|
|
UINT cbData = (uint) (pbLimit - pbData);
|
|
if (cbData > cbMax) {
|
|
cbData = cbMax;
|
|
}
|
|
Dump(pbData, cbData);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static void CopyUp(UINT8 *pbDst, UINT8 *pbSrc, UINT32 cbSrc)
|
|
{
|
|
//!!! pbDst >= pbSrc
|
|
if (pbDst < pbSrc) {
|
|
printf("CopyUp(dst=%p < src=%p)\n", pbDst, pbSrc);
|
|
Halt();
|
|
}
|
|
|
|
INT32 nSrc = (cbSrc + 3) / 4;
|
|
UINT32 *pDst = ((UINT32*)pbDst) + nSrc;
|
|
UINT32 *pSrc = ((UINT32*)pbSrc) + nSrc;
|
|
|
|
while (nSrc-- > 0) {
|
|
*--pDst = *--pSrc;
|
|
}
|
|
}
|
|
|
|
static void CopyDown(UINT8 *pbDst, UINT8 *pbSrc, UINT32 cbSrc)
|
|
{
|
|
//!!! pbDst <= pbSrc
|
|
if (pbDst > pbSrc) {
|
|
printf("CopyDown(dst=%p > src=%p)\n", pbDst, pbSrc);
|
|
Halt();
|
|
}
|
|
|
|
INT32 nSrc = (cbSrc + 3) / 4;
|
|
volatile UINT32 *pDst = (UINT32*)pbDst;
|
|
volatile UINT32 *pSrc = (UINT32*)pbSrc;
|
|
|
|
while (nSrc-- > 0) {
|
|
*pDst = *pSrc;
|
|
if (*pDst != *pSrc) {
|
|
printf("CopyDown error at %p/%p : %08x != %08x\n",
|
|
pDst, pSrc, *pDst, *pSrc);
|
|
Halt();
|
|
}
|
|
pDst++;
|
|
pSrc++;
|
|
}
|
|
}
|
|
|
|
const char * SmapTypeToString(int type)
|
|
{
|
|
switch (type) {
|
|
case 1: return "RAM ";
|
|
case 2: return "Reserved";
|
|
case 3: return "ACPI RAM";
|
|
case 4: return "ACPI NVS";
|
|
default: return "Other ";
|
|
}
|
|
}
|
|
|
|
bool check(UINT8 *pbCache, UINT8 value, const char *pszDesc)
|
|
{
|
|
for (int i = 0; i < 16; i++) {
|
|
if (pbCache[i] == value) {
|
|
pbCache[i] = 0;
|
|
printf(" %s\n", pszDesc);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int wcseq(UINT16 * pwzData, UINT16 * pwzKnown)
|
|
{
|
|
while (*pwzData && *pwzKnown && *pwzData == *pwzKnown) {
|
|
pwzData++;
|
|
pwzKnown++;
|
|
}
|
|
return (*pwzData == *pwzKnown);
|
|
}
|
|
|
|
static int wcslen(UINT16 *pwz)
|
|
{
|
|
int len = 0;
|
|
|
|
while (*pwz++) {
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
static int wcsfindcmd(UINT16 *pwzCmd, UINT16 *pwzKnown)
|
|
{
|
|
for (;;) {
|
|
int len = wcslen(pwzCmd);
|
|
if (len == 0) {
|
|
return 0;
|
|
}
|
|
if (wcseq(pwzCmd, pwzKnown) != 0) {
|
|
return 1;
|
|
}
|
|
|
|
pwzCmd += len + 1;
|
|
}
|
|
}
|
|
|
|
#if DO_ACPI
|
|
#include "acpi/acpi.cpp"
|
|
#endif
|
|
|
|
static void CheckPci(const Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
///////////////////////////////////////////////// Check for Compatibility.
|
|
//
|
|
if ((bi->PciBiosAX >> 8) != 0 || (bi->PciBiosEDX != 0x20494350)) {
|
|
Yellow();
|
|
printf("Hardware does not support PCI V2.x.\n");
|
|
printf("PCI V2.x: AX:%04x, BX:%04x, CX:%04x, EDX:%08x\n",
|
|
bi->PciBiosAX, bi->PciBiosBX, bi->PciBiosCX, bi->PciBiosEDX);
|
|
Halt();
|
|
}
|
|
if (!(bi->PciBiosAX & 0x01)) {
|
|
Yellow();
|
|
printf("Hardware does not support multiple PCI buses.\n");
|
|
printf("PCI V2.x: AX:%04x, BX:%04x, CX:%04x, EDX:%08x\n",
|
|
bi->PciBiosAX, bi->PciBiosBX, bi->PciBiosCX, bi->PciBiosEDX);
|
|
Halt();
|
|
}
|
|
|
|
}
|
|
|
|
static bool CheckSmapForRam(const Struct_Microsoft_Singularity_BootInfo *bi, UINT64 base, UINT64 size)
|
|
{
|
|
Struct_Microsoft_Singularity_SMAPINFO *sm = (Struct_Microsoft_Singularity_SMAPINFO *)bi->SmapData32;
|
|
for (UINT i = 0; i < bi->SmapCount; i++) {
|
|
if (sm[i].type == 1 &&
|
|
sm[i].addr <= base &&
|
|
sm[i].addr + sm[i].size >= base + size) {
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void CheckSmap(const Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
/////////////////////////////////////////////////////// System Memory Map.
|
|
//
|
|
printf(" Base Address Limit Address Type \n");
|
|
printf(" ================ ================ ==========\n");
|
|
|
|
Struct_Microsoft_Singularity_SMAPINFO *sm = (Struct_Microsoft_Singularity_SMAPINFO *)bi->SmapData32;
|
|
for (UINT i = 0; i < bi->SmapCount; i++) {
|
|
printf(" %16lx", (UINT64)sm[i].addr);
|
|
printf(" %16lx", (UINT64)sm[i].addr + (UINT64)sm[i].size);
|
|
printf(" %d:%s\n",
|
|
sm[i].type,
|
|
SmapTypeToString((int)sm[i].type));
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void DumpFeatures(UINT32 features)
|
|
{
|
|
printf(" ");
|
|
if (features & 0x1) { printf("x87 "); }
|
|
if (features & 0x2) { printf("VME "); }
|
|
if (features & 0x4) { printf("DBG "); }
|
|
if (features & 0x8) { printf("PSE "); }
|
|
if (features & 0x10) { printf("TSC "); }
|
|
if (features & 0x20) { printf("MSR "); }
|
|
if (features & 0x40) { printf("PAE "); }
|
|
if (features & 0x80) { printf("MCE "); }
|
|
if (features & 0x100) { printf("CX8 "); }
|
|
if (features & 0x200) { printf("APIC "); }
|
|
if (features & 0x200) { printf("R0 "); }
|
|
if (features & 0x800) { printf("SEP "); }
|
|
if (features & 0x1000) { printf("MTRR "); }
|
|
if (features & 0x2000) { printf("PGE "); }
|
|
if (features & 0x4000) { printf("MCA "); }
|
|
if (features & 0x8000) { printf("CMOV "); }
|
|
printf("\n ");
|
|
if (features & 0x10000) { printf("PAT "); }
|
|
if (features & 0x20000) { printf("PSE36 "); }
|
|
if (features & 0x40000) { printf("PSN "); }
|
|
if (features & 0x80000) { printf("CFLUSH "); }
|
|
if (features & 0x100000) { printf("R1 "); }
|
|
if (features & 0x200000) { printf("DS "); }
|
|
if (features & 0x400000) { printf("ACPI "); }
|
|
if (features & 0x800000) { printf("MMX "); }
|
|
if (features & 0x1000000) { printf("FXSR "); }
|
|
if (features & 0x2000000) { printf("SSE "); }
|
|
if (features & 0x4000000) { printf("SSE2 "); }
|
|
if (features & 0x8000000) { printf("SS "); }
|
|
if (features & 0x10000000) { printf("HTT "); }
|
|
if (features & 0x20000000) { printf("TM "); }
|
|
if (features & 0x40000000) { printf("R2 "); }
|
|
if (features & 0x80000000) { printf("PBE "); }
|
|
printf("\n");
|
|
}
|
|
|
|
static void CheckCpuid(const Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
/////////////////////////////////////////////////////////////////// CPUID.
|
|
#if 1
|
|
{
|
|
UINT32 output[4];
|
|
|
|
CPUID(1, output);
|
|
|
|
UINT family = (output[0] & 0xf00) >> 8;
|
|
UINT model = (output[0] & 0x0f0) >> 4;
|
|
UINT step = (output[0] & 0x00f);
|
|
UINT brand = (output[1] & 0xff);
|
|
|
|
if (family == 0xf) {
|
|
family += (output[0] & 0xff00000) >> 24;
|
|
}
|
|
if (model == 0xf) {
|
|
model += (output[0] & 0xf0000) >> 16;
|
|
}
|
|
|
|
CPUID(0, output);
|
|
printf("CPUID: %c%c%c%c%c%c%c%c%c%c%c%c Family %d, Model %d, Step %d, Brand %d\n",
|
|
((char *)output)[4],
|
|
((char *)output)[5],
|
|
((char *)output)[6],
|
|
((char *)output)[7],
|
|
((char *)output)[12],
|
|
((char *)output)[13],
|
|
((char *)output)[14],
|
|
((char *)output)[15],
|
|
((char *)output)[8],
|
|
((char *)output)[9],
|
|
((char *)output)[10],
|
|
((char *)output)[11],
|
|
family, model, step, brand);
|
|
|
|
UINT32 max = output[0];
|
|
for (UINT32 i = 3; i <= max; i++) {
|
|
CPUID(i, output);
|
|
printf(" %08x: %08x %08x %08x %08x\n",
|
|
i, output[0], output[1], output[2], output[3]);
|
|
}
|
|
|
|
CPUID(1, output);
|
|
#if DEBUG
|
|
if ((output[1] & 0xff00) != 0) {
|
|
printf(" CFlush %d bytes\n", ((output[1] & 0xff00) >> 8) * 8);
|
|
}
|
|
if ((output[1] & 0xff0000) != 0) {
|
|
printf(" Hyperthreads: %d\n", (output[1] & 0xff0000) >> 16);
|
|
}
|
|
if ((output[1] & 0xff000000) != 0xff) {
|
|
printf(" Local APIC Id: %d\n", (output[1] & 0xff000000) >> 24);
|
|
}
|
|
#endif
|
|
|
|
printf(" Features: ");
|
|
if (output[2] & 0x80) { printf("EST "); }
|
|
if (output[2] & 0x100) { printf("TM2 "); }
|
|
if (output[2] & 0x400) { printf("L1C "); }
|
|
printf("\n");
|
|
DumpFeatures(output[3]);
|
|
|
|
#if DEBUG
|
|
printf(" Caches:\n");
|
|
|
|
CPUID(2, output);
|
|
for (int j = 0; j < 4; j++) {
|
|
if (output[j] & 0x80000000) {
|
|
output[j] = 0;
|
|
}
|
|
}
|
|
output[0] &= 0xffffff00;
|
|
|
|
UINT8 *pbCache = (UINT8*)output;
|
|
|
|
check(pbCache, 0x01, "ITLB: 4KB Pages, 4-way, 32 entries");
|
|
check(pbCache, 0x02, "ITLB: 4MB Pages, 4-way, 2 entries");
|
|
check(pbCache, 0x03, "DTLB: 4KB Pages, 4-way, 64 entries");
|
|
check(pbCache, 0x04, "DTLB: 4MB Pages, 4-way, 8 entries");
|
|
check(pbCache, 0x06, "L1-I: 8KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x08, "L1-I: 16KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x0A, "L1-D: 8KB, 2-way, 32 byte line size");
|
|
check(pbCache, 0x0C, "L1-D: 16KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x22, "L3 : 512KB, 4-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x23, "L3 : 1MB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x25, "L3 : 2MB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x29, "L3 : 4MB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x2C, "L1-D: 32KB, 8-way, 64 byte line size");
|
|
check(pbCache, 0x30, "L1-I: 32KB, 8-way, 64 byte line size");
|
|
check(pbCache, 0x40, "----: No L2 or, if processor contains a valid L2, no L3");
|
|
check(pbCache, 0x41, "L2 : 128KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x42, "L2 : 256KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x43, "L2 : 512KB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x44, "L2 : 1MB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x45, "L2 : 2MB, 4-way, 32 byte line size");
|
|
check(pbCache, 0x50, "ITLB: 4KB and 4MB pages, 64 entries");
|
|
check(pbCache, 0x51, "ITLB: 4KB and 4MB pages, 128 entries");
|
|
check(pbCache, 0x52, "ITLB: 4KB and 4MB pages, 256 entries");
|
|
check(pbCache, 0x5B, "DTLB: 4KB and 4MB pages, 64 entries");
|
|
check(pbCache, 0x5C, "DTLB: 4KB and 4MB pages, 128 entries");
|
|
check(pbCache, 0x5D, "DTLB: 4KB and 4MB pages, 256 entries");
|
|
check(pbCache, 0x60, "L1-D: 16KB, 8-way, 64 byte line size");
|
|
check(pbCache, 0x66, "L1-D: 8KB, 4-way, 64 byte line size");
|
|
check(pbCache, 0x67, "L1-D: 16KB, 4-way, 64 byte line size");
|
|
check(pbCache, 0x68, "L1-D: 32KB, 4-way, 64 byte line size");
|
|
check(pbCache, 0x70, "TC : 12K-uop, 8-way");
|
|
check(pbCache, 0x71, "TC : 16K-uop, 8-way");
|
|
check(pbCache, 0x72, "TC : 32K-uop, 8-way");
|
|
check(pbCache, 0x78, "L2 : 1MB, 8-way, 64 byte line size");
|
|
check(pbCache, 0x79, "L2 : 128KB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x7A, "L2 : 256KB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x7B, "L2 : 512KB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x7C, "L2 : 1MB, 8-way, 64 byte line size, 128 byte sector size");
|
|
check(pbCache, 0x7D, "L2 : 2MB, 8-way, 64 byte line size");
|
|
check(pbCache, 0x7F, "L2 : 512KB, 2-way, 64 byte line size");
|
|
check(pbCache, 0x82, "L2 : 256KB, 8-way, 32 byte line size");
|
|
check(pbCache, 0x83, "L2 : 512KB, 8-way, 32 byte line size");
|
|
check(pbCache, 0x84, "L2 : 1MB, 8-way, 32 byte line size");
|
|
check(pbCache, 0x85, "L2 : 2MB, 8-way, 32 byte line size");
|
|
check(pbCache, 0x86, "L2 : 512KB, 4-way, 64 byte line size");
|
|
check(pbCache, 0x87, "L2 : 1MB, 8-way, 64 byte line size");
|
|
check(pbCache, 0xB0, "ITLB: 4KB Pages, 4-way, 128 entries");
|
|
check(pbCache, 0xB3, "DTLB: 4KB Pages, 4-way, 128 entries");
|
|
check(pbCache, 0xF0, "----: 64 byte prefetch");
|
|
check(pbCache, 0xF1, "----: 128 byte prefetch");
|
|
|
|
for (int j = 0; j < 16; j++) {
|
|
if (pbCache[j] != 0) {
|
|
printf(" Missed %02x\n", pbCache[j]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
CPUID(0x80000000, output);
|
|
if ((output[0] & 0x80000000)) {
|
|
UINT32 max = output[0];
|
|
#if DEBUG
|
|
printf("Max ext CPUID = %x\n", max);
|
|
for (UINT32 i = 0x80000005; i <= max; i++) {
|
|
CPUID(i, output);
|
|
printf(" %08x: %08x %08x %08x %08x\n",
|
|
i, output[0], output[1], output[2], output[3]);
|
|
}
|
|
#endif
|
|
|
|
CPUID(0x80000001, output);
|
|
if (output[3] != 0) {
|
|
printf(" AMD Features:\n");
|
|
printf(" ");
|
|
if (output[3] & 0x1) { printf("x87 "); }
|
|
if (output[3] & 0x2) { printf("VME "); }
|
|
if (output[3] & 0x4) { printf("DBG "); }
|
|
if (output[3] & 0x8) { printf("PSE "); }
|
|
if (output[3] & 0x10) { printf("TSC "); }
|
|
if (output[3] & 0x20) { printf("MSR "); }
|
|
if (output[3] & 0x40) { printf("PAE "); }
|
|
if (output[3] & 0x80) { printf("MCE "); }
|
|
if (output[3] & 0x100) { printf("CX8 "); }
|
|
if (output[3] & 0x200) { printf("APIC "); }
|
|
if (output[3] & 0x400) { printf("R0 "); }
|
|
if (output[3] & 0x800) { printf("FSEP "); }
|
|
if (output[3] & 0x1000) { printf("MTRR "); }
|
|
if (output[3] & 0x2000) { printf("PGE "); }
|
|
if (output[3] & 0x4000) { printf("MCA "); }
|
|
if (output[3] & 0x8000) { printf("CMOV "); }
|
|
printf("\n ");
|
|
if (output[3] & 0x10000) { printf("PAT "); }
|
|
if (output[3] & 0x20000) { printf("PSE36 "); }
|
|
if (output[3] & 0x40000) { printf("R1 "); }
|
|
if (output[3] & 0x80000) { printf("R2 "); }
|
|
if (output[3] & 0x100000) { printf("NX "); }
|
|
if (output[3] & 0x200000) { printf("R3 "); }
|
|
if (output[3] & 0x400000) { printf("xMMX "); }
|
|
if (output[3] & 0x800000) { printf("MMX "); }
|
|
if (output[3] & 0x1000000) { printf("FXSR "); }
|
|
if (output[3] & 0x2000000) { printf("FFXSR "); }
|
|
if (output[3] & 0x4000000) { printf("R4 "); }
|
|
if (output[3] & 0x8000000) { printf("R5 "); }
|
|
if (output[3] & 0x10000000) { printf("R6 "); }
|
|
if (output[3] & 0x20000000) { printf("LM "); }
|
|
if (output[3] & 0x40000000) { printf("x3D "); }
|
|
if (output[3] & 0x80000000) { printf("3D "); }
|
|
printf("\n");
|
|
}
|
|
|
|
CHAR szBrand[64];
|
|
CPUID(0x80000002, (UINT32*)&szBrand[0]);
|
|
CPUID(0x80000003, (UINT32*)&szBrand[16]);
|
|
CPUID(0x80000004, (UINT32*)&szBrand[32]);
|
|
szBrand[48] = '\0';
|
|
CHAR *pszBrand = szBrand;
|
|
while (*pszBrand == ' ') {
|
|
pszBrand++;
|
|
}
|
|
printf(" Brand: %s\n", pszBrand);
|
|
}
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void CheckApic(const Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
////////////////////////////////////////////////////// Local and I/O APIC.
|
|
//
|
|
#if DEBUG
|
|
UINT32 apicid = 0;
|
|
UINT32 apicver = 0;
|
|
|
|
printf(" IO APIC:\n");
|
|
for (UINT32 base = 0xfec00000; base <= 0xfec0fc00; base += 0x400) {
|
|
__asm {
|
|
mov ebx, base;
|
|
mov eax, 0;
|
|
mov [ebx], eax;
|
|
mov eax, [ebx+0x10];
|
|
mov apicid, eax;
|
|
|
|
mov eax, 1;
|
|
mov [ebx], eax;
|
|
mov eax, [ebx+0x10];
|
|
mov apicver, eax;
|
|
}
|
|
if (apicid == ~0u && apicver == ~0u) {
|
|
continue;
|
|
}
|
|
printf(" %08x: %08x %08x\n", base, apicid, apicver);
|
|
}
|
|
|
|
printf(" Local APIC:\n");
|
|
for (UINT32 base = 0xfee00000; base <= 0xfee00000; base += 0x400) {
|
|
__asm {
|
|
mov ebx, base;
|
|
mov eax, [ebx+0x20];
|
|
mov apicid, eax;
|
|
mov eax, [ebx+0x30];
|
|
mov apicver, eax;
|
|
}
|
|
printf(" %08x: id=%08x ver=%08x\n", base, apicid, apicver);
|
|
}
|
|
|
|
printf(" MSR[0x%02x] = %016lx\n", 0x10, RDMSR(0x10));
|
|
//printf(" MSR[0x%02x] = %016lx\n", 0x17, RDMSR(0x17));
|
|
//printf(" MSR[0x%02x] = %016lx\n", 0x1b, RDMSR(0x1b));
|
|
|
|
printf("\n");
|
|
#endif
|
|
}
|
|
|
|
struct ACPI_RSDP
|
|
{
|
|
CHAR Signature[8]; // "RSD PTR "
|
|
UINT8 Checksum;
|
|
CHAR OemId[6];
|
|
UINT8 Revision;
|
|
UINT32 RsdtAddress;
|
|
UINT32 RsdtLength;
|
|
UINT32 XsdtAddrLo;
|
|
UINT32 XsdtAddrHi;
|
|
UINT8 ExtendedChecksum;
|
|
UINT8 Reserved[3];
|
|
};
|
|
typedef ACPI_RSDP * PACPI_RSDP;
|
|
|
|
int IsAcpiRsdp(PACPI_RSDP pScan)
|
|
{
|
|
if (pScan->Signature[0] != 'R' || pScan->Signature[1] != 'S' ||
|
|
pScan->Signature[2] != 'D' || pScan->Signature[3] != ' ' ||
|
|
pScan->Signature[4] != 'P' || pScan->Signature[5] != 'T' ||
|
|
pScan->Signature[6] != 'R' || pScan->Signature[7] != ' ') {
|
|
|
|
return 0;
|
|
}
|
|
return Checksum((UINT8*)pScan, 20);
|
|
}
|
|
|
|
static void CheckAcpi(Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
/////////////////////////////////////////////////////////// Scan for ACPI.
|
|
//
|
|
PACPI_RSDP pAcpi = NULL;
|
|
|
|
for (UINT8 *pbScan = (UINT8*)0xe0000; pbScan < (UINT8*)0xfffff; pbScan += 0x10) {
|
|
PACPI_RSDP pScan = (PACPI_RSDP)pbScan;
|
|
if (IsAcpiRsdp(pScan)) {
|
|
pAcpi = pScan;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pAcpi == NULL && bi->Ebda32 != NULL) {
|
|
#if 0
|
|
printf("bi->Ebda32 = %08x\n", bi->Ebda32);
|
|
Dump((UINT8*)bi->Ebda32, 0x400);
|
|
#endif
|
|
|
|
for (UINT8 *pbScan = (UINT8*)bi->Ebda32;
|
|
pbScan < (UINT8*)bi->Ebda32 + 0x400; pbScan += 0x10) {
|
|
|
|
PACPI_RSDP pScan = (PACPI_RSDP)pbScan;
|
|
if (IsAcpiRsdp(pScan)) {
|
|
pAcpi = pScan;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bi->AcpiRoot32 = (UINT)pAcpi;
|
|
|
|
#if DO_ACPI
|
|
if (pAcpi != NULL) {
|
|
printf("ACPI Information:\n");
|
|
Acpi(pAcpi);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct MP_FLOAT
|
|
{
|
|
UINT8 Signature[4]; // "_MP_"
|
|
UINT32 AddrMpConfigTable32; //canonical form
|
|
UINT8 Paragraphs;
|
|
UINT8 Version;
|
|
UINT8 Checksum;
|
|
UINT8 Features[5];
|
|
};
|
|
|
|
struct MP_FIXED
|
|
{
|
|
UINT8 Signature[4];
|
|
UINT16 BaseTableSize;
|
|
UINT8 Version;
|
|
UINT8 Checksum;
|
|
UINT8 OemId[8];
|
|
UINT8 ProductId[12];
|
|
UINT32 AddrOemTablePointer; //canonical form
|
|
UINT16 OemTableSize;
|
|
UINT32 LocalAPIC;
|
|
UINT16 ExtendedTableSize;
|
|
UINT8 ExtendedTableChecksum;
|
|
};
|
|
|
|
struct MP_PROCESSOR
|
|
{
|
|
UINT8 EntryType; // == 0x00
|
|
UINT8 ApicId;
|
|
UINT8 ApicVersion;
|
|
UINT8 Flags;
|
|
UINT32 Signature;
|
|
UINT32 Features;
|
|
UINT32 Reserved0;
|
|
UINT32 Reserved1;
|
|
};
|
|
|
|
struct MP_BUS
|
|
{
|
|
UINT8 EntryType; // == 0x01
|
|
UINT8 BusId;
|
|
UINT8 BusType[6];
|
|
};
|
|
|
|
struct MP_IO_APIC
|
|
{
|
|
UINT8 EntryType; // == 0x02
|
|
UINT8 ApicId;
|
|
UINT8 ApicVersion;
|
|
UINT8 Flags;
|
|
UINT32 Address;
|
|
};
|
|
|
|
struct MP_IO_INTERRUPT
|
|
{
|
|
UINT8 EntryType; // == 0x03
|
|
UINT8 Type;
|
|
UINT16 Flags;
|
|
UINT8 SrcBusId;
|
|
UINT8 SrcBusIrq;
|
|
UINT8 DstApicId;
|
|
UINT8 DstApicIrq;
|
|
};
|
|
|
|
struct MP_LOCAL_INTERRUPT
|
|
{
|
|
UINT8 EntryType; // == 0x04
|
|
UINT8 Type;
|
|
UINT16 Flags;
|
|
UINT8 SrcBusId;
|
|
UINT8 SrcBusIrq;
|
|
UINT8 DstApicId;
|
|
UINT8 DstApicIrq;
|
|
};
|
|
|
|
struct MP_ADDRESS_SPACE_MAPPING
|
|
{
|
|
UINT8 EntryType; // == 0x80
|
|
UINT8 EntrySize;
|
|
UINT8 BusId;
|
|
UINT8 AddressType;
|
|
UINT64 AddressBase;
|
|
UINT64 AddressSize;
|
|
};
|
|
|
|
struct MP_BUS_HIERARCHY
|
|
{
|
|
UINT8 EntryType; // == 0x81
|
|
UINT8 EntrySize;
|
|
UINT8 BusId;
|
|
UINT8 BusInfo;
|
|
UINT8 ParentBusId;
|
|
UINT8 Reserved[3];
|
|
};
|
|
|
|
struct MP_ADDRESS_SPACE_MODIFIER
|
|
{
|
|
UINT8 EntryType; // == 0x82
|
|
UINT8 EntrySize;
|
|
UINT8 BusId;
|
|
UINT8 Predefined;
|
|
UINT32 RangeList;
|
|
};
|
|
|
|
int IsMpsFps(MP_FLOAT * pScan)
|
|
{
|
|
if (pScan->Signature[0] != '_' || pScan->Signature[1] != 'M' ||
|
|
pScan->Signature[2] != 'P' || pScan->Signature[3] != '_') {
|
|
|
|
return 0;
|
|
}
|
|
return Checksum((UINT8*)pScan, pScan->Paragraphs * 0x10);
|
|
}
|
|
|
|
MP_FLOAT * ScanForMp(UINT8 * pbBase, UINT8 * pbLimit)
|
|
{
|
|
for (; pbBase < pbLimit; pbBase += 0x10) {
|
|
MP_FLOAT * pScan = (MP_FLOAT *)pbBase;
|
|
if (IsMpsFps(pScan)) {
|
|
return pScan;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void CheckMp(Struct_Microsoft_Singularity_BootInfo *bi)
|
|
{
|
|
printf("MP Information:\n");
|
|
|
|
const UINT16 CMOS_SELECT = 0x70;
|
|
const UINT16 CMOS_DATA = 0x71;
|
|
|
|
IoSpaceWrite8(CMOS_SELECT, 0xf);
|
|
UINT8 boot = IoSpaceRead8(CMOS_DATA);
|
|
#if DEBUG
|
|
printf("CMOS Boot type = %02x\n", boot);
|
|
#endif
|
|
|
|
if ((bi->MpEnter32 & 0xfff00fff) != 0) {
|
|
printf("MpEnter is not valid for IPI Startup: %08x\n", bi->MpEnter32);
|
|
Halt();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////// Scan for MPS.
|
|
//
|
|
MP_FLOAT * pFloat = NULL;
|
|
|
|
if (pFloat == NULL && bi->Ebda32 != NULL) {
|
|
pFloat = ScanForMp((UINT8*)bi->Ebda32, (UINT8*)bi->Ebda32 + 0x400);
|
|
}
|
|
if (pFloat == NULL) {
|
|
pFloat = ScanForMp((UINT8*)0x9fc00, (UINT8*)0xa0000);
|
|
}
|
|
if (pFloat == NULL) {
|
|
pFloat = ScanForMp((UINT8*)0x7fc00, (UINT8*)0x80000);
|
|
}
|
|
if (pFloat == NULL) {
|
|
pFloat = ScanForMp((UINT8*)0xf0000, (UINT8*)0xfffff);
|
|
}
|
|
if (pFloat == NULL) {
|
|
return;
|
|
}
|
|
|
|
printf(" Found MPS Version 1.%d at %lp\n", pFloat->Version, pFloat);
|
|
if (pFloat->Version < 4) {
|
|
pFloat = NULL;
|
|
return;
|
|
}
|
|
bi->MpFloat32 = (UINT32) pFloat;
|
|
|
|
#if DEBUG
|
|
printf(" MpConfigTable32=%x, Features=%02x%02x%02x%02x%02x\n",
|
|
pFloat->AddrMpConfigTable32,
|
|
pFloat->Features[0],
|
|
pFloat->Features[1],
|
|
pFloat->Features[2],
|
|
pFloat->Features[3],
|
|
pFloat->Features[4]);
|
|
#endif
|
|
|
|
if (pFloat->AddrMpConfigTable32) {
|
|
#if DEBUG
|
|
MP_FIXED * pFixed = (MP_FIXED *) pFloat->AddrMpConfigTable32;
|
|
|
|
printf(" %c%c%c%c len=%d ver=%d sum=%02x\n",
|
|
pFixed->Signature[0],
|
|
pFixed->Signature[1],
|
|
pFixed->Signature[2],
|
|
pFixed->Signature[3],
|
|
pFixed->BaseTableSize,
|
|
pFixed->Version,
|
|
pFixed->Checksum);
|
|
printf(" Oem=[%-8.8s] Product=[%-12.12s] table=%x size=%d\n",
|
|
pFixed->OemId,
|
|
pFixed->ProductId,
|
|
pFixed->AddrOemTablePointer,
|
|
pFixed->OemTableSize);
|
|
printf(" LocalAPIC=%08x ExtSize=%d ExtSum=%02x\n",
|
|
pFixed->LocalAPIC,
|
|
pFixed->ExtendedTableSize,
|
|
pFixed->ExtendedTableChecksum);
|
|
|
|
UINT8 *pbBegin = ((UINT8*)pFixed) + sizeof(*pFixed);
|
|
UINT8 *pbLimit = ((UINT8*)pFixed) + pFixed->BaseTableSize;
|
|
|
|
while (pbBegin < pbLimit) {
|
|
printf(" %4d: ", pbBegin - ((UINT8*)pFixed));
|
|
|
|
switch (pbBegin[0]) {
|
|
case 0:
|
|
{
|
|
MP_PROCESSOR *pProc = (MP_PROCESSOR *)pbBegin;
|
|
|
|
printf("Proc Apic=%02x Ver=%02x Flags=%02x Sign=%08x Feat=%08x\n",
|
|
pProc->ApicId,
|
|
pProc->ApicVersion,
|
|
pProc->Flags,
|
|
pProc->Signature,
|
|
pProc->Features);
|
|
DumpFeatures(pProc->Features);
|
|
|
|
pbBegin = (UINT8*)(pProc + 1);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
MP_BUS *pBus = (MP_BUS *)pbBegin;
|
|
|
|
printf("Bus Id=%02x Type=[%-6.6s]\n",
|
|
pBus->BusId,
|
|
pBus->BusType);
|
|
|
|
pbBegin = (UINT8*)(pBus + 1);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
{
|
|
MP_IO_APIC *pApic = (MP_IO_APIC *)pbBegin;
|
|
|
|
printf("Apic Apic=%02x Ver=%02x Flags=%02x Address=%08x\n",
|
|
pApic->ApicId,
|
|
pApic->ApicVersion,
|
|
pApic->Flags,
|
|
pApic->Address);
|
|
|
|
pbBegin = (UINT8*)(pApic + 1);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
MP_IO_INTERRUPT *pInterrupt = (MP_IO_INTERRUPT *)pbBegin;
|
|
|
|
printf("I/O Type=%02x Flags=%04x [Bus=%02x Irq=%02x] -> [Apic=%02x Irq=%02x]\n",
|
|
pInterrupt->Type,
|
|
pInterrupt->Flags,
|
|
pInterrupt->SrcBusId,
|
|
pInterrupt->SrcBusIrq,
|
|
pInterrupt->DstApicId,
|
|
pInterrupt->DstApicIrq);
|
|
|
|
pbBegin = (UINT8*)(pInterrupt + 1);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
{
|
|
MP_LOCAL_INTERRUPT *pInterrupt = (MP_LOCAL_INTERRUPT *)pbBegin;
|
|
|
|
printf("Loc Type=%02x Flags=%04x [Id=%02x Irq=%02x] -> [Id=%02x Irq=%02x]\n",
|
|
pInterrupt->Type,
|
|
pInterrupt->Flags,
|
|
pInterrupt->SrcBusId,
|
|
pInterrupt->SrcBusIrq,
|
|
pInterrupt->DstApicId,
|
|
pInterrupt->DstApicIrq);
|
|
|
|
pbBegin = (UINT8*)(pInterrupt + 1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown Configuration Type = %02x\n", pbBegin[0]);
|
|
pbBegin = pbLimit;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pbBegin = ((UINT8*)pFixed) + pFixed->BaseTableSize;
|
|
pbLimit = pbBegin + pFixed->ExtendedTableSize;
|
|
|
|
while (pbBegin < pbLimit) {
|
|
printf(" %4d: ", pbBegin - ((UINT8*)pFixed));
|
|
|
|
switch (pbBegin[0]) {
|
|
case 0x80:
|
|
{
|
|
MP_ADDRESS_SPACE_MAPPING *pMap = (MP_ADDRESS_SPACE_MAPPING *)pbBegin;
|
|
|
|
printf("Map Bus=%02x Type=%02x Base=%08lx Size=%08lx\n",
|
|
pMap->BusId,
|
|
pMap->AddressType,
|
|
pMap->AddressBase,
|
|
pMap->AddressSize);
|
|
}
|
|
break;
|
|
|
|
case 0x81:
|
|
{
|
|
MP_BUS_HIERARCHY *pHier = (MP_BUS_HIERARCHY *)pbBegin;
|
|
|
|
printf("Hier Bus=%02x Info=%02x ParentBusId=%02x\n",
|
|
pHier->BusId,
|
|
pHier->BusInfo,
|
|
pHier->ParentBusId);
|
|
}
|
|
break;
|
|
|
|
case 0x82:
|
|
{
|
|
MP_ADDRESS_SPACE_MODIFIER *pMap = (MP_ADDRESS_SPACE_MODIFIER *)pbBegin;
|
|
|
|
printf("Mod Bus=%02x Prefined=%02x RangeList=%08x\n",
|
|
pMap->BusId,
|
|
pMap->Predefined,
|
|
pMap->RangeList);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown Extended Type = %02x (len=%d bytes)\n", pbBegin[0], pbBegin[1]);
|
|
break;
|
|
}
|
|
|
|
pbBegin += pbBegin[1];
|
|
}
|
|
#endif
|
|
|
|
#if BOOT_START_MP
|
|
printf(" MP Init:\n");
|
|
volatile UINT32 * LocalApicIcrLo = (UINT32 *)(pFixed->LocalAPIC + 0x300);
|
|
volatile UINT32 * LocalApicIcrHi = (UINT32 *)(pFixed->LocalAPIC + 0x310);
|
|
volatile UINT32 * LocalApicEoi = (UINT32 *)(pFixed->LocalAPIC + 0x0b0);
|
|
volatile UINT32 * LocalApicEsr = (UINT32 *)(pFixed->LocalAPIC + 0x280);
|
|
|
|
const UINT32 AllExcludingSelf = 0xc0000;
|
|
const UINT32 LevelAssert = 0x04000;
|
|
const UINT32 SendPending = 0x01000;
|
|
const UINT32 DeliveryStartup = 0x00600;
|
|
const UINT32 DeliveryInit = 0x00500;
|
|
|
|
printf(" Sending IPI Init.\n");
|
|
*LocalApicEsr = 0;
|
|
*LocalApicEsr = 0;
|
|
*LocalApicIcrLo = (AllExcludingSelf |
|
|
LevelAssert |
|
|
SendPending |
|
|
DeliveryInit);
|
|
|
|
while (*LocalApicIcrLo & SendPending) {
|
|
__asm pause;
|
|
|
|
// Write tells APIC to update ESR.
|
|
*LocalApicEsr = 0;
|
|
if (*LocalApicEsr != 0) {
|
|
printf(" APIC Error: %08x\n", *LocalApicEsr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf(" Sent IPI Init.\n");
|
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
}
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
printf( "Sending IPI Startup %d.\n", i);
|
|
*LocalApicEsr = 0;
|
|
*LocalApicEsr = 0;
|
|
*LocalApicIcrLo = (AllExcludingSelf |
|
|
LevelAssert |
|
|
SendPending |
|
|
DeliveryStartup |
|
|
(bi->MpEnter32 >> 12));
|
|
|
|
while (*LocalApicIcrLo & SendPending) {
|
|
__asm pause;
|
|
|
|
// Write tells APIC to update ESR.
|
|
*LocalApicEsr = 0;
|
|
if (*LocalApicEsr != 0) {
|
|
printf(" APIC Error: %08x\n", *LocalApicEsr);
|
|
break;
|
|
}
|
|
}
|
|
printf(" Sent IPI Startup.\n");
|
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
}
|
|
}
|
|
#endif // BOOT_START_MP
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void CheckMinidump(Struct_Microsoft_Singularity_BootInfo *bi, uintptr *pEntry, uintptr *pStack)
|
|
{
|
|
//////////////////////////////////////////////////////////// Vet Minidump.
|
|
//
|
|
UINT8* pbImage = (UINT8*)bi->DumpAddr32;
|
|
UINT32 cbImage = bi->DumpSize32;
|
|
|
|
UINT32 *plHeader = (UINT32*)pbImage;
|
|
UINT32 *plTrailer = NULL;
|
|
|
|
#if DEBUG
|
|
printf("Minidump at %x\n", pbImage);
|
|
#endif
|
|
|
|
if (plHeader[0] != MINIDUMP_SIGNATURE ||
|
|
plHeader[1] != MINIDUMP_VERSION) {
|
|
|
|
printf("Image is corrupt!\n");
|
|
printf(" Addr: %8x, Size: %8x\n", bi->DumpAddr32, bi->DumpSize32);
|
|
printf(" %08x != %08x, %08x != %08x\n",
|
|
MINIDUMP_SIGNATURE, plHeader[0],
|
|
MINIDUMP_VERSION, plHeader[1]);
|
|
Halt();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////// Size the Minidump.
|
|
//
|
|
UINT32 Entry = 0;
|
|
UINT32 Stack = 0;
|
|
UINT32 Base = 0xffffffff;
|
|
UINT32 Limit = 0;
|
|
UINT32 cbSave = 0xfffffff;
|
|
|
|
PMINIDUMP_HEADER pHeader = (PMINIDUMP_HEADER)(pbImage + 0);
|
|
PMINIDUMP_DIRECTORY pDir
|
|
= (PMINIDUMP_DIRECTORY)(pbImage + pHeader->StreamDirectoryRva);
|
|
|
|
#if DEBUG
|
|
printf(" Streams: %d\n", pHeader->NumberOfStreams);
|
|
#endif
|
|
for (UINT i = 0; i < pHeader->NumberOfStreams; i++) {
|
|
switch (pDir[i].StreamType) {
|
|
case ThreadListStream:
|
|
{
|
|
PMINIDUMP_THREAD_LIST pl =
|
|
(PMINIDUMP_THREAD_LIST)(pbImage + pDir[i].Location.Rva);
|
|
#if DEBUG
|
|
printf(" Threads: %d\n", pl->NumberOfThreads);
|
|
#endif
|
|
for (UINT t = 0; t < pl->NumberOfThreads; t++) {
|
|
PCONTEXT pContext = (PCONTEXT)(pbImage + pl->Threads[t].ThreadContext.Rva);
|
|
Entry = pContext->Eip;
|
|
Stack = pContext->Esp;
|
|
#if DEBUG
|
|
printf(" entry: %x, stack %x \n", Entry, Stack);
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MemoryListStream:
|
|
{
|
|
PMINIDUMP_MEMORY_LIST pl =
|
|
(PMINIDUMP_MEMORY_LIST)(pbImage + pDir[i].Location.Rva);
|
|
#if DEBUG
|
|
printf(" Number of Memory Ranges: %d, pl =%lx \n", pl->NumberOfMemoryRanges);
|
|
for (UINT t = 0; t < pl->NumberOfMemoryRanges; t++) {
|
|
printf(" stream at %lx, size =%lx \n",
|
|
pl->MemoryRanges[t].StartOfMemoryRange,
|
|
pl->MemoryRanges[t].Memory.DataSize);
|
|
}
|
|
#endif
|
|
|
|
for (UINT t = 0; t < pl->NumberOfMemoryRanges; t++) {
|
|
if (cbSave > pl->MemoryRanges[t].Memory.Rva) {
|
|
cbSave = pl->MemoryRanges[t].Memory.Rva;
|
|
}
|
|
|
|
UINT32 pbDst = (UINT32)pl->MemoryRanges[t].StartOfMemoryRange;
|
|
UINT32 cbSrc = (UINT32)pl->MemoryRanges[t].Memory.DataSize;
|
|
|
|
if (!CheckSmapForRam(bi,
|
|
pl->MemoryRanges[t].StartOfMemoryRange,
|
|
pl->MemoryRanges[t].Memory.DataSize)) {
|
|
printf("No RAM available at %lx..%lx.\n",
|
|
pl->MemoryRanges[t].StartOfMemoryRange,
|
|
pl->MemoryRanges[t].StartOfMemoryRange +
|
|
pl->MemoryRanges[t].Memory.DataSize);
|
|
Halt();
|
|
}
|
|
|
|
if (pbDst > 0x100000) {
|
|
if (Base > pbDst) {
|
|
Base = pbDst;
|
|
}
|
|
if (Limit < pbDst + cbSrc) {
|
|
Limit = pbDst + cbSrc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0xcafeface:
|
|
plTrailer = (UINT32 *)(pbImage + pDir[i].Location.Rva);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////// Validate the minidump.
|
|
|
|
if (plTrailer == NULL || plTrailer[0] != 0xfeedbeef || plTrailer[1] != 0xcafeface) {
|
|
printf("Image is corrupt!\n");
|
|
printf(" Addr: %8x, Size: %8x\n", bi->DumpAddr32, bi->DumpSize32);
|
|
printf(" 0xfeedbeef != 0x%08x, 0xcafeface != 0x%08x\n",
|
|
plTrailer[0], plTrailer[1]);
|
|
Halt();
|
|
}
|
|
else {
|
|
UINT32 *plPos = (UINT32*)pbImage;
|
|
UINT32 *plEnd = (UINT32*)(plTrailer + 4);
|
|
UINT32 sum = 0;
|
|
for (; plPos < plEnd;) {
|
|
sum += *plPos++;
|
|
}
|
|
if (sum != 0) {
|
|
printf("Image is corrupt!\n");
|
|
printf(" Addr: %8x, Size: %8x\n", bi->DumpAddr32, bi->DumpSize32);
|
|
printf(" Checksum: %08x\n", sum);
|
|
Halt();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////// Expand the minidump.
|
|
//
|
|
for (UINT i = 0; i < pHeader->NumberOfStreams; i++) {
|
|
if (pDir[i].StreamType == MemoryListStream) {
|
|
PMINIDUMP_MEMORY_LIST pl =
|
|
(PMINIDUMP_MEMORY_LIST)(pbImage + pDir[i].Location.Rva);
|
|
|
|
for (UINT t = 0; t < pl->NumberOfMemoryRanges; t++) {
|
|
UINT8 *pbSrc = pbImage + pl->MemoryRanges[t].Memory.Rva;
|
|
UINT8 *pbDst = (UINT8*)pl->MemoryRanges[t].StartOfMemoryRange;
|
|
UINT32 cbSrc = pl->MemoryRanges[t].Memory.DataSize;
|
|
|
|
if (pbDst < (UINT8*)0x100000) {
|
|
// Don't write into memory below 1MB.
|
|
#if DEBUG
|
|
printf(" %p..%p -> %p..%p Ignored.\n",
|
|
pbSrc, pbSrc + cbSrc,
|
|
pbDst, pbDst + cbSrc);
|
|
#endif
|
|
}
|
|
else {
|
|
#if DEBUG
|
|
printf(" %p..%p -> %p..%p Copied\n",
|
|
pbSrc, pbSrc + cbSrc,
|
|
pbDst, pbDst + cbSrc);
|
|
#endif
|
|
CopyDown(pbDst, pbSrc, cbSrc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DEBUG
|
|
printf(" Minidump at %x..%x\n",
|
|
bi->DumpAddr32, bi->DumpAddr32 + bi->DumpSize32);
|
|
printf(" Kernel at %x..%x [Entry=%x, Stack=%x]\n", Base, Limit, Entry, Stack);
|
|
#endif
|
|
|
|
*pEntry = Entry;
|
|
*pStack = Stack;
|
|
|
|
bi->DumpBase = Base;
|
|
bi->DumpLimit = Limit;
|
|
bi->DumpRemainder = (UINT32)(plTrailer + 4);
|
|
}
|
|
|
|
static uintptr g_Entry = 0;
|
|
static uintptr g_Stack = 0;
|
|
static Struct_Microsoft_Singularity_BootInfo *g_bi = 0;
|
|
static Struct_Microsoft_Singularity_X86_IDTP g_idt;
|
|
static Struct_Microsoft_Singularity_X86_IDTE g_idtEntries[32];
|
|
|
|
extern "C" void __cdecl IdtHandler(UINT32 _cr2,
|
|
UINT32 _edi, UINT32 _esi, UINT32 _ebp, UINT32 _esp,
|
|
UINT32 _ebx, UINT32 _edx, UINT32 _ecx, UINT32 _eax,
|
|
UINT32 _num, UINT32 _err, UINT32 _eip, UINT32 _cs0,
|
|
UINT32 _efl)
|
|
{
|
|
printf("\n");
|
|
printf("=-=-=-= X86 Exception 0x%x [%x] =-=-=-=\n", _num, &_efl);
|
|
printf("err=%08x cr2=%08x eip=%08x efl=%08x\n",
|
|
_err, _cr2, _eip, _efl);
|
|
printf("eax=%08x ebx=%08x ecx=%08x edx=%08x\n",
|
|
_eax, _ebx, _ecx, _edx);
|
|
printf("esi=%08x edi=%08x ebp=%08x esp=%08x\n",
|
|
_esi, _edi, _ebp, _esp);
|
|
|
|
printf("Stack:\n");
|
|
UINT32 * stack = ((UINT32*)_esp);
|
|
for (int i = 0; i < 10; i++) {
|
|
printf(" %08x: %08x\n", &stack[i], stack[i]);
|
|
}
|
|
printf("Call Stack:\n");
|
|
for (int i = 0; i < 10 && _ebp >= Struct_Microsoft_Singularity_BootInfo_PHYSICAL_DISABLED; i++) {
|
|
ULONG_PTR next = ((ULONG_PTR *)_ebp)[0];
|
|
ULONG_PTR code = ((ULONG_PTR *)_ebp)[1];
|
|
|
|
printf(" %p: %p %p\n", _ebp, next, code);
|
|
_ebp = next;
|
|
}
|
|
|
|
Halt();
|
|
for (;;);
|
|
}
|
|
|
|
static void IdtInit()
|
|
{
|
|
Struct_Microsoft_Singularity_BootInfo *bi = g_bi;
|
|
|
|
UINT32 entry = (UINT32)bi->IdtEnter0;
|
|
UINT32 offset = ((UINT32)bi->IdtEnter1) - ((UINT32)bi->IdtEnter0);
|
|
|
|
for (int i = 0; i < arrayof(g_idtEntries); i++) {
|
|
g_idtEntries[i].offset_0_15 = (UINT16)entry;
|
|
g_idtEntries[i].selector =
|
|
(UINT16)(offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtPC) -
|
|
offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtNull));
|
|
g_idtEntries[i].access =
|
|
(Struct_Microsoft_Singularity_X86_IDTE_PRESENT |
|
|
Struct_Microsoft_Singularity_X86_IDTE_DPL_RING0 |
|
|
Struct_Microsoft_Singularity_X86_IDTE_INT_GATE);
|
|
g_idtEntries[i].offset_16_31 = (UINT16)(entry >> 16);
|
|
|
|
entry += offset;
|
|
}
|
|
|
|
*(void **)bi->IdtTarget = (void *)IdtHandler;
|
|
|
|
g_idt.limit = sizeof(g_idtEntries);
|
|
g_idt.addr = (UINT32)g_idtEntries;
|
|
|
|
__asm {
|
|
lidt g_idt.limit;
|
|
}
|
|
|
|
}
|
|
|
|
static void __declspec(naked) __fastcall SwitchStack
|
|
(
|
|
void (__fastcall *pfNext)(void) /* ECX */,
|
|
UINT32 _esp /* EDX */
|
|
)
|
|
{
|
|
__asm {
|
|
#if 0
|
|
push ebp;
|
|
mov ebp, esp;
|
|
|
|
mov ebx, 0xb8000;
|
|
mov eax, ecx;
|
|
call printdw;
|
|
|
|
mov eax, edx;
|
|
call printdw;
|
|
|
|
mov eax, ecx;
|
|
call printdw;
|
|
#endif
|
|
|
|
mov esp, edx;
|
|
jmp ecx;
|
|
|
|
#if 0
|
|
// Print a DWORD to the screen
|
|
// [in] ebx = address of screen
|
|
// [in] eax = dword to print
|
|
// [in] edi = trashed for temporary
|
|
//
|
|
printdw:
|
|
mov edi, eax;
|
|
shr edi, 28;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print28;
|
|
add edi, 7;
|
|
print28:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 24;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print24;
|
|
add edi, 7;
|
|
print24:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 20;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print20;
|
|
add edi, 7;
|
|
print20:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 16;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print16;
|
|
add edi, 7;
|
|
print16:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 12;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print12;
|
|
add edi, 7;
|
|
print12:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 8;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print08;
|
|
add edi, 7;
|
|
print08:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 4;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print04;
|
|
add edi, 7;
|
|
print04:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 0;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print00;
|
|
add edi, 7;
|
|
print00:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, 0x0f20;
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
ret;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void __fastcall undump1(void);
|
|
static void __fastcall undump2(void);
|
|
|
|
static void __fastcall undump_mp(int cpu);
|
|
|
|
extern "C" void undump(Struct_Microsoft_Singularity_BootInfo *bi, int cpu)
|
|
{
|
|
if (cpu == 0)
|
|
{
|
|
g_bi = bi;
|
|
g_bi->BootCount = 0;
|
|
undump1();
|
|
}
|
|
else
|
|
{
|
|
g_bi->MpStatus32 = Struct_Microsoft_Singularity_MpBootStatus_UndumpEntry;
|
|
undump_mp(cpu);
|
|
}
|
|
}
|
|
|
|
|
|
static void __fastcall undump1(void)
|
|
{
|
|
BdInitDebugger(g_bi->DebugBasePort);
|
|
Normal();
|
|
Cls();
|
|
|
|
Struct_Microsoft_Singularity_BootInfo *bi = (Struct_Microsoft_Singularity_BootInfo *)g_bi;
|
|
|
|
printf("32-bit Singularity Undump [" __DATE__ " " __TIME__ "]\n");
|
|
printf("BootInfo: %08lx (0x%x/%d bytes)\n", bi, sizeof(*bi), sizeof(*bi));
|
|
|
|
if (sizeof(Struct_Microsoft_Singularity_BootInfo) != bi->RecSize) {
|
|
printf("sizeof(BootInfo)=%d, bi->RecSize=%ld\n",
|
|
sizeof(Struct_Microsoft_Singularity_BootInfo), bi->RecSize);
|
|
for(;;);
|
|
}
|
|
|
|
IdtInit();
|
|
|
|
|
|
CheckMinidump(bi, &g_Entry, &g_Stack);
|
|
|
|
#if 0
|
|
UINT32 _esp;
|
|
__asm mov _esp, esp;
|
|
printf(" SwitchStack(bi=%x, next=%x, esp=%x) was esp=%x\n",
|
|
bi, undump2, g_Stack, _esp);
|
|
|
|
Dump(((UINT8*)undump2) - 8, 16);
|
|
Probe(((UINT8*)undump2) - 8, 16);
|
|
Dump(((UINT8*)g_Stack) - 8, 16);
|
|
Probe(((UINT8*)g_Stack) - 8, 16);
|
|
#endif
|
|
printf("Switching stack to %x and calling %x\n", g_Stack, undump2);
|
|
SwitchStack(undump2, g_Stack); // Transfers execution to undump2();
|
|
}
|
|
|
|
static void __fastcall undump2(void)
|
|
{
|
|
#if 0
|
|
__asm {
|
|
mov eax, esp;
|
|
call printdw;
|
|
|
|
int 3;
|
|
|
|
again: jmp again;
|
|
jmp ecx;
|
|
|
|
// Print a DWORD to the screen
|
|
// [in] ebx = address of screen
|
|
// [in] eax = dword to print
|
|
// [in] edi = trashed for temporary
|
|
//
|
|
printdw:
|
|
mov edi, eax;
|
|
shr edi, 28;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print28;
|
|
add edi, 7;
|
|
print28:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 24;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print24;
|
|
add edi, 7;
|
|
print24:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 20;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print20;
|
|
add edi, 7;
|
|
print20:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 16;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print16;
|
|
add edi, 7;
|
|
print16:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 12;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print12;
|
|
add edi, 7;
|
|
print12:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 8;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print08;
|
|
add edi, 7;
|
|
print08:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 4;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print04;
|
|
add edi, 7;
|
|
print04:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, eax;
|
|
shr edi, 0;
|
|
and edi, 0xf;
|
|
add edi, 0x0f30;
|
|
cmp edi, 0x0f3a;
|
|
jl print00;
|
|
add edi, 7;
|
|
print00:
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
|
|
mov edi, 0x0f20;
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
mov [ebx+0], edi;
|
|
add ebx, 2;
|
|
ret;
|
|
}
|
|
#endif
|
|
|
|
Struct_Microsoft_Singularity_BootInfo *bi = g_bi;
|
|
void (__cdecl * pfHal)(const Struct_Microsoft_Singularity_BootInfo *, int)
|
|
= (void (__cdecl *)(const Struct_Microsoft_Singularity_BootInfo *, int))g_Entry;
|
|
|
|
#if DEBUG
|
|
printf("Probing basic hardware.\n");
|
|
#endif
|
|
|
|
CheckPci(bi);
|
|
CheckCpuid(bi);
|
|
CheckApic(bi);
|
|
CheckAcpi(bi);
|
|
CheckMp(bi);
|
|
FpuInit();
|
|
printf("Starting Singularity Kernel (at 0x%x)\n", pfHal);
|
|
|
|
pfHal(bi, 0);
|
|
|
|
bi->BootCount++;
|
|
|
|
SwitchStack(undump1, Struct_Microsoft_Singularity_BootInfo_REAL_STACK);
|
|
// Transfers execution to undump1();
|
|
}
|
|
|
|
static void __fastcall undump_mp(int cpu)
|
|
{
|
|
IdtInit();
|
|
FpuInit();
|
|
|
|
g_bi->MpStatus32 = Struct_Microsoft_Singularity_MpBootStatus_HalEntry;
|
|
|
|
void (__cdecl * pfHal)(const Struct_Microsoft_Singularity_BootInfo *, int)
|
|
= (void (__cdecl *)(const Struct_Microsoft_Singularity_BootInfo *, int))g_Entry;
|
|
|
|
pfHal(g_bi, cpu);
|
|
}
|