const DEVVTBL* IsoMount(ULONG DeviceId) { UCHAR Buffer[SECTORSIZE]; PPVD Pvd = (PPVD)Buffer; LARGE_INTEGER Position; ULONG Count; LONG ret; // // Read The Primary Volume Descriptor // Position.HighPart = 0; Position.LowPart = 16 * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) return NULL; ret = ArcRead(DeviceId, Pvd, SECTORSIZE, &Count); if (ret != ESUCCESS || Count < sizeof(PVD)) return NULL; // // Check if PVD is valid. If yes, return ISO9660 function table // if (Pvd->VdType == 1 && RtlEqualMemory(Pvd->StandardId, "CD001", 5)) return &Iso9660FuncTable; else return NULL; }
/* * IsoBufferDirectory() * This function allocates a buffer, reads the specified directory * and returns a pointer to that buffer into pDirectoryBuffer. The * function returns an ARC error code. The directory is specified * by its starting sector and length. */ static LONG IsoBufferDirectory(ULONG DeviceId, ULONG DirectoryStartSector, ULONG DirectoryLength, PVOID* pDirectoryBuffer) { PVOID DirectoryBuffer; ULONG SectorCount; LARGE_INTEGER Position; ULONG Count; ULONG ret; TRACE("IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector, DirectoryLength); SectorCount = ROUND_UP(DirectoryLength, SECTORSIZE) / SECTORSIZE; TRACE("Trying to read (DirectoryCount) %d sectors.\n", SectorCount); // // Attempt to allocate memory for directory buffer // TRACE("Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength); DirectoryBuffer = MmHeapAlloc(DirectoryLength); if (!DirectoryBuffer) return ENOMEM; // // Now read directory contents into DirectoryBuffer // Position.HighPart = 0; Position.LowPart = DirectoryStartSector * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) { MmHeapFree(DirectoryBuffer); return ret; } ret = ArcRead(DeviceId, DirectoryBuffer, SectorCount * SECTORSIZE, &Count); if (ret != ESUCCESS || Count != SectorCount * SECTORSIZE) { MmHeapFree(DirectoryBuffer); return EIO; } *pDirectoryBuffer = DirectoryBuffer; return ESUCCESS; }
NTSTATUS NTAPI IopReadBootRecord( IN PDEVICE_OBJECT DeviceObject, IN ULONGLONG LogicalSectorNumber, IN ULONG SectorSize, OUT PMASTER_BOOT_RECORD BootRecord) { ULONG FileId = (ULONG)DeviceObject; LARGE_INTEGER Position; ULONG BytesRead; ARC_STATUS Status; Position.QuadPart = LogicalSectorNumber * SectorSize; Status = ArcSeek(FileId, &Position, SeekAbsolute); if (Status != ESUCCESS) return STATUS_IO_DEVICE_ERROR; Status = ArcRead(FileId, BootRecord, SectorSize, &BytesRead); if (Status != ESUCCESS || BytesRead != SectorSize) return STATUS_IO_DEVICE_ERROR; return STATUS_SUCCESS; }
LONG IsoRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count) { PISO_FILE_INFO FileHandle = FsGetDeviceSpecific(FileId); UCHAR SectorBuffer[SECTORSIZE]; LARGE_INTEGER Position; ULONG DeviceId; ULONG FilePointer; ULONG SectorNumber; ULONG OffsetInSector; ULONG LengthInSector; ULONG NumberOfSectors; ULONG BytesRead; LONG ret; TRACE("IsoRead() Buffer = %p, N = %lu\n", Buffer, N); DeviceId = FsGetDeviceId(FileId); *Count = 0; // // If they are trying to read past the // end of the file then return success // with Count == 0 // FilePointer = FileHandle->FilePointer; if (FilePointer >= FileHandle->FileSize) { return ESUCCESS; } // // If they are trying to read more than there is to read // then adjust the amount to read // if (FilePointer + N > FileHandle->FileSize) { N = FileHandle->FileSize - FilePointer; } // // Ok, now we have to perform at most 3 calculations // I'll draw you a picture (using nifty ASCII art): // // CurrentFilePointer -+ // | // +----------------+ // | // +-----------+-----------+-----------+-----------+ // | Sector 1 | Sector 2 | Sector 3 | Sector 4 | // +-----------+-----------+-----------+-----------+ // | | // +---------------+--------------------+ // | // N -----------------+ // // 1 - The first calculation (and read) will align // the file pointer with the next sector // boundary (if we are supposed to read that much) // 2 - The next calculation (and read) will read // in all the full sectors that the requested // amount of data would cover (in this case // sectors 2 & 3). // 3 - The last calculation (and read) would read // in the remainder of the data requested out of // the last sector. // // // Only do the first read if we // aren't aligned on a cluster boundary // if (FilePointer % SECTORSIZE) { // // Do the math for our first read // SectorNumber = FileHandle->FileStart + (FilePointer / SECTORSIZE); OffsetInSector = FilePointer % SECTORSIZE; LengthInSector = (N > (SECTORSIZE - OffsetInSector)) ? (SECTORSIZE - OffsetInSector) : N; // // Now do the read and update Count, N, FilePointer, & Buffer // Position.HighPart = 0; Position.LowPart = SectorNumber * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) { return ret; } ret = ArcRead(DeviceId, SectorBuffer, SECTORSIZE, &BytesRead); if (ret != ESUCCESS || BytesRead != SECTORSIZE) { return EIO; } RtlCopyMemory(Buffer, SectorBuffer + OffsetInSector, LengthInSector); *Count += LengthInSector; N -= LengthInSector; FilePointer += LengthInSector; Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInSector); } // // Do the math for our second read (if any data left) // if (N > 0) { // // Determine how many full clusters we need to read // NumberOfSectors = (N / SECTORSIZE); SectorNumber = FileHandle->FileStart + (FilePointer / SECTORSIZE); // // Now do the read and update Count, N, FilePointer, & Buffer // Position.HighPart = 0; Position.LowPart = SectorNumber * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) { return ret; } ret = ArcRead(DeviceId, Buffer, NumberOfSectors * SECTORSIZE, &BytesRead); if (ret != ESUCCESS || BytesRead != NumberOfSectors * SECTORSIZE) { return EIO; } *Count += NumberOfSectors * SECTORSIZE; N -= NumberOfSectors * SECTORSIZE; FilePointer += NumberOfSectors * SECTORSIZE; Buffer = (PVOID)((ULONG_PTR)Buffer + NumberOfSectors * SECTORSIZE); } // // Do the math for our third read (if any data left) // if (N > 0) { SectorNumber = FileHandle->FileStart + (FilePointer / SECTORSIZE); // // Now do the read and update Count, N, FilePointer, & Buffer // Position.HighPart = 0; Position.LowPart = SectorNumber * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) { return ret; } ret = ArcRead(DeviceId, SectorBuffer, SECTORSIZE, &BytesRead); if (ret != ESUCCESS || BytesRead != SECTORSIZE) { return EIO; } RtlCopyMemory(Buffer, SectorBuffer, N); *Count += N; FilePointer += N; } TRACE("IsoRead() done\n"); return ESUCCESS; }
/* * IsoLookupFile() * This function searches the file system for the * specified filename and fills in an ISO_FILE_INFO structure * with info describing the file, etc. returns ARC error code */ static LONG IsoLookupFile(PCSTR FileName, ULONG DeviceId, PISO_FILE_INFO IsoFileInfoPointer) { UCHAR Buffer[SECTORSIZE]; PPVD Pvd = (PPVD)Buffer; UINT32 i; ULONG NumberOfPathParts; CHAR PathPart[261]; PVOID DirectoryBuffer; ULONG DirectorySector; ULONG DirectoryLength; ISO_FILE_INFO IsoFileInfo; LARGE_INTEGER Position; ULONG Count; LONG ret; TRACE("IsoLookupFile() FileName = %s\n", FileName); RtlZeroMemory(IsoFileInfoPointer, sizeof(ISO_FILE_INFO)); RtlZeroMemory(&IsoFileInfo, sizeof(ISO_FILE_INFO)); // // Read The Primary Volume Descriptor // Position.HighPart = 0; Position.LowPart = 16 * SECTORSIZE; ret = ArcSeek(DeviceId, &Position, SeekAbsolute); if (ret != ESUCCESS) return ret; ret = ArcRead(DeviceId, Pvd, SECTORSIZE, &Count); if (ret != ESUCCESS || Count < sizeof(PVD)) return EIO; DirectorySector = Pvd->RootDirRecord.ExtentLocationL; DirectoryLength = Pvd->RootDirRecord.DataLengthL; // // Figure out how many sub-directories we are nested in // NumberOfPathParts = FsGetNumPathParts(FileName); // // Loop once for each part // for (i=0; i<NumberOfPathParts; i++) { // // Get first path part // FsGetFirstNameFromPath(PathPart, FileName); // // Advance to the next part of the path // for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++) { } FileName++; // // Buffer the directory contents // ret = IsoBufferDirectory(DeviceId, DirectorySector, DirectoryLength, &DirectoryBuffer); if (ret != ESUCCESS) return ret; // // Search for file name in directory // if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer, DirectoryLength, PathPart, &IsoFileInfo)) { MmHeapFree(DirectoryBuffer); return ENOENT; } MmHeapFree(DirectoryBuffer); // // If we have another sub-directory to go then // grab the start sector and file size // if ((i+1) < NumberOfPathParts) { DirectorySector = IsoFileInfo.FileStart; DirectoryLength = IsoFileInfo.FileSize; } } RtlCopyMemory(IsoFileInfoPointer, &IsoFileInfo, sizeof(ISO_FILE_INFO)); return ESUCCESS; }
BOOLEAN BlReadSignature( IN PCHAR DiskName, IN BOOLEAN IsCdRom ) /*++ Routine Description: Given an ARC disk name, reads the MBR and adds its signature to the list of disks. Arguments: Diskname - Supplies the name of the disk. IsCdRom - Indicates whether the disk is a CD-ROM. Return Value: TRUE - Success FALSE - Failure --*/ { PARC_DISK_SIGNATURE Signature; UCHAR SectorBuffer[2048+256]; UCHAR Partition[100]; ULONG DiskId; ULONG Status; LARGE_INTEGER SeekValue; PUCHAR Sector; ULONG i; ULONG Sum; ULONG Count; ULONG SectorSize; if (IsCdRom) { SectorSize = 2048; } else { SectorSize = 512; } Signature = BlAllocateHeap(sizeof(ARC_DISK_SIGNATURE)); if (Signature==NULL) { return(FALSE); } Signature->ArcName = BlAllocateHeap(strlen(DiskName)+2); if (Signature->ArcName==NULL) { return(FALSE); } #if defined(_i386_) // // NTDETECT creates an "eisa(0)..." arcname for detected // BIOS disks on an EISA machine. Change this to "multi(0)..." // in order to be consistent with the rest of the system // (particularly the arcname in boot.ini) // if (_strnicmp(DiskName,"eisa",4)==0) { strcpy(Signature->ArcName,"multi"); strcpy(Partition,"multi"); strcat(Signature->ArcName,DiskName+4); strcat(Partition,DiskName+4); } else { strcpy(Signature->ArcName, DiskName); strcpy(Partition, DiskName); } #else strcpy(Signature->ArcName, DiskName); strcpy(Partition, DiskName); #endif strcat(Partition, "partition(0)"); Status = ArcOpen(Partition, ArcOpenReadOnly, &DiskId); if (Status != ESUCCESS) { return(TRUE); } // // Read in the first sector // Sector = ALIGN_BUFFER(SectorBuffer); if (IsCdRom) { // // For a CD-ROM, the interesting data starts at 0x8000. // SeekValue.QuadPart = 0x8000; } else { SeekValue.QuadPart = 0; } Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute); if (Status == ESUCCESS) { Status = ArcRead(DiskId, Sector, SectorSize, &Count); } ArcClose(DiskId); if (Status != ESUCCESS) { return(TRUE); } // // Check to see whether this disk has a valid partition table signature or not. // if (((PUSHORT)Sector)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) { Signature->ValidPartitionTable = FALSE; } else { Signature->ValidPartitionTable = TRUE; } Signature->Signature = ((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1]; // // compute the checksum // Sum = 0; for (i=0; i<(SectorSize/4); i++) { Sum += ((PULONG)Sector)[i]; } Signature->CheckSum = ~Sum + 1; InsertHeadList(&BlLoaderBlock->ArcDiskInformation->DiskSignatures, &Signature->ListEntry); return(TRUE); }
/* * WinLdrLoadImage loads the specified image from the file (it doesn't * perform any additional operations on the filename, just directly * calls the file I/O routines), and relocates it so that it's ready * to be used when paging is enabled. * Addressing mode: physical */ BOOLEAN WinLdrLoadImage(IN PCHAR FileName, TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA) { ULONG FileId; PVOID PhysicalBase; PVOID VirtualBase = NULL; UCHAR HeadersBuffer[SECTOR_SIZE * 2]; PIMAGE_NT_HEADERS NtHeaders; PIMAGE_SECTION_HEADER SectionHeader; ULONG VirtualSize, SizeOfRawData, NumberOfSections; ARC_STATUS Status; LARGE_INTEGER Position; ULONG i, BytesRead; TRACE("WinLdrLoadImage(%s, %ld, *)\n", FileName, MemoryType); /* Open the image file */ Status = ArcOpen(FileName, OpenReadOnly, &FileId); if (Status != ESUCCESS) { // UiMessageBox("Can not open the file."); return FALSE; } /* Load the first 2 sectors of the image so we can read the PE header */ Status = ArcRead(FileId, HeadersBuffer, SECTOR_SIZE * 2, &BytesRead); if (Status != ESUCCESS) { UiMessageBox("Error reading from file."); ArcClose(FileId); return FALSE; } /* Now read the MZ header to get the offset to the PE Header */ NtHeaders = RtlImageNtHeader(HeadersBuffer); if (!NtHeaders) { // Print(L"Error - no NT header found in %s\n", FileName); UiMessageBox("Error - no NT header found."); ArcClose(FileId); return FALSE; } /* Ensure this is executable image */ if (((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0)) { // Print(L"Not an executable image %s\n", FileName); UiMessageBox("Not an executable image."); ArcClose(FileId); return FALSE; } /* Store number of sections to read and a pointer to the first section */ NumberOfSections = NtHeaders->FileHeader.NumberOfSections; SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); /* Try to allocate this memory, if fails - allocate somewhere else */ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage, (PVOID)((ULONG)NtHeaders->OptionalHeader.ImageBase & (KSEG0_BASE - 1)), MemoryType); if (PhysicalBase == NULL) { /* It's ok, we don't panic - let's allocate again at any other "low" place */ PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage, MemoryType); if (PhysicalBase == NULL) { // Print(L"Failed to alloc pages for image %s\n", FileName); UiMessageBox("Failed to alloc pages for image."); ArcClose(FileId); return FALSE; } } /* This is the real image base - in form of a virtual address */ VirtualBase = PaToVa(PhysicalBase); TRACE("Base PA: 0x%X, VA: 0x%X\n", PhysicalBase, VirtualBase); /* Set to 0 position and fully load the file image */ Position.HighPart = Position.LowPart = 0; Status = ArcSeek(FileId, &Position, SeekAbsolute); if (Status != ESUCCESS) { UiMessageBox("Error seeking to start of file."); ArcClose(FileId); return FALSE; } Status = ArcRead(FileId, PhysicalBase, NtHeaders->OptionalHeader.SizeOfHeaders, &BytesRead); if (Status != ESUCCESS) { // Print(L"Error reading headers %s\n", FileName); UiMessageBox("Error reading headers."); ArcClose(FileId); return FALSE; } /* Reload the NT Header */ NtHeaders = RtlImageNtHeader(PhysicalBase); /* Load the first section */ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); /* Fill output parameters */ *ImageBasePA = PhysicalBase; /* Walk through each section and read it (check/fix any possible bad situations, if they arise) */ for (i = 0; i < NumberOfSections; i++) { VirtualSize = SectionHeader->Misc.VirtualSize; SizeOfRawData = SectionHeader->SizeOfRawData; /* Handle a case when VirtualSize equals 0 */ if (VirtualSize == 0) VirtualSize = SizeOfRawData; /* If PointerToRawData is 0, then force its size to be also 0 */ if (SectionHeader->PointerToRawData == 0) { SizeOfRawData = 0; } else { /* Cut the loaded size to the VirtualSize extents */ if (SizeOfRawData > VirtualSize) SizeOfRawData = VirtualSize; } /* Actually read the section (if its size is not 0) */ if (SizeOfRawData != 0) { /* Seek to the correct position */ Position.LowPart = SectionHeader->PointerToRawData; Status = ArcSeek(FileId, &Position, SeekAbsolute); TRACE("SH->VA: 0x%X\n", SectionHeader->VirtualAddress); /* Read this section from the file, size = SizeOfRawData */ Status = ArcRead(FileId, (PUCHAR)PhysicalBase + SectionHeader->VirtualAddress, SizeOfRawData, &BytesRead); if (Status != ESUCCESS) { ERR("WinLdrLoadImage(): Error reading section from file!\n"); break; } } /* Size of data is less than the virtual size - fill up the remainder with zeroes */ if (SizeOfRawData < VirtualSize) { TRACE("WinLdrLoadImage(): SORD %d < VS %d\n", SizeOfRawData, VirtualSize); RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG_PTR)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData); } SectionHeader++; } /* We are done with the file - close it */ ArcClose(FileId); /* If loading failed - return right now */ if (Status != ESUCCESS) return FALSE; /* Relocate the image, if it needs it */ if (NtHeaders->OptionalHeader.ImageBase != (ULONG_PTR)VirtualBase) { WARN("Relocating %p -> %p\n", NtHeaders->OptionalHeader.ImageBase, VirtualBase); return (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase, (ULONG_PTR)VirtualBase - (ULONG_PTR)PhysicalBase, "FreeLdr", TRUE, TRUE, /* in case of conflict still return success */ FALSE); } TRACE("WinLdrLoadImage() done, PA = %p\n", *ImageBasePA); return TRUE; }
ARC_STATUS LowWriteSectors( IN ULONG VolumeId, IN ULONG SectorSize, IN ULONG StartingSector, IN ULONG NumberOfSectors, IN PVOID Buffer ) /*++ Routine Description: This routine write 'NumberOfSectors' sectors starting at sector 'StartingSector' on the volume with ID 'VolumeId'. Arguments: VolumeId - Supplies the ID for the volume. SectorSize - Supplies the number of bytes per sector. StartingSector - Supplies the starting sector for the write. NumberOfSectors - Supplies the number of sectors to write. Buffer - Supplies the sectors to write. Return Value: ArcSeek, ArcWrite, EIO, ESUCCESS --*/ { ARC_STATUS r; ULONG c; LARGE_INTEGER l; ULONG i; ULONG transfer; PCHAR buf; ULONG total; l.QuadPart = UInt32x32To64(StartingSector,SectorSize); buf = (PCHAR) Buffer; r = ArcSeek(VolumeId, &l, SeekAbsolute); if (r != ESUCCESS) { return r; } total = SectorSize*NumberOfSectors; for (i = 0; i < total; i += MAX_TRANSFER) { transfer = min(MAX_TRANSFER, total - i); r = ArcWrite(VolumeId, &buf[i], transfer, &c); if (r != ESUCCESS) { return r; } if (c != transfer) { return EIO; } } return ESUCCESS; }
ARC_STATUS CdfsReadDisk( IN ULONG DeviceId, IN ULONG Lbo, IN ULONG ByteCount, IN OUT PVOID Buffer ) /*++ Routine Description: This routine reads in zero or more sectors from the specified device. Arguments: DeviceId - Supplies the device id to use in the arc calls. Lbo - Supplies the LBO to start reading from. ByteCount - Supplies the number of bytes to read. Buffer - Supplies a pointer to the buffer to read the bytes into. Return Value: ESUCCESS is returned if the read operation is successful. Otherwise, an unsuccessful status is returned that describes the reason for failure. --*/ { LARGE_INTEGER LargeLbo; ARC_STATUS Status; ULONG i; // // Seek to the appropriate offset on the volume // LargeLbo.LowPart = Lbo; LargeLbo.HighPart = 0; if ((Status = ArcSeek( DeviceId, &LargeLbo , SeekAbsolute )) != ESUCCESS) { return Status; } // // Issue the arc read request // if ((Status = ArcRead( DeviceId, Buffer, ByteCount, &i)) != ESUCCESS) { return Status; } // // Make sure we got back the amount requested // if (ByteCount != i) { return EIO; } // // Everything is fine so return success to our caller // return ESUCCESS; }
VOID BlpRebootDOS( IN PCHAR BootSectorImage OPTIONAL ) /*++ Routine Description: Loads up the bootstrap sectors and executes them (thereby rebooting into DOS or OS/2) Arguments: BootSectorImage - If specified, supplies name of file on the C: drive that contains the boot sector image. In this case, this routine will return if that file cannot be opened (for example, if it's a directory). If not specified, then default to \bootsect.dos, and this routine will never return. Return Value: None. --*/ { ULONG SectorId; ARC_STATUS Status; ULONG Read; ULONG DriveId; ULONG BootType; LARGE_INTEGER SeekPosition; extern UCHAR BootPartitionName[]; // // HACKHACK John Vert (jvert) // Some SCSI drives get really confused and return zeroes when // you use the BIOS to query their size after the AHA driver has // initialized. This can completely tube OS/2 or DOS. So here // we try and open both BIOS-accessible hard drives. Our open // code is smart enough to retry if it gets back zeros, so hopefully // this will give the SCSI drives a chance to get their act together. // Status = ArcOpen("multi(0)disk(0)rdisk(0)partition(0)", ArcOpenReadOnly, &DriveId); if (Status == ESUCCESS) { ArcClose(DriveId); } Status = ArcOpen("multi(0)disk(0)rdisk(1)partition(0)", ArcOpenReadOnly, &DriveId); if (Status == ESUCCESS) { ArcClose(DriveId); } // // Load the boot sector at address 0x7C00 (expected by Reboot callback) // Status = ArcOpen(BootPartitionName, ArcOpenReadOnly, &DriveId); if (Status != ESUCCESS) { BlPrint(BlFindMessage(BL_REBOOT_IO_ERROR),BootPartitionName); while (1) { GET_KEY(); } } Status = BlOpen( DriveId, BootSectorImage ? BootSectorImage : "\\bootsect.dos", ArcOpenReadOnly, &SectorId ); if (Status != ESUCCESS) { if(BootSectorImage) { // // The boot sector image might actually be a directory. // Return to the caller to attempt standard boot. // BlClose(DriveId); return; } BlPrint(BlFindMessage(BL_REBOOT_IO_ERROR),BootPartitionName); while (1) { } } Status = BlRead( SectorId, (PVOID)0x7c00, SECTOR_SIZE, &Read ); if (Status != ESUCCESS) { BlPrint(BlFindMessage(BL_REBOOT_IO_ERROR),BootPartitionName); while (1) { } } // // The FAT boot code is only one sector long so we just want // to load it up and jump to it. // // For HPFS and NTFS, we can't do this because the first sector // loads the rest of the boot sectors -- but we want to use // the boot code in the boot sector image file we loaded. // // For HPFS, we load the first 20 sectors (boot code + super and // space blocks) into d00:200. Fortunately this works for both // NT and OS/2. // // For NTFS, we load the first 16 sectors and jump to d00:256. // If the OEM field of the boot sector starts with NTFS, we // assume it's NTFS boot code. // // // Try to read 8K from the boot code image. // If this succeeds, we have either HPFS or NTFS. // SeekPosition.QuadPart = 0; BlSeek(SectorId,&SeekPosition,SeekAbsolute); BlRead(SectorId,(PVOID)0xd000,SECTOR_SIZE*16,&Read); if(Read == SECTOR_SIZE*16) { if(memcmp((PVOID)0x7c03,"NTFS",4)) { // // HPFS -- we need to load the super block. // BootType = 1; // HPFS SeekPosition.QuadPart = 16*SECTOR_SIZE; ArcSeek(DriveId,&SeekPosition,SeekAbsolute); ArcRead(DriveId,(PVOID)0xf000,SECTOR_SIZE*4,&Read); } else { // // NTFS -- we've loaded everything we need to load. // BootType = 2; // NTFS } } else { BootType = 0; // FAT } // // DX must be the drive to boot from // _asm { mov dx, 0x80 } REBOOT(BootType); }