2020-09-30 17:17:25 +02:00

408 lines
8.8 KiB
C

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
bldr32.c
Abstract:
This module implements the initialization sequence required to jump to
XBOXKRNL.EXE.
--*/
#include "bldr32.h"
#include "bldr.h"
#include "xpcicfg.h"
#include "enckey.h"
#ifdef BLDRMEMTEST
#include <ldi.h>
#include <sha.h>
#include <rc4.h>
#endif
VOID
DbgInitialize(
VOID
);
VOID
DbgPrintCharacter(
IN UCHAR Character
);
//
// Prototype for the entry point of XBOXKRNL.EXE.
//
typedef
int
(__cdecl *NTOS_ENTRY_POINT)(
IN PUCHAR LoadOptions,
IN const UCHAR* CryptKeys
);
VOID
BldrDisableInteralROM(
VOID
);
VOID
BldrEncoderFixup(
VOID
);
VOID
BldrSetupUSB(
VOID
);
#ifdef BLDRMEMTEST
VOID
BldrTestMemory(
ULONG StartAddress,
ULONG EndAddress,
BOOLEAN CompareDigests
);
ULONG MemTestErrorCount = 0;
#endif
VOID
BldrStartup2(
VOID
)
{
PIMAGE_NT_HEADERS NtHeader;
NTOS_ENTRY_POINT NtosEntryPoint;
PBOOTLDRPARAM BootLdrParam;
const UCHAR* KeyToDecryptKernel;
BOOLEAN FirstTime;
#ifdef RETAILXM3
BldrDisableInteralROM();
BldrEncoderFixup();
#endif
BldrPrint(("Bldr: Entered BldrStartup2"));
#ifdef BLDRMEMTEST
//
// Memory test before calibration
//
//BldrTestMemory(0, BLDR_RELOCATED_ORIGIN - 1, TRUE);
BldrTestMemory(BLDR_RELOCATED_ORIGIN + BLDR_BLOCK_SIZE, 0x3FFFFFF, TRUE);
#endif
//
// The boot loader was relocated from BLDR_BOOT_ORIGIN to
// BLDR_RELOCATED_ORIGIN. Code should no longer attempt to access any
// memory at the boot origin because it will be overwritten when we
// decompress the kernel into low memory. Fill the old memory with a
// garbage value to ensure that we don't accidently use that memory.
//
RtlFillMemory((PVOID)(0x80000000 + BLDR_BOOT_ORIGIN), BLDR_BLOCK_SIZE, 0xCC);
//
// Calculate a pointer to the boot parameters stored at the begining of
// of the boot loader image eg command line. In case of ROM, entire image
// including the parameter structure is decrypted so its safe to use
// the command line which will normally be empty.
//
BootLdrParam = (PBOOTLDRPARAM)(0x80000000 + BLDR_RELOCATED_ORIGIN);
FirstTime = TRUE;
#ifndef RETAILXM3
if (strstr(BootLdrParam->CommandLine, "SHADOW") != NULL) {
FirstTime = FALSE;
}
#endif
if (FirstTime) {
//
// Set drive/slew from ROM.
//
BldrSetDrvSlwFromROMData((PVOID)XPCICFG_GPU_MEMORY_REGISTER_BASE_0);
//
// Setup LDT bus including DWORD flow control
//
BldrSetupLDTBus();
//
// Configure the USB ASRC
//
BldrSetupUSB();
}
#ifdef BLDRMEMTEST
//
// Memory test after calibration
//
//BldrTestMemory(0, BLDR_RELOCATED_ORIGIN - 1, FALSE);
BldrTestMemory(BLDR_RELOCATED_ORIGIN + BLDR_BLOCK_SIZE, 0x3FFFFFF, FALSE);
#endif
//
// Decrypt and decompress the kernel image from ROM to its base address
// in RAM. Kernel encryption key is the 3rd key in the XboxCryptKeys
//
KeyToDecryptKernel = XboxCryptKeys + (2 * XBOX_KEY_LENGTH);
BldrCopyROMToRAM(KeyToDecryptKernel);
//
// Go find the entry point.
//
NtHeader = RtlImageNtHeader(PsNtosImageBase);
if (NtHeader == NULL) {
//
// Image is invalid
//
BldrPrint(("Bldr: Entry point not found--invalid image"));
BldrShutdownSystem();
}
NtosEntryPoint = (NTOS_ENTRY_POINT)((ULONG_PTR)PsNtosImageBase +
NtHeader->OptionalHeader.AddressOfEntryPoint);
//
// Pass control to XBOXKRNL.EXE.
//
BldrPrint(("Bldr: Calling into the kernel"));
#ifdef BLDRMEMTEST
//
// While testing memory, if there are no errors, tell the SMC to reboot
//
if (MemTestErrorCount == 0) {
DbgPrint("Memory test finished with no errors, rebooting\r\n...");
BldrWriteSMBusByte(SMC_SLAVE_ADDRESS, 0x2, 0x40);
} else {
DbgPrint("Memory test FAILED with %d errors", MemTestErrorCount);
}
#endif
NtosEntryPoint(BootLdrParam->CommandLine, XboxCryptKeys);
}
VOID
BldrReencryptROM(
VOID
)
{
BldrEncDec((PUCHAR)0 - ROM_DEC_SIZE - BLDR_BLOCK_SIZE,
BLDR_BLOCK_SIZE, KeyToDecryptBldr, 16);
}
#ifdef RETAILXM3
VOID
BldrDisableInteralROM(
VOID
)
{
_outpd(PCI_TYPE1_ADDR_PORT, 0x80000880);
_outp(PCI_TYPE1_DATA_PORT, 2);
}
#include <bldrtran.h>
VOID
BldrEncoderFixup(
VOID
)
{
UCHAR i0;
UCHAR i1;
UCHAR i2;
UCHAR i3;
UCHAR o0;
UCHAR o1;
ULONG Val;
//
// Read the inputs
//
Val = 0;
BldrReadSMBusByte(SMC_SLAVE_ADDRESS, 0x1c, &Val);
i0 = (UCHAR)Val;
BldrReadSMBusByte(SMC_SLAVE_ADDRESS, 0x1d, &Val);
i1 = (UCHAR)Val;
BldrReadSMBusByte(SMC_SLAVE_ADDRESS, 0x1e, &Val);
i2 = (UCHAR)Val;
BldrReadSMBusByte(SMC_SLAVE_ADDRESS, 0x1f, &Val);
i3 = (UCHAR)Val;
if (i0 == 0 && i1 == 0 && i2 == 0 && i3 == 0) {
BldrShutdownSystem();
}
BldrEncoderTranslate(i0, i1, i2, i3, &o0, &o1);
//
// Write the outputs
//
BldrWriteSMBusByte(SMC_SLAVE_ADDRESS, 0x20, o0);
BldrWriteSMBusByte(SMC_SLAVE_ADDRESS, 0x21, o1);
BldrPrint(("\n%d %d %d %d => %d %d", i0, i1, i2, i3, o0, o1));
//
// Reset the SMC revision pointer
//
BldrWriteSMBusByte(SMC_SLAVE_ADDRESS, 0x1, 0);
//
// Reenable all MCP devices. Specifically NIC and IDE which
// were disabled in the init table strap value
//
_outpd(PCI_TYPE1_ADDR_PORT, 0x8000088C);
_outpd(PCI_TYPE1_DATA_PORT, 0x40000000);
}
#endif
VOID
BldrSetupUSB(
VOID
)
{
UCHAR MCPRevisionID;
//
// Setup the USB ASRC (Automatic Slew Rate Compensation) which affects how the
// USB signal is driven. This change is required only for MCP revision D01 and later.
// Read the MCP revision to see if the change needs to be applied.
//
_outpd(PCI_TYPE1_ADDR_PORT, 0x80000808);
MCPRevisionID = (UCHAR)_inp(PCI_TYPE1_DATA_PORT);
if (MCPRevisionID >= 0xD1) {
_outpd(PCI_TYPE1_ADDR_PORT, 0x800008C8);
_outpd(PCI_TYPE1_DATA_PORT, 0x00008F00);
}
}
#ifdef BLDRMEMTEST
VOID
BldrTestMemory(
ULONG StartAddress,
ULONG EndAddress,
BOOLEAN CompareDigests
)
{
UCHAR Key[16];
ULONG Index;
UCHAR SHADigest[A_SHA_DIGEST_LEN];
A_SHA_CTX SHAHash;
if (CompareDigests) {
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, (PVOID)BLDR_RELOCATED_ORIGIN, BLDR_BLOCK_SIZE);
A_SHAFinal(&SHAHash, SHADigest);
DbgPrintHex(SHADigest, 20);
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, (PVOID)0xFFFF9E00, BLDR_BLOCK_SIZE);
A_SHAFinal(&SHAHash, SHADigest);
DbgPrintHex(SHADigest, 20);
}
DbgPrint("Testing memory from %x to %x with 00s", StartAddress, EndAddress);
RtlFillMemory((PVOID)StartAddress, EndAddress - StartAddress + 1, 0);
for (Index = 0; Index < 16; Index++) {
Key[Index] = (UCHAR)Index;
}
BldrEncDec((PUCHAR)StartAddress, EndAddress - StartAddress + 1, Key, sizeof(Key));
__asm wbinvd
for (Index = 0; Index < 16; Index++) {
Key[Index] = (UCHAR)Index;
}
BldrEncDec((PUCHAR)StartAddress, EndAddress - StartAddress + 1, Key, sizeof(Key));
__asm wbinvd
for (Index = StartAddress; Index <= EndAddress; Index++) {
if ((*(UCHAR*)Index) != 0) {
MemTestErrorCount++;
DbgPrint("***Mem test failed at %x (%d)", Index, (*(UCHAR*)Index));
}
}
DbgPrint("Testing memory from %x to %x with FFs", StartAddress, EndAddress);
RtlFillMemory((PVOID)StartAddress, EndAddress - StartAddress + 1, 0xFF);
for (Index = 0; Index < 16; Index++) {
Key[Index] = (UCHAR)Index;
}
BldrEncDec((PUCHAR)StartAddress, EndAddress - StartAddress + 1, Key, sizeof(Key));
__asm wbinvd
for (Index = 0; Index < 16; Index++) {
Key[Index] = (UCHAR)Index;
}
BldrEncDec((PUCHAR)StartAddress, EndAddress - StartAddress + 1, Key, sizeof(Key));
__asm wbinvd
for (Index = StartAddress; Index <= EndAddress; Index++) {
if ((*(UCHAR*)Index) != 0xFF) {
MemTestErrorCount++;
DbgPrint("***Mem test failed at %x (%d)", Index, (*(UCHAR*)Index));
}
}
}
#endif