////////////////////////////////////////////////////////////////////////////// // // 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 struct STATIC_ASSERT_FAILURE; template <> struct STATIC_ASSERT_FAILURE { }; template 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); }