Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

364 lines
8.4 KiB

#include "bldr.h"
#include "sal.h"
#include "ssc.h"
#include "ntimage.h"
#define SECTOR_SIZE 512
SalDiskReadWrite(
ULONG ReadWrite,
ULONG SectorsToRead,
ULONG Cylinder,
ULONG CylinderPerSector,
ULONG Head,
ULONG Drive,
PUCHAR Buffer
)
{
IA32_BIOS_REGISTER_STATE IA32RegisterState;
BIT32_AND_BIT16 IA32Register;
if (ReadWrite == 0) {
IA32Register.HighPart16 = 0x02;
} else {
IA32Register.HighPart16 = 0x03;
}
IA32Register.LowPart16 = SectorsToRead;
IA32RegisterState.eax = IA32Register.Part32;
IA32Register.HighPart16 = Cylinder;
IA32Register.LowPart16 = CylinderPerSector;
IA32RegisterState.ecx = IA32Register.Part32;
IA32Register.HighPart16 = Head;
IA32Register.LowPart16 = Drive;
IA32RegisterState.edx = IA32Register.Part32;
IA32RegisterState.es = 0;
IA32Register.HighPart16 = 0;
IA32Register.LowPart16 = Buffer;
IA32RegisterState.ebx = IA32Register.Part32;
// SAL_PROC(0x100,&IA32RegisterState,0,0,0,0,0,0,);
}
ReadSectors(
ULONG SectorBase,
USHORT SectorCount,
PUCHAR Buffer)
{
static char *VolumeName = "\\\\.\\D:";
SSC_HANDLE VolumeHandle;
SSC_DISK_REQUEST Request[1];
SSC_DISK_COMPLETION DiskCompletion;
LARGE_INTEGER VolumeNamePtr;
LARGE_INTEGER RequestPtr;
LARGE_INTEGER VolumeOffset;
LARGE_INTEGER DiskCompletionPtr;
VolumeNamePtr.LowPart = VolumeName;
VolumeNamePtr.HighPart = 0;
VolumeHandle = SscDiskOpenVolume (VolumeNamePtr, SSC_ACCESS_READ);
Request[0].DiskBufferAddress.LowPart = Buffer;
Request[0].DiskBufferAddress.HighPart = 0;
Request[0].DiskByteCount = SectorCount * SECTOR_SIZE;
RequestPtr.LowPart = Request;
RequestPtr.HighPart = 0;
VolumeOffset.LowPart = SectorBase * SECTOR_SIZE;
VolumeOffset.HighPart = 0;
SscDiskReadVolume(VolumeHandle, 1, RequestPtr, VolumeOffset);
DiskCompletion.VolumeHandle = VolumeHandle;
DiskCompletionPtr.LowPart = &DiskCompletion;
DiskCompletionPtr.HighPart = 0;
while (1) {
if (SscDiskWaitIoCompletion(DiskCompletionPtr) == 0) break;
}
}
SalPrint(
PUCHAR Buffer
)
{
IA32_BIOS_REGISTER_STATE IA32RegisterState;
BIT32_AND_BIT16 IA32Register;
ULONG i;
for (i = 0; Buffer[i] != 0 && i < 256; i++) {
IA32Register.HighPart16 = 14;
IA32Register.LowPart16 = Buffer[i];
IA32RegisterState.eax = IA32Register.Part32;
IA32RegisterState.ebx = 7;
// SAL_PROC(0x100,&IA32RegisterState,0,0,0,0,0,0,);
}
}
Multiply(
ULONG Multiplicant,
ULONG Multiplier)
{
return(Multiplicant * Multiplier);
}
Divide(
ULONG Numerator,
ULONG Denominator,
PULONG Result,
PULONG Remainder
)
{
float f1, f2;
f1 = (float) Numerator;
f2 = (float) Denominator;
*Result = (ULONG) (f1 / f2);
*Remainder = Numerator % Denominator;
}
memcpy(
PUCHAR Source,
PUCHAR Destination,
ULONG Length
)
{
while (Length--) {
*Destination++ = *Source++;
}
}
memmove(
PUCHAR Source,
PUCHAR Destination,
ULONG Length
)
{
while (Length--) {
*Destination++ = *Source++;
}
}
memset(
PUCHAR Destination,
ULONG Length,
ULONG Value
)
{
while (Length--) {
*Destination++ = Value;
}
}
strncmp(
PUCHAR String1,
PUCHAR String2,
ULONG Length
)
{
while (Length--) {
if (*String1++ != *String2++)
return(String1);
}
return(0);
}
PrintName(
PUCHAR String
)
{
LARGE_INTEGER StringPtr;
StringPtr.LowPart = String;
StringPtr.HighPart = 0;
SscDbgPrintf(StringPtr);
}
BootErr$Print(
PUCHAR String
)
{
LARGE_INTEGER StringPtr;
StringPtr.LowPart = String;
StringPtr.HighPart = 0;
SscDbgPrintf(StringPtr);
}
LoadNtldrSymbols()
{
static char *NtfsBoot = "\\ntfsboot.exe";
static char *Ntldr = "\\NTLDR";
LARGE_INTEGER PhysicalPtr;
PhysicalPtr.LowPart = NtfsBoot;
PhysicalPtr.HighPart = 0;
SscUnloadImage(PhysicalPtr,
0x0,
(ULONG)-1,
(ULONG)0);
PhysicalPtr.LowPart = Ntldr;
PhysicalPtr.HighPart = 0;
SscLoadImage(PhysicalPtr,
0xE00000,
0x118A00,
0x7cc,
0, // process ID
1); // load count
}
ULONG
RelocateLoaderSections(
ULONG NtldrBuffer
)
/*++
Routine Description:
The SU module is prepended to the OS loader file. The OS loader file
is a coff++ file. This routine computes the beginning of the OS loader
file, then relocates the OS loader's sections as if it were just
loading the file from disk file.
Arguments:
NtldrBuffer - Buffer that contains the NTLDR raw image from disk
Returns:
Entry point of loader
--*/
{
ULONG Start, End;
USHORT Section;
ULONG Source,Destination;
ULONG VirtualSize;
ULONG SizeOfRawData;
PIMAGE_FILE_HEADER FileHeader;
PIMAGE_OPTIONAL_HEADER OptionalHeader;
PIMAGE_SECTION_HEADER SectionHeader;
//
// Make a pointer to the beginning of the loader's coff header
//
FileHeader = (PIMAGE_FILE_HEADER) NtldrBuffer;
//
// Validate the appended loader image by checking signatures.
// 1st - is it an executable image?
// 2nd - is the target environment the 386?
//
if ((FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0) {
SalPrint("SU_NTLDR_CORRUPT");
return;
}
if (FileHeader->Machine != IMAGE_FILE_MACHINE_IA64) {
SalPrint("SU_NTLDR_CORRUPT");
return;
}
//
// Make a pointer to the optional header in the header-buffer
//
OptionalHeader = (PIMAGE_OPTIONAL_HEADER)((PUCHAR)FileHeader +
sizeof(IMAGE_FILE_HEADER));
//
// Make a pointer to the first section in the header buffer
//
SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
Start = OptionalHeader->ImageBase+SectionHeader->VirtualAddress;
End = Start + SectionHeader->SizeOfRawData;
//
// Loop and relocate each section with a non-zero RawData size
//
for (Section=FileHeader->NumberOfSections ; Section-- ; SectionHeader++) {
//
// Compute source, destination, and count arguments
//
Source = NtldrBuffer + SectionHeader->PointerToRawData;
Destination = OptionalHeader->ImageBase + SectionHeader->VirtualAddress;
VirtualSize = SectionHeader->Misc.VirtualSize;
SizeOfRawData = SectionHeader->SizeOfRawData;
if (VirtualSize == 0) {
VirtualSize = SizeOfRawData;
}
if (SectionHeader->PointerToRawData == 0) {
//
// SizeOfRawData can be non-zero even if PointerToRawData is zero
//
SizeOfRawData = 0;
} else if (SizeOfRawData > VirtualSize) {
//
// Don't load more from image than is expected in memory
//
SizeOfRawData = VirtualSize;
}
if (Destination < Start) {
Start = Destination;
}
if (Destination+VirtualSize > End) {
End = Destination+VirtualSize;
}
if (SizeOfRawData != 0) {
//
// This section is either a code (.TEXT) section or an
// initialized data (.DATA) section.
// Relocate the section to memory at the virtual/physical
// addresses specified in the section header.
//
memmove(Source,Destination,SizeOfRawData);
}
if (SizeOfRawData < VirtualSize) {
//
// Zero the portion not loaded from the image
//
memset(Destination+SizeOfRawData,0,VirtualSize - SizeOfRawData);
}
#if 0
//
// Check if this is the resource section. If so, we need
// to pass its location to the osloader.
//
if ((SectionHeader->Name[0] == '.') &&
(SectionHeader->Name[1] == 'r') &&
(SectionHeader->Name[2] == 's') &&
(SectionHeader->Name[3] == 'r') &&
(SectionHeader->Name[4] == 'c')) {
ResourceDirectory = Destination;
ResourceOffset = SectionHeader->VirtualAddress;
}
#endif
}
return(OptionalHeader->AddressOfEntryPoint + OptionalHeader->ImageBase);
}