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 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 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 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); } }