UINT32 BlAcpiGetNumberOfProcessors( VOID ) //++ // // Routine Description: // // This function returns the number of processors. // // Return Value: // // Number of processors. // //-- { PACPI_MADT_ENTRY Entry; PCHAR Limit; PACPI_PROCESSOR_LOCAL_APIC LocalApic; PCHAR Next; UINT32 NumberOfProcessors; if (BlAcpiMadt == NULL) { return 1; } Next = (PCHAR) &BlAcpiMadt->ApicStructures[0]; Limit = ((PCHAR) BlAcpiMadt) + BlAcpiMadt->Length; NumberOfProcessors = 0; while (Next < Limit) { Entry = (PACPI_MADT_ENTRY) Next; if ((Entry->Type == ACPI_APIC_TYPE_PROCESSOR_LOCAL) && (Entry->Length >= sizeof(ACPI_PROCESSOR_LOCAL_APIC))) { LocalApic = (PACPI_PROCESSOR_LOCAL_APIC) Next; if (LocalApic->u1.s1.Enabled != FALSE) { #if ACPI_VERBOSE BlRtlPrintf("ACPI: AcpiProcessorId=%u , LocalApicId=%u\n", LocalApic->AcpiProcessorId, LocalApic->ApicId); #endif NumberOfProcessors += 1; } } Next += Entry->Length; } return NumberOfProcessors; }
VOID BlAcpiResetSystem( VOID ) //++ // // Routine Description: // // This function resets the system through the ACPI reset register. // //-- { if ((BlAcpiFadt->Revision < 2) || (BlAcpiFadt->Length < (FIELD_OFFSET(ACPI_FADT, ResetValue) + sizeof(UINT8))) || ((BlAcpiFadt->Flags & ACPI_FADT_FLAGS_RESET_SUPPORTED) == 0) ) { #if ACPI_VERBOSE BlRtlPrintf("ACPI: Reset register is not supported! [FADT v%u]\n", BlAcpiFadt->Revision); #endif return; } #if ACPI_VERBOSE BlRtlPrintf("ACPI: Reset register type is %u.\n", BlAcpiFadt->ResetRegister.AddressSpaceId); #endif switch (BlAcpiFadt->ResetRegister.AddressSpaceId) { case ACPI_GAS_IO: { BlRtlWritePort8((UINT16) BlAcpiFadt->ResetRegister.Address, BlAcpiFadt->ResetValue); break; } } }
PACPI_SRAT BlAcpiLocateSrat( PACPI_RSDT Rsdt ) //++ // // Routine Description: // // This function locates the ACPI SRAT structure. // // Arguments: // // Rsdt - Supplies a pointer to the ACPI RSDT structure. // // Return Value: // // ACPI SRAT structure, if located. // NULL, otherwise. // //-- { UINT32 Index; PACPI_SRAT Srat; UINT32 NumberOfTables; NumberOfTables = (Rsdt->Length - FIELD_OFFSET(ACPI_RSDT, Entry)) / sizeof(Rsdt->Entry[0]); for (Index = 0; Index < NumberOfTables; Index += 1) { Srat = (PACPI_SRAT) (ULONG_PTR) Rsdt->Entry[Index]; if ((Srat->Signature[0] == 'S') && (Srat->Signature[1] == 'R') && (Srat->Signature[2] == 'A') && (Srat->Signature[3] == 'T') && (Srat->Length >= sizeof(ACPI_SRAT)) && (BlRtlComputeChecksum8(Srat, Srat->Length) == 0)) { #if ACPI_VERBOSE BlRtlPrintf("ACPI: Found SRAT Table\n"); #endif return Srat; } } return NULL; }
VOID BlPeLoadImage( PVOID LoadBase, PVOID Image, PVOID *EntryPoint ) //++ // // Routine Description: // // This function loads the specified image. // // Arguments: // // Image - Supplies a pointer to the image to load. // // EntryPoint - Receives a pointer to the entry point of the image. // //-- { ULONG_PTR BytesToCopy; PIMAGE_DOS_HEADER DosHeader; UINT32 Index; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER Section; ULONG_PTR VirtualBase; ULONG_PTR RelocDiff; VirtualBase = (ULONG_PTR) LoadBase; DosHeader = (PIMAGE_DOS_HEADER) Image; if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) { BlRtlPrintf("PECOFF: Missing MZ!\n"); BlRtlHalt(); } NtHeader = (PIMAGE_NT_HEADERS) ((ULONG_PTR) Image + DosHeader->e_lfanew); if (NtHeader->Signature != IMAGE_NT_SIGNATURE) { BlRtlPrintf("PECOFF: Missing PE!\n"); BlRtlHalt(); } if (NtHeader->FileHeader.NumberOfSections == 0) { BlRtlPrintf("PECOFF: No sections!\n"); BlRtlHalt(); } if ((NtHeader->OptionalHeader.ImageBase % PAGE_SIZE) != 0) { BlRtlPrintf("PECOFF: Not page aligned.\n"); BlRtlHalt(); } BlRtlCopyMemory((PVOID) VirtualBase, Image, NtHeader->OptionalHeader.SizeOfHeaders); Section = (PIMAGE_SECTION_HEADER) (((ULONG_PTR) &NtHeader->OptionalHeader) + NtHeader->FileHeader.SizeOfOptionalHeader); for (Index = 0; Index < NtHeader->FileHeader.NumberOfSections; Index += 1) { BlRtlZeroMemory((PVOID) (VirtualBase + Section[Index].VirtualAddress), Section[Index].Misc.VirtualSize); if (Section[Index].SizeOfRawData < Section[Index].Misc.VirtualSize) { BytesToCopy = Section[Index].SizeOfRawData; } else { BytesToCopy = Section[Index].Misc.VirtualSize; } BlRtlCopyMemory((PVOID) (VirtualBase + Section[Index].VirtualAddress), (PVOID) (((ULONG_PTR) Image) + Section[Index].PointerToRawData), BytesToCopy); #if PECOFF_VERBOSE { CHAR Temp[IMAGE_SIZEOF_SHORT_NAME + 1]; BlRtlCopyMemory(Temp, Section[Index].Name, IMAGE_SIZEOF_SHORT_NAME); Temp[IMAGE_SIZEOF_SHORT_NAME] = 0; BlRtlPrintf("PECOFF: %p ... %p (%p ... %p) %s\n", VirtualBase + Section[Index].VirtualAddress, VirtualBase + Section[Index].VirtualAddress + Section[Index].Misc.VirtualSize - 1, (((ULONG_PTR) Image) + Section[Index].PointerToRawData), (((ULONG_PTR) Image) + Section[Index].PointerToRawData) + BytesToCopy, Temp); } #endif } RelocDiff = VirtualBase - (ULONG_PTR)NtHeader->OptionalHeader.ImageBase; if (RelocDiff != 0) { PUINT8 RelocList; PUINT8 RelocListEnd; PIMAGE_BASE_RELOCATION Block; RelocList = (PUINT8) (VirtualBase + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); RelocListEnd = RelocList + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; #if PECOFF_VERBOSE BlRtlPrintf("PECOFF: Relocs: %p ... %p\n", RelocList, RelocListEnd); #endif while (RelocList < RelocListEnd) { Block = (PIMAGE_BASE_RELOCATION) RelocList; BlPeApplyFixupBlock(Block, VirtualBase, RelocDiff); RelocList += Block->SizeOfBlock; } } *EntryPoint = (PVOID) (VirtualBase + NtHeader->OptionalHeader.AddressOfEntryPoint); return; }
VOID BlPeApplyFixupBlock( PIMAGE_BASE_RELOCATION Block, ULONG_PTR VirtualBase, ULONG_PTR RelocDiff ) //++ // // Routine Description: // // This function applies all of the base fixups in the specified block to the image. // // Arguments: // // Block - Supplies a pointer to the base relocation fixup block. // // VirtualBase - Supplies the target address of the image. // // RelocDiff - Supplies the offset of the image target address from the base address. // //-- { PUINT16 Reloc; PUINT16 BlockEnd; ULONG_PTR BlockBase; ULONG_PTR Target; Reloc = Block->TypeOffset; BlockEnd = (PUINT16) ( ((PUINT8) Block) + Block->SizeOfBlock); BlockBase = VirtualBase + Block->VirtualAddress; #if PECOFF_VERBOSE BlRtlPrintf("PECOFF: Reloc Block %p:\n", Block->VirtualAddress); #endif for (; Reloc < BlockEnd; Reloc++) { Target = BlockBase + (*Reloc & 0xfff); #if PECOFF_VERBOSE switch (*Reloc >> 12) { case IMAGE_REL_BASED_ABSOLUTE: { BlRtlPrintf("PECOFF: %p: abs:%x \r", (PUINT32) Target, * (PUINT32) Target); break; } case IMAGE_REL_BASED_HIGHLOW: { BlRtlPrintf("PECOFF: %p: r32:%x->%x \r", (PUINT32) Target, * (PUINT32) Target, * (PUINT32) Target + (UINT32) RelocDiff); break; } case IMAGE_REL_BASED_DIR64: { BlRtlPrintf("PECOFF: %p: r64:%lx->%lx \r", (PUINT64) Target, * (PUINT64) Target, * (PUINT64) Target + (UINT64) RelocDiff); break; } default: { BlRtlPrintf("PECOFF: %p: %x ??? \r", (PUINT32) Target, Reloc[0] >> 12); break; } } #endif switch (*Reloc >> 12) { case IMAGE_REL_BASED_ABSOLUTE: { break; } case IMAGE_REL_BASED_HIGHLOW: { * (PUINT32) Target += (UINT32) RelocDiff; break; } case IMAGE_REL_BASED_DIR64: { * (PUINT64 *) Target += (UINT64) RelocDiff; break; } default: { BlRtlPrintf("PECOFF: Illegal relocation.\n"); BlRtlHalt(); } } } }
VOID BlPeGetVirtualRange( PVOID Image, PVOID *VirtualBase, ULONG_PTR *VirtualSize ) //++ // // Routine Description: // // This function queries the virtual range for the specified image. // // Arguments: // // Image - Supplies a pointer to the image. // // VirtualBase - Receives the virtual base address of the image. // // VirtualSize - Receives the virtual size of the image. // //-- { PIMAGE_DOS_HEADER DosHeader; UINT32 Index; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER Section; UINT32 SectionEnd; DosHeader = (PIMAGE_DOS_HEADER) Image; if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) { BlRtlPrintf("PECOFF: Invalid image!\n"); BlRtlHalt(); } NtHeader = (PIMAGE_NT_HEADERS) ((ULONG_PTR) Image + DosHeader->e_lfanew); if (NtHeader->Signature != IMAGE_NT_SIGNATURE) { BlRtlPrintf("PECOFF: Invalid image!\n"); BlRtlHalt(); } if (NtHeader->FileHeader.NumberOfSections == 0) { BlRtlPrintf("PECOFF: Invalid image!\n"); BlRtlHalt(); } if ((NtHeader->OptionalHeader.ImageBase % PAGE_SIZE) != 0) { BlRtlPrintf("PECOFF: Invalid image!\n"); BlRtlHalt(); } *VirtualBase = (PVOID) NtHeader->OptionalHeader.ImageBase; *VirtualSize = 0; Section = (PIMAGE_SECTION_HEADER) (((ULONG_PTR) &NtHeader->OptionalHeader) + NtHeader->FileHeader.SizeOfOptionalHeader); for (Index = 0; Index < NtHeader->FileHeader.NumberOfSections; Index += 1) { SectionEnd = Section[Index].VirtualAddress + Section[Index].Misc.VirtualSize; if (SectionEnd > *VirtualSize) { *VirtualSize = SectionEnd; } } *VirtualSize = ROUND_UP_TO_PAGES(*VirtualSize); return; }
VOID BlAcpiInitialize( VOID ) //++ // // Routine Description: // // This function initializes ACPI support for the boot loader. // //-- { BlAcpiRsdp = BlAcpiLocateRsdp(); if (BlAcpiRsdp == NULL) { BlRtlPrintf("ACPI: No RSDP!\n"); BlRtlHalt(); } BlAcpiRsdpAddress = (PVOID) BlAcpiRsdp; BlAcpiRsdt = BlAcpiLocateRsdt(BlAcpiRsdp); if (BlAcpiRsdt == NULL) { BlRtlPrintf("ACPI: No RSDT!\n"); BlRtlHalt(); } BlAcpiFadt = BlAcpiLocateFadt(BlAcpiRsdt); if (BlAcpiFadt == NULL) { BlRtlPrintf("ACPI: No FADT!\n"); //BlRtlHalt(); } BlAcpiMadt = BlAcpiLocateMadt(BlAcpiRsdt); if (BlAcpiMadt == NULL) { BlAcpiNumberOfProcessors = 1; } else { BlAcpiNumberOfProcessors = BlAcpiGetNumberOfProcessors(); } if (BlAcpiNumberOfProcessors == 0) { BlRtlPrintf("ACPI: No local APIC!\n"); BlRtlHalt(); } BlAcpiSrat = BlAcpiLocateSrat(BlAcpiRsdt); if (BlAcpiSrat != NULL) { BlAcpiDumpSratEntries(); } #if ACPI_VERBOSE BlRtlPrintf("ACPI: RSDP @ %p\n" "ACPI: RSDT @ %p\n" "ACPI: FADT @ %p [Revision=%u , Length=%u]\n" "ACPI: MADT @ %p\n" "ACPI: %u processor(s)\n", BlAcpiRsdp, BlAcpiRsdt, BlAcpiFadt, BlAcpiFadt->Revision, BlAcpiFadt->Length, BlAcpiMadt, BlAcpiNumberOfProcessors); #endif // // Map APIC page uncached. // if ((BlAcpiMadt != NULL) && (BlAcpiMadt->LocalApicAddress != 0)) { #if ACPI_VERBOSE BlRtlPrintf("ACPI: APIC mapped @ %p.\n", BlAcpiMadt->LocalApicAddress); #endif BlMmMapVirtualRange((PVOID) (ULONG_PTR) BlAcpiMadt->LocalApicAddress, (PVOID) (ULONG_PTR) BlAcpiMadt->LocalApicAddress, PAGE_SIZE, TRUE, FALSE, FALSE); } }
VOID BlAcpiDumpSratEntries( VOID ) //++ // // Routine Description: // // This function prints out the SRAT table. //-- { PACPI_SRAT_ENTRY Entry; PCHAR Limit; PACPI_SRAT_PROC_AFFINITY_ENTRY ProcAffinityEntry; PACPI_SRAT_MEM_AFFINITY_ENTRY MemAffinityEntry; PCHAR Next; UINT32 hbits; UINT32 totalbits; if (BlAcpiSrat == NULL) { BlRtlPrintf("ACPI: No Srat??\n"); return; } #if ACPI_VERBOSE BlRtlPrintf("SRAT:\n"); #endif Next = (PCHAR) &BlAcpiSrat->SratStructures[0]; Limit = ((PCHAR) BlAcpiSrat) + BlAcpiSrat->Length; while (Next < Limit) { Entry = (PACPI_SRAT_ENTRY) Next; if ((Entry->Type == ACPI_SRAT_TYPE_PROC_AFFINITY_ENTRY) && (Entry->Length >= sizeof(ACPI_SRAT_PROC_AFFINITY_ENTRY))) { ProcAffinityEntry = (PACPI_SRAT_PROC_AFFINITY_ENTRY) Next; #if ACPI_VERBOSE BlRtlPrintf(" Processor:\n"); #endif hbits = 0; hbits += ProcAffinityEntry->ProximityDomainHighTwentyFourBits[0] << 24; hbits += ProcAffinityEntry->ProximityDomainHighTwentyFourBits[1] << 16; hbits += ProcAffinityEntry->ProximityDomainHighTwentyFourBits[2] << 8; totalbits = hbits | ProcAffinityEntry->ProximityDomainLowEightBits; #if ACPI_VERBOSE BlRtlPrintf(" HighDomain 0x%06x LowDomain 0x%02x totalbits 0x%08x\n", hbits, ProcAffinityEntry->ProximityDomainLowEightBits, totalbits); BlRtlPrintf(" ApicID: %d flags 0x%08x\n", ProcAffinityEntry->ApicID, ProcAffinityEntry->Flags); #endif } else if ((Entry->Type == ACPI_SRAT_TYPE_MEM_AFFINITY_ENTRY) && (Entry->Length >= sizeof(ACPI_SRAT_MEM_AFFINITY_ENTRY))) { MemAffinityEntry = (PACPI_SRAT_MEM_AFFINITY_ENTRY) Next; #if ACPI_VERBOSE BlRtlPrintf(" Memory:\n"); BlRtlPrintf(" BaseAddress 0x%08x.%08x .. 0x%08x.%08x", MemAffinityEntry->BaseAddressHigh, MemAffinityEntry->BaseAddressLow, MemAffinityEntry->LengthHigh, MemAffinityEntry->LengthLow); BlRtlPrintf(" Domain %d Flags 0x%08x\n", MemAffinityEntry->ProximityDomain, MemAffinityEntry->Flags); #endif } Next += Entry->Length; } }