singrdk/base/boot/SingLdrPc/blsingularity.cpp

1160 lines
30 KiB
C++

//++
//
// Copyright (c) Microsoft Corporation
//
// Module Name:
//
// blsingularity.cpp
//
// Abstract:
//
// This module initializes and boots Singularity.
//
//--
#include "bl.h"
#define SINGULARITY_DISTRO_INI_PATH "singularity/singboot.ini"
#define SINGULARITY_LOG_RECORD_SIZE 0x20000
#define SINGULARITY_LOG_TEXT_SIZE 0x20000
#define SINGULARITY_KERNEL_STACK_SIZE 0xC0000
//
// Define halclass style basic definitions and macros.
//
typedef ULONG_PTR PTR_TYPE;
typedef LONG_PTR SPTR_TYPE;
typedef ULONG_PTR UPTR_TYPE;
#define OFFSETOF FIELD_OFFSET
#define STATIC_ASSERT C_ASSERT
//
// Include halclasswin.h for Singularity definitions.
//
#define SINGULARITY_LOADER 1
#pragma pack(1)
#include <halclasswin.h>
#pragma pack()
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, rc) == RM_CODE_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, rd) == RM_DATA_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, pc) == PM_CODE_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, pd) == PM_DATA_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, lc) == LM_CODE_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, ld) == LM_DATA_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, pp) == PROCESSOR_SELECTOR);
C_ASSERT(FIELD_OFFSET(Struct_Microsoft_Singularity_Isal_IX_DescriptorTable_Gdt, tss) == TSS_SELECTOR);
Class_Microsoft_Singularity_Hal_Platform *BlPlatform;
Class_Microsoft_Singularity_Hal_Cpu *BlCpuArray;
typedef struct _BL_DISTRO_FILE {
LIST_ENTRY Entry;
UINT32 Size;
CHAR Path[1024];
PVOID Data;
} BL_DISTRO_FILE, *PBL_DISTRO_FILE;
typedef struct _BL_DISTRO {
UINT32 NumberOfFiles;
UINT32 TotalSize;
LIST_ENTRY FileList;
PVOID Data;
} BL_DISTRO, PBL_DISTRO;
BL_DISTRO BlDistro;
PBL_DISTRO_FILE BlKernelFile;
PVOID BlKernelBase;
ULONG_PTR BlKernelSize;
UINT32
(*BlKernelEntryPoint)(
Class_Microsoft_Singularity_Hal_Platform *Platform,
Class_Microsoft_Singularity_Hal_Cpu *Cpu
);
PBL_SMAP BlSingularitySmap;
PWCHAR BlCommandLine;
Struct_Microsoft_Singularity_Io_FileImage *BlSingularityFileImageTable;
UINT32 BlSingularityFileImageTableSize;
//
// OHCI 1394 buffer for Singularity KD.
//
// AIFIX: Currently, this buffer needs to be allocated in low memory, because
// Singularity KD does not connect if it is allocated in high memory.
//
__declspec(align(PAGE_SIZE)) UINT8 BlSingularityOhci1394Buffer[3 * PAGE_SIZE];
VOID
BlSingularityLoadDistro(
VOID
)
//++
//
// Routine Description:
//
// This function loads the distro.
//
//--
{
UINT32 BytesRead;
UINT32 CharactersConsumed;
PBL_DISTRO_FILE DistroFile;
UINT32 DummySize;
PLIST_ENTRY Entry;
UINT32 FilesRead;
PLIST_ENTRY Head;
PCHAR NewLine;
PCHAR Next;
UINT32 Size;
PCHAR Temp;
PVOID BlIniFileData;
UINT32 BlIniFileSize;
BlDistro.NumberOfFiles = 0;
BlRtlInitializeListHead(&BlDistro.FileList);
//
// Read the distro INI file.
//
if (BlFsGetFileSize(SINGULARITY_DISTRO_INI_PATH, &BlIniFileSize) == FALSE) {
BlRtlPrintf("BL: Unable to get INI file!\n");
BlRtlHalt();
}
BlIniFileData = BlPoolAllocateBlock(BlIniFileSize + 1);
if (BlFsReadFile(SINGULARITY_DISTRO_INI_PATH, BlIniFileData, BlIniFileSize) == FALSE) {
BlRtlPrintf("BL: Unable to read INI file!\n");
BlRtlHalt();
}
//
// Parse INI file and build distro file list.
//
NewLine = (PCHAR) BlIniFileData;
for (;;) {
Next = NewLine;
NewLine = Next + 1;
while ((*NewLine != 0) && (*NewLine != '\r') && (*NewLine != '\n')) {
NewLine += 1;
}
if (*NewLine == 0) {
break;
}
while ((*NewLine == '\r') || (*NewLine == '\n')) {
*NewLine = 0;
NewLine += 1;
}
Next = (PCHAR)BlRtlFindSubstring(Next, "Size=");
if (Next == NULL) {
continue;
}
Next += 5;
if (BlRtlParsePositiveDecimal(Next,
&Size,
&CharactersConsumed) == FALSE) {
ParseFailure:
BlRtlPrintf("BL: Error parsing distro INI file!\n");
BlRtlHalt();
}
Next = (PCHAR)BlRtlFindSubstring(Next, "Path=");
if (Next == NULL) {
goto ParseFailure;
}
Next += 5;
if (*Next == 0) {
goto ParseFailure;
}
DistroFile = (PBL_DISTRO_FILE) BlPoolAllocateBlock(sizeof(BL_DISTRO_FILE));
BLASSERT((NewLine - Next) < sizeof(DistroFile->Path));
Temp = (PCHAR)Next;
while (Temp != NewLine) {
if (*Temp == '\\') {
*Temp = '/';
}
Temp += 1;
}
BlRtlCopyMemory(DistroFile->Path, Next, NewLine - Next);
//
// By convention with DistroBuiderl, the first file with a size of zero is
// really the INI file, so we need to set its size.
//
if (Size == 0) {
Size = BlIniFileSize;
}
DistroFile->Size = Size;
BlDistro.NumberOfFiles += 1;
BlDistro.TotalSize += Size;
BlRtlInsertTailList(&BlDistro.FileList, &DistroFile->Entry);
}
//
// Read distro files.
//
BlDistro.Data = (PVOID) BlMmAllocatePhysicalRegion(ROUND_UP_TO_PAGES(BlDistro.TotalSize), BL_MM_PHYSICAL_REGION_DISTRO);
#if DISTRO_VERBOSE
BlKdPrintf("DISTRO: Reading distro (%u files , %u bytes).\n",
BlDistro.NumberOfFiles,
BlDistro.TotalSize);
#endif
FilesRead = 0;
BytesRead = 0;
Next = (PCHAR) BlDistro.Data;
Head = &BlDistro.FileList;
for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink) {
DistroFile = CONTAINING_RECORD(Entry, BL_DISTRO_FILE, Entry);
DistroFile->Data = Next;
BLASSERT(DistroFile->Path[0] == '/');
#if DISTRO_VERBOSE
BlKdPrintf("DISTRO: %s [%u bytes]\n",
DistroFile->Path,
DistroFile->Size);
#endif
if (BlFsReadFile(&DistroFile->Path[1], DistroFile->Data, DistroFile->Size) == FALSE) {
BlRtlPrintf("\n"
"BL: Error reading %s!\n",
DistroFile->Path);
BlRtlHalt();
}
Next += DistroFile->Size;
FilesRead += 1;
BytesRead += DistroFile->Size;
BlVideoPrintf("\rReading distro files ... %u / %u [%u / %u]",
FilesRead,
BlDistro.NumberOfFiles,
BytesRead,
BlDistro.TotalSize);
}
BlVideoPrintf("\n");
//
// If this is a network boot, then signal the PXE server to exit.
// This is the only mechanism to notify the server that the boot succeeded.
//
if (BlGetBeb()->BootType == BL_PXE_BOOT) {
BlFsGetFileSize("end.:", &DummySize);
}
//
// Switch distro range to read-only.
//
BlMmMapVirtualRange(BlDistro.Data,
BlDistro.Data,
BlDistro.TotalSize,
FALSE,
TRUE,
FALSE);
//
// Build file image table.
//
BlSingularityFileImageTable = (Struct_Microsoft_Singularity_Io_FileImage *) BlPoolAllocateBlock(BlDistro.NumberOfFiles * sizeof(Struct_Microsoft_Singularity_Io_FileImage));
for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink) {
DistroFile = CONTAINING_RECORD(Entry, BL_DISTRO_FILE, Entry);
BlSingularityFileImageTable[BlSingularityFileImageTableSize].Address = (ULONG_PTR) DistroFile->Data;
BlSingularityFileImageTable[BlSingularityFileImageTableSize].Size = DistroFile->Size;
BlSingularityFileImageTableSize += 1;
}
return;
}
VOID
BlSingularityLoadKernelImage(
VOID
)
//++
//
// Routine Description:
//
// This function loads the kernel image.
//
//--
{
BLASSERT(BlRtlIsListEmpty(&BlDistro.FileList) == FALSE);
//
// Kernel is the first entry in the distro file list.
//
BlKernelFile = CONTAINING_RECORD(BlDistro.FileList.Flink,
BL_DISTRO_FILE,
Entry);
//
// Get the virtual range for the kernel image.
//
BlPeGetVirtualRange(BlKernelFile->Data, &BlKernelBase, &BlKernelSize);
BLASSERT(((UINT64) BlKernelBase % PAGE_SIZE) == 0);
BLASSERT((BlKernelSize % PAGE_SIZE) == 0);
//
// Allocate a physical region for the kernel image, since pages are identity mapped at boot.
//
// AIFIX: This needs to be be made dynamic!
//
if (BlMmAllocateSpecificPhysicalRegion((UINT64) BlKernelBase,
BlKernelSize,
BL_MM_PHYSICAL_REGION_KERNEL_IMAGE) == FALSE) {
BlMmDumpPhysicalRegionList();
BlRtlHalt();
}
#if SINGULARITY_VERBOSE
BlRtlPrintf("BL: Loading kernel ... [%p ... %p]\n",
BlKernelBase,
(ULONG_PTR) BlKernelBase + BlKernelSize - 1);
#endif
BlPeLoadImage(BlKernelBase, BlKernelFile->Data, (PVOID *) &BlKernelEntryPoint);
}
//
// AIFIX: Fix task page definition.
//
#if defined(BOOT_X86)
typedef Struct_Microsoft_Singularity_Isal_IX_TSS BL_TASK_SEGMENT;
#elif defined(BOOT_X64)
typedef Struct_Microsoft_Singularity_Isal_IX_TSS64 BL_TASK_SEGMENT;
#endif
typedef struct _BL_PROCESSOR {
UINT32 Index;
Class_Microsoft_Singularity_Hal_Cpu *Cpu;
PVOID KernelStack;
ULONG_PTR KernelStackSize;
PVOID ContextPage;
PVOID BasePage;
BL_TASK_SEGMENT *TaskPage;
} BL_PROCESSOR, *PBL_PROCESSOR;
PBL_PROCESSOR BlProcessor;
UINT32 BlProcessorCount;
VOID
BlSingularityInitializeProcessor(
UINT32 Index
)
//++
//
// Routine Description:
//
// This function initializes the specified processor.
//
// Arguments:
//
// Index - Supplies the index of the processor to initialize.
//
//--
{
Class_Microsoft_Singularity_Hal_Cpu *Processor;
//
// Initialize native processor structure.
//
Processor = BlProcessor[Index].Cpu;
Processor->Size = sizeof(Class_Microsoft_Singularity_Hal_Cpu);
Processor->Id = Index;
#if 0
Processor->ApicId = Index;
#endif
Processor->KernelStackLimit = (ULONG_PTR) BlProcessor[Index].KernelStack;
// Processor->KernelStackBegin = Processor->KernelStackLimit + SINGULARITY_KERNEL_STACK_SIZE;
Processor->KernelStackBegin = Processor->KernelStackLimit + BlProcessor[Index].KernelStackSize;
Processor->CpuRecordPage = (ULONG_PTR) BlProcessor[Index].BasePage;
//
// Initialize task structure.
//
BlProcessor[Index].TaskPage->io_bitmap_offset = sizeof(BL_TASK_SEGMENT);
//
// Initialize segments.
//
BlRtlZeroMemory(&Processor->segments, sizeof(Processor->segments));
Processor->segments.gdtPtr.addr = (ULONG_PTR) &Processor->segments.gdt;
Processor->segments.gdtPtr.limit = sizeof(Processor->segments.gdt) - 1;
BlRtlCopyMemory(&Processor->segments.gdt.pc,
(PVOID) (BlMmInitialGdtr.Base + PM_CODE_SELECTOR),
sizeof(CODE_SEGMENT));
BlRtlCopyMemory(&Processor->segments.gdt.pd,
(PVOID) (BlMmInitialGdtr.Base + PM_DATA_SELECTOR),
sizeof(CODE_SEGMENT));
#if defined(BOOT_X64)
BlRtlCopyMemory(&Processor->segments.gdt.lc,
(PVOID) (BlMmInitialGdtr.Base + LM_CODE_SELECTOR),
sizeof(CODE_SEGMENT));
BlRtlCopyMemory(&Processor->segments.gdt.ld,
(PVOID) (BlMmInitialGdtr.Base + LM_DATA_SELECTOR),
sizeof(CODE_SEGMENT));
#endif
BlMmInitializeDataSegment((PDATA_SEGMENT) &Processor->segments.gdt.pp,
(UINT32) (ULONG_PTR) BlProcessor[Index].ContextPage,
PAGE_SIZE - 1);
BlMmInitializeSystemSegment((PSYSTEM_SEGMENT) &Processor->segments.gdt.tss,
SSDT_AVAILABLE_TSS,
(ULONG_PTR) BlProcessor[Index].TaskPage,
sizeof(BL_TASK_SEGMENT) - 1);
return;
}
UINT32 BlSingularityProcessorToStart;
UINT32
BlSingularityCallKernel(
UINT32 Index
)
//++
//
// Routine Description:
//
// This function calls the kernel.
//
// Arguments:
//
// Index - Supplies the index of the current processor.
//
// Return Value:
//
// Kernel exit code.
//
//--
{
UINT32 ExitCode;
#if SINGULARITY_VERBOSE
BlRtlPrintf("\fBL: Processor[%d]: Starting Singularity ...\n",
Index
);
BlRtlPrintf("BL: Cpu = %p\n",
BlProcessor[Index].Cpu
);
BlRtlPrintf("BL: GDT =[%p...%p]\n",
BlProcessor[Index].Cpu->segments.gdtPtr.addr,
BlProcessor[Index].Cpu->segments.gdtPtr.addr + BlProcessor[Index].Cpu->segments.gdtPtr.limit
);
BlRtlPrintf("BL: stack=[%p...%p]\n",
BlProcessor[Index].Cpu->KernelStackLimit,
BlProcessor[Index].Cpu->KernelStackBegin
);
#endif
BlMmSetGdtr((PGDTR) &BlProcessor[Index].Cpu->segments.gdtPtr.limit);
#if defined(BOOT_X86)
BlMmSetFs(PROCESSOR_SELECTOR);
#elif defined(BOOT_X64)
BlMmSetGs(PROCESSOR_SELECTOR);
#endif
BlMmSetCr3(BlMmBootCr3);
BlRtlPrintf("BL: kernel=[%p ... %p]\n",
BlKernelBase, (ULONG_PTR) BlKernelBase + BlKernelSize - 1);
BlRtlPrintf("BL: entry= %p\n", BlKernelEntryPoint);
ExitCode = BlKernelEntryPoint(BlPlatform, BlProcessor[Index].Cpu);
BlMmSetGdtr(&BlMmInitialGdtr);
BlVideoInitialize();
return ExitCode;
}
VOID
BlSingularityEnterKernel(
VOID
)
//++
//
// Routine Description:
//
// This function enters Singularity.
//
//--
{
UINT32 ExitCode;
PVOID LocalVariable;
UINT32 Index;
Index = BlSingularityProcessorToStart;
BLASSERT(((ULONG_PTR) &LocalVariable) >= BlProcessor[Index].Cpu->KernelStackLimit);
BLASSERT(((ULONG_PTR) &LocalVariable) < BlProcessor[Index].Cpu->KernelStackBegin);
//
// The bootstrap processor runs in a loop calling kernel entry point and performing warm boot
// when the kernel returns. The application processors do not return from the kernel call and are
// reinitialized with SIPIs by the kernel after a warm boot.
//
if (Index == 0) {
for (;;) {
BlMmDumpPhysicalRegionList();
ExitCode = BlSingularityCallKernel(Index);
#if SINGULARITY_VERBOSE
BlRtlPrintf("BL: Processor[%02x]: Kernel exited with 0x%08x.\n",
Index,
ExitCode);
#endif
BlPlatform->BootCount += 1;
BlRtlZeroMemory(BlKernelBase, BlKernelSize);
BlPeLoadImage(BlKernelBase, BlKernelFile->Data, (PVOID *) &BlKernelEntryPoint);
}
}
else {
ExitCode = BlSingularityCallKernel(Index);
BlRtlPrintf("BL: AP returned from kernel call!\n");
BlRtlHalt();
}
return;
}
VOID
BlSingularityExit(
VOID
)
//++
//
// Routine Description:
//
// This function exits Singularity and performs the "kill action" requested by the kernel.
//
//--
{
BlMmSetGdtr(&BlMmInitialGdtr);
BlVideoInitialize();
switch (BlPlatform->KillAction) {
case Class_Microsoft_Singularity_Hal_Platform_EXIT_AND_SHUTDOWN: {
BlRtlPrintf("BL: Kernel requested shutdown.\n");
BlRtlShutdownSystem();
break;
}
case Class_Microsoft_Singularity_Hal_Platform_EXIT_AND_RESTART: {
BlRtlPrintf("BL: Kernel requested restart.\n");
BlRtlResetSystem();
break;
}
case Class_Microsoft_Singularity_Hal_Platform_EXIT_AND_HALT: {
BlRtlPrintf("BL: Kernel requested halt.\n");
BlRtlHalt();
break;
}
case Class_Microsoft_Singularity_Hal_Platform_EXIT_AND_WARMBOOT: {
BlRtlPrintf("BL: Kernel requested warmboot.\n");
BlPlatform->BootCount += 1;
BlRtlZeroMemory(BlKernelBase, BlKernelSize);
BlPeLoadImage(BlKernelBase, BlKernelFile->Data, (PVOID *) &BlKernelEntryPoint);
BlSingularityProcessorToStart = 0;
BlMmSwitchStack((PVOID) BlProcessor[0].Cpu->KernelStackBegin, BlSingularityEnterKernel);
break;
}
default: {
BlRtlPrintf("BL: Unrecognized kill action 0x%08x!\n", BlPlatform->KillAction);
BlRtlHalt();
}
}
}
unsigned int IsApicPresent (void)
{
unsigned int reg_edx = BlGetCpuidEdx(1);
return ((reg_edx >> 9) & 0x1);
}
#define INITIAL_APIC_ID_BITS 0xFF000000 // EBX[31:24] unique APIC ID
// Returns the 8-bit unique Initial APIC ID for the processor this
// code is actually running on. The default value returned is 0xFF if
// Hyper-Threading Technology is not supported.
// Taken from intel application note Ap-485 "Intel Processor Identification and the CPUID instruction"
unsigned char GetAPIC_ID (void)
{
unsigned int reg_ebx = BlGetCpuidEbx(1);
return (unsigned char) ((reg_ebx & INITIAL_APIC_ID_BITS) >> 24);
}
VOID
BlSingularityInitialize(
UINT32 NumberOfProcessors,
PFAR_POINTER ApEntry16,
PFAR_POINTER ApStartupLock
)
//++
//
// Routine Description:
//
// This function initializes Singularity.
//
// Arguments:
//
// NumberOfProcessors - Supplies the number of processors on the system.
//
// ApEntry6 - Supplies a pointer to the 16-bit entry point for
// application processors on a multi-processor system.
//
// ApStartupLock - Supplies a pointer to the lock used for AP startup
// synchronization.
//
//--
{
UINT64 Base;
UINT32 Index;
PVOID PhysicalRegionHandle;
UINT64 Size;
UINT32 Type;
UINT8 id;
UINT64 HighAddress;
UINT64 TempAddress;
UINT64 StackStart;
UINT64 PlayStart;
int i;
char* p;
//
// Allocate processor array and set processor count.
//
BlProcessor = (PBL_PROCESSOR) BlPoolAllocateBlock(sizeof(BL_PROCESSOR) * NumberOfProcessors);
BlProcessorCount = NumberOfProcessors;
//
// Load distro.
//
BlSingularityLoadDistro();
//
// Load kernel image.
//
BlSingularityLoadKernelImage();
//
// Allocate native platform structure.
//
BlPlatform = (Class_Microsoft_Singularity_Hal_Platform *) BlMmAllocatePhysicalRegion(ROUND_UP_TO_PAGES(sizeof(Class_Microsoft_Singularity_Hal_Platform)), BL_MM_PHYSICAL_REGION_NATIVE_PLATFORM);
BlPlatform->Size = sizeof(Class_Microsoft_Singularity_Hal_Platform);
if (IsApicPresent()) {
BlPlatform->hasApic = 1;
}
else {
BlPlatform->hasApic = 0;
}
//
// Set offsets for per-cpu and per-thread pointers.
//
BlPlatform->CpuRecordPointerOffset = 0;
BlPlatform->ThreadRecordPointerOffset = sizeof(PTR_TYPE);
//
// Set boot time.
//
if (BlStartTime.Year != 0) {
BlPlatform->BootYear = 2000 + BlStartTime.Year;
BlPlatform->BootMonth = BlStartTime.Month;
BlPlatform->BootDay = BlStartTime.Day;
BlPlatform->BootHour = BlStartTime.Hour;
BlPlatform->BootMinute = BlStartTime.Minute;
BlPlatform->BootSecond = BlStartTime.Second;
}
//
// Set processor count.
//
BlPlatform->CpuRealCount = NumberOfProcessors;
BlPlatform->CpuMaxCount = NumberOfProcessors;
//
// Set MPS floating pointer structure address.
//
BlPlatform->MpFloat32 = (UINT32) (ULONG_PTR) BlMpsFps;
//
// Set kernel range.
//
BlPlatform->KernelDllBase = (ULONG_PTR) BlKernelBase;
BlPlatform->KernelDllFirstPage = (ULONG_PTR) BlKernelBase;
BlPlatform->KernelDllSize = BlKernelSize;
//
// Set command line.
//
BlPlatform->CommandLine32 = (ULONG_PTR) BlCommandLine;
BlPlatform->CommandLineCount = BlRtlStringLengthW(BlCommandLine);
//
// Set PNP node list address.
//
BlPlatform->PnpNodesAddr32 = (ULONG_PTR) BlPnpSystemDeviceNodeList;
BlPlatform->PnpNodesSize32 = BlPnpSystemDeviceNodeListSize;
//
// Set ISA information.
//
BlPlatform->IsaCsns = BlPnpIsaConfiguration.NumberOfCardSelectNumbers;
BlPlatform->IsaReadPort = BlPnpIsaConfiguration.DataReadPort;
//
// Set PCI BIOS information.
//
BlPlatform->PciBiosAX = BlPciInstallationCheck.Eax;
BlPlatform->PciBiosBX = BlPciInstallationCheck.Ebx;
BlPlatform->PciBiosCX = BlPciInstallationCheck.Ecx;
BlPlatform->PciBiosEDX = BlPciInstallationCheck.Edx;
//
// Set VESA information.
//
BlPlatform->VesaBuffer = BlVesaVideoBuffer;
//
// Set ACPI information.
//
BlPlatform->AcpiRoot32 = (ULONG_PTR) BlAcpiRsdpAddress;
//
// Set file image table.
//
BlPlatform->FileImageTableBase32 = (ULONG_PTR) BlSingularityFileImageTable;
BlPlatform->FileImageTableEntries = BlSingularityFileImageTableSize;
//
// Allocate log record and text buffers.
//
BlPlatform->LogRecordBuffer = (ULONG_PTR) BlMmAllocatePhysicalRegion(SINGULARITY_LOG_RECORD_SIZE, BL_MM_PHYSICAL_REGION_LOG_RECORD);
BlPlatform->LogRecordSize = SINGULARITY_LOG_RECORD_SIZE;
BlPlatform->LogTextBuffer = (ULONG_PTR) BlMmAllocatePhysicalRegion(SINGULARITY_LOG_TEXT_SIZE, BL_MM_PHYSICAL_REGION_LOG_TEXT);
BlPlatform->LogTextSize = SINGULARITY_LOG_TEXT_SIZE;
//
// Set debugger settings.
//
if (BlKdComPort != 0) {
BlPlatform->DebuggerType = Class_Microsoft_Singularity_Hal_Platform_DEBUGGER_SERIAL;
BlPlatform->DebugBasePort = BlComBasePort[BlKdComPort];
}
else if (BlPciOhci1394BaseAddress != 0) {
BlRtlPrintf("Got 1394 debugger base address!\n");
BlPlatform->DebuggerType = Class_Microsoft_Singularity_Hal_Platform_DEBUGGER_1394;
BlPlatform->Ohci1394Base = BlPciOhci1394BaseAddress;
BlPlatform->Ohci1394BufferAddr32 = (ULONG_PTR) BlSingularityOhci1394Buffer;
BlPlatform->Ohci1394BufferSize32 = sizeof(BlSingularityOhci1394Buffer);
}
else {
BlRtlPrintf("Debugger OFF\n");
BlPlatform->DebuggerType = Class_Microsoft_Singularity_Hal_Platform_DEBUGGER_NONE;
}
BlPlatform->TwiddleSpinBase = 0xb8000;
//
// Set exit routine.
//
BlPlatform->Kill32 = (ULONG_PTR) BlSingularityExit;
//
// Set entry routine and startup lock address for application processors.
//
BlPlatform->MpEnter32 = (ULONG_PTR) BlRtlConvertFarPointerToLinearPointer(ApEntry16);
BlPlatform->MpStartupLock32 = (ULONG_PTR) BlRtlConvertFarPointerToLinearPointer(ApStartupLock);
//
// Allocate native processor structures.
//
BlCpuArray =
(Class_Microsoft_Singularity_Hal_Cpu *) BlMmAllocatePhysicalRegion(ROUND_UP_TO_PAGES(sizeof(Class_Microsoft_Singularity_Hal_Cpu) * NumberOfProcessors), BL_MM_PHYSICAL_REGION_NATIVE_PROCESSOR);
BlPlatform->Cpus = (ULONG_PTR) BlCpuArray;
//
// Allocate per-processor resources upfront.
//
for (Index = 0; Index < NumberOfProcessors; Index += 1) {
BlProcessor[Index].Index = Index;
BlProcessor[Index].Cpu = &BlCpuArray[Index];
BlProcessor[Index].ContextPage = (PVOID) BlMmAllocatePhysicalRegion(2 * PAGE_SIZE, BL_MM_PHYSICAL_REGION_CONTEXT);
BlProcessor[Index].BasePage = (PVOID) ((ULONG_PTR) BlProcessor[Index].ContextPage + PAGE_SIZE);
BlProcessor[Index].TaskPage = (BL_TASK_SEGMENT *) BlMmAllocatePhysicalRegion(PAGE_SIZE, BL_MM_PHYSICAL_REGION_TASK);
}
//
// Allocate kernel stack for the bootstrap processor.
//
StackStart = BlMmAllocatePhysicalRegion(SINGULARITY_KERNEL_STACK_SIZE,
BL_MM_PHYSICAL_REGION_KERNEL_STACK);
if (0 == StackStart) {
BlRtlPrintf("Failed to allocate kernel stack.\n", StackStart);
BlRtlHalt();
}
BlRtlPrintf("Allocated kernel stack at 0x%016I64x\n", StackStart);
BlProcessor[0].KernelStack = (PVOID) (StackStart);
BlProcessor[0].Cpu->DomainBsp = TRUE;
BlPlatform->OutgoingMessage = 0;
BlPlatform->OutgoingCount = 0;
BlPlatform->IncomingFree = 0;
BlPlatform->IncomingFreeCount = 0;
BlPlatform->IncomingMessage = 0;
BlPlatform->IncomingCount = 0;
BlPlatform->OutgoingFree = 0;
BlPlatform->OutgoingFreeCount = 0;
BlPlatform->MaxBufferLength = 0;
BlProcessor[0].KernelStackSize = SINGULARITY_KERNEL_STACK_SIZE;
//
// Initialize the first processor structure.
//
BlSingularityInitializeProcessor(0);
//
// Allocate memory map for Singularity.
//
BlSingularitySmap = (PBL_SMAP) BlMmAllocatePhysicalRegion(sizeof(BL_SMAP), BL_MM_PHYSICAL_REGION_SINGULARITY_SMAP);
//
// Claim all remaining physical memory for Singularity.
//
while (BlMmFindFreePhysicalRegion(&Base, &Size) != FALSE) {
BlMmAllocateSpecificPhysicalRegion(Base, Size, BL_MM_PHYSICAL_REGION_SINGULARITY);
}
//
// Generate memory map for Singularity.
//
BlRtlZeroMemory(BlSingularitySmap, sizeof(BL_SMAP));
BlPlatform->PhysicalBase = (ULONG_PTR) -1;
PhysicalRegionHandle = NULL;
while (BlMmGetNextPhysicalRegion(&PhysicalRegionHandle,
&Base,
&Size,
&Type) != FALSE) {
if ((Type == BL_MM_PHYSICAL_REGION_SINGULARITY) ||
(Type == BL_MM_PHYSICAL_REGION_KERNEL_IMAGE) ||
(Type == BL_MM_PHYSICAL_REGION_NATIVE_PLATFORM) ||
(Type == BL_MM_PHYSICAL_REGION_NATIVE_PROCESSOR) ||
(Type == BL_MM_PHYSICAL_REGION_KERNEL_STACK)
) {
if (Type == BL_MM_PHYSICAL_REGION_SINGULARITY) {
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Base = Base;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Size = Size;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Type = BL_SMAP_AVAILABLE;
}
else if (Type == BL_MM_PHYSICAL_REGION_KERNEL_IMAGE ||
(Type == BL_MM_PHYSICAL_REGION_NATIVE_PLATFORM) ||
(Type == BL_MM_PHYSICAL_REGION_NATIVE_PROCESSOR)) {
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Base = Base;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Size = Size;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Type = BL_SMAP_KERNEL_NONGC;
}
else if (Type == BL_MM_PHYSICAL_REGION_KERNEL_STACK) {
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Base = Base;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Size = Size;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Type = BL_SMAP_KERNEL_STACK;
}
else {
BlRtlPrintf("UNKNOWN TYPE MEMORY??? %d\n", Type);
}
if (Base < BlPlatform->PhysicalBase) {
BlPlatform->PhysicalBase = (ULONG_PTR) Base;
}
BlSingularitySmap->EntryCount += 1;
}
else {
#if MM_VERBOSE
BlRtlPrintf("Building SMAP marking type %s nongc\n", BlMmPhysicalRegionTypeString(Type));
#endif
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Base = Base;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Size = Size;
BlSingularitySmap->Entry[BlSingularitySmap->EntryCount].Type = BL_SMAP_KERNEL_NONGC;
BlSingularitySmap->EntryCount += 1;
}
}
BlPlatform->Smap32 = (ULONG_PTR) (PVOID) BlSingularitySmap->Entry;
BlPlatform->SmapCount = BlSingularitySmap->EntryCount;
#if MM_VERBOSE
BlMmDumpPhysicalRegionList();
#endif
//
// Start processor 0.
//
BlSingularityProcessorToStart = 0;
BlMmSwitchStack((PVOID) BlProcessor[0].Cpu->KernelStackBegin, BlSingularityEnterKernel);
return;
}
VOID
BlSingularityApEntry(
VOID
)
//++
//
// Routine Description:
//
// This function implements the entry point for application processors.
//
//--
{
UINT32 Index;
UINT8 MyIdChar;
UINT32 MyId;
UINT32 MyStack;
Class_Microsoft_Singularity_Hal_Cpu *Processor;
// BlRtlPrintf("In Ap Entry\n");
// BlRtlPrintf("Non AP processor booting\n");
Index = BlPlatform->MpBootInfo.TargetCpu;
if (Index == 0) {
// BlRtlPrintf("BL: BSP entered AP code!\n");
BlRtlHalt();
}
#if SINGULARITY_VERBOSE
BlRtlPrintf("BL: Initializing processor %u of %u. [Max=%u]\n",
Index + 1,
BlPlatform->CpuRealCount,
BlPlatform->CpuMaxCount);
#endif
BlProcessor[Index].KernelStack = (PVOID) BlPlatform->MpBootInfo.KernelStackLimit;
BlProcessor[Index].Cpu->DomainBsp = FALSE;
BlProcessor[Index].KernelStackSize = BlPlatform->MpBootInfo.KernelStackBegin - BlPlatform->MpBootInfo.KernelStackLimit;
BlSingularityInitializeProcessor(Index);
BlSingularityProcessorToStart = Index;
BlMmSwitchStack((PVOID) BlProcessor[Index].Cpu->KernelStackBegin, BlSingularityEnterKernel);
return;
}