3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/xhaldrv.c
6 * PURPOSE: Hal drive routines
7 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
13 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/xhal.h>
19 #include <internal/debug.h>
21 /* LOCAL MACROS and TYPES ***************************************************/
23 #define AUTO_DRIVE ((ULONG)-1)
25 #define PARTITION_MAGIC 0xaa55
27 #define PARTITION_TBL_SIZE 4
30 typedef struct _PARTITION
32 unsigned char BootFlags; /* bootable? 0=no, 128=yes */
33 unsigned char StartingHead; /* beginning head number */
34 unsigned char StartingSector; /* beginning sector number */
35 unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
36 unsigned char PartitionType; /* Operating System type indicator code */
37 unsigned char EndingHead; /* ending head number */
38 unsigned char EndingSector; /* ending sector number */
39 unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
40 unsigned int StartingBlock; /* first sector relative to start of disk */
41 unsigned int SectorCount; /* number of sectors in partition */
42 } PACKED PARTITION, *PPARTITION;
45 typedef struct _PARTITION_SECTOR
47 UCHAR BootCode[440]; /* 0x000 */
48 ULONG Signature; /* 0x1B8 */
49 UCHAR Reserved[2]; /* 0x1BC */
50 PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */
51 USHORT Magic; /* 0x1FE */
52 } PACKED PARTITION_SECTOR, *PPARTITION_SECTOR;
55 typedef enum _DISK_MANAGER
63 /* FUNCTIONS *****************************************************************/
66 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
67 OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
69 IO_STATUS_BLOCK StatusBlock;
70 DISK_GEOMETRY DiskGeometry;
71 PDEVICE_OBJECT DeviceObject = NULL;
72 PFILE_OBJECT FileObject;
77 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
81 /* Get the drives sector size */
82 Status = IoGetDeviceObjectPointer(DeviceName,
86 if (!NT_SUCCESS(Status))
88 DPRINT("Status %x\n",Status);
92 KeInitializeEvent(&Event,
96 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
101 sizeof(DISK_GEOMETRY),
107 ObDereferenceObject(FileObject);
108 return(STATUS_INSUFFICIENT_RESOURCES);
111 Status = IoCallDriver(DeviceObject,
113 if (Status == STATUS_PENDING)
115 KeWaitForSingleObject(&Event,
120 Status = StatusBlock.Status;
122 if (!NT_SUCCESS(Status))
124 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
126 DiskGeometry.BytesPerSector = 512;
130 ObDereferenceObject(FileObject);
135 DPRINT("DiskGeometry.BytesPerSector: %d\n",
136 DiskGeometry.BytesPerSector);
138 /* Read the partition table */
139 Status = IoReadPartitionTable(DeviceObject,
140 DiskGeometry.BytesPerSector,
144 if ((!NT_SUCCESS(Status) || (*LayoutInfo)->PartitionCount == 0) &&
145 DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
147 PDRIVE_LAYOUT_INFORMATION Buffer;
149 if (NT_SUCCESS(Status))
151 ExFreePool(*LayoutInfo);
154 /* Allocate a partition list for a single entry. */
155 Buffer = ExAllocatePool(NonPagedPool,
156 sizeof(DRIVE_LAYOUT_INFORMATION));
159 RtlZeroMemory(Buffer,
160 sizeof(DRIVE_LAYOUT_INFORMATION));
161 Buffer->PartitionCount = 1;
162 *LayoutInfo = Buffer;
164 Status = STATUS_SUCCESS;
168 ObDereferenceObject(FileObject);
175 xHalpReadSector (IN PDEVICE_OBJECT DeviceObject,
177 IN PLARGE_INTEGER SectorOffset,
180 IO_STATUS_BLOCK StatusBlock;
185 DPRINT("xHalpReadSector() called\n");
187 assert(DeviceObject);
190 KeInitializeEvent(&Event,
194 /* Read the sector */
195 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
203 Status = IoCallDriver(DeviceObject,
205 if (Status == STATUS_PENDING)
207 KeWaitForSingleObject(&Event,
212 Status = StatusBlock.Status;
215 if (!NT_SUCCESS(Status))
217 DPRINT("Reading sector failed (Status 0x%08lx)\n",
227 xHalpWriteSector (IN PDEVICE_OBJECT DeviceObject,
229 IN PLARGE_INTEGER SectorOffset,
232 IO_STATUS_BLOCK StatusBlock;
237 DPRINT("xHalpWriteSector() called\n");
239 KeInitializeEvent(&Event,
243 /* Write the sector */
244 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
252 Status = IoCallDriver(DeviceObject,
254 if (Status == STATUS_PENDING)
256 KeWaitForSingleObject(&Event,
261 Status = StatusBlock.Status;
264 if (!NT_SUCCESS(Status))
266 DPRINT("Writing sector failed (Status 0x%08lx)\n",
275 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
277 IN ULONG MBRTypeIdentifier,
280 LARGE_INTEGER SectorOffset;
281 PPARTITION_SECTOR Sector;
284 DPRINT("xHalExamineMBR()\n");
288 if (SectorSize < 512)
290 if (SectorSize > 4096)
293 Sector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
297 DPRINT ("Partition sector allocation failed\n");
301 SectorOffset.QuadPart = 0LL;
302 Status = xHalpReadSector (DeviceObject,
306 if (!NT_SUCCESS(Status))
308 DPRINT("xHalpReadSector() failed (Status %lx)\n", Status);
313 if (Sector->Magic != PARTITION_MAGIC)
315 DPRINT("Invalid MBR magic value\n");
320 if (Sector->Partition[0].PartitionType != MBRTypeIdentifier)
322 DPRINT("Invalid MBRTypeIdentifier\n");
327 if (Sector->Partition[0].PartitionType == 0x54)
329 /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
330 DPRINT("Found 'Ontrack Disk Manager'!\n");
331 *((PULONG)Sector) = 63;
334 *Buffer = (PVOID)Sector;
339 HalpAssignDrive(IN PUNICODE_STRING PartitionName,
340 IN ULONG DriveNumber,
343 WCHAR DriveNameBuffer[8];
344 UNICODE_STRING DriveName;
347 DPRINT("HalpAssignDrive()\n");
349 if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 24))
351 /* Force assignment */
352 if ((SharedUserData->DosDeviceMap & (1 << DriveNumber)) != 0)
354 DbgPrint("Drive letter already used!\n");
360 /* Automatic assignment */
361 DriveNumber = AUTO_DRIVE;
363 for (i = 2; i < 24; i++)
365 if ((SharedUserData->DosDeviceMap & (1 << i)) == 0)
372 if (DriveNumber == AUTO_DRIVE)
374 DbgPrint("No drive letter available!\n");
379 DPRINT("DriveNumber %d\n", DriveNumber);
381 /* Update the shared user page */
382 SharedUserData->DosDeviceMap |= (1 << DriveNumber);
383 SharedUserData->DosDeviceDriveType[DriveNumber] = DriveType;
385 /* Build drive name */
386 swprintf(DriveNameBuffer,
389 RtlInitUnicodeString(&DriveName,
392 DPRINT(" %wZ ==> %wZ\n",
396 /* Create symbolic link */
397 IoCreateSymbolicLink(&DriveName,
403 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
404 IN PSTRING NtDeviceName,
405 OUT PUCHAR NtSystemPath,
406 OUT PSTRING NtSystemPathString)
408 PDRIVE_LAYOUT_INFORMATION *LayoutArray;
409 PCONFIGURATION_INFORMATION ConfigInfo;
410 OBJECT_ATTRIBUTES ObjectAttributes;
411 IO_STATUS_BLOCK StatusBlock;
412 UNICODE_STRING UnicodeString1;
413 UNICODE_STRING UnicodeString2;
421 DPRINT("xHalIoAssignDriveLetters()\n");
423 ConfigInfo = IoGetConfigurationInformation();
425 Buffer1 = (PWSTR)ExAllocatePool(PagedPool,
427 Buffer2 = (PWSTR)ExAllocatePool(PagedPool,
430 /* Create PhysicalDrive links */
431 DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount);
432 for (i = 0; i < ConfigInfo->DiskCount; i++)
435 L"\\Device\\Harddisk%d\\Partition0",
437 RtlInitUnicodeString(&UnicodeString1,
440 InitializeObjectAttributes(&ObjectAttributes,
446 Status = NtOpenFile(&FileHandle,
451 FILE_SYNCHRONOUS_IO_NONALERT);
452 if (NT_SUCCESS(Status))
457 L"\\??\\PhysicalDrive%d",
459 RtlInitUnicodeString(&UnicodeString2,
462 DPRINT("Creating link: %S ==> %S\n",
466 IoCreateSymbolicLink(&UnicodeString2,
471 /* Initialize layout array */
472 LayoutArray = ExAllocatePool(NonPagedPool,
473 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
474 RtlZeroMemory(LayoutArray,
475 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
476 for (i = 0; i < ConfigInfo->DiskCount; i++)
479 L"\\Device\\Harddisk%d\\Partition0",
481 RtlInitUnicodeString(&UnicodeString1,
484 Status = xHalQueryDriveLayout(&UnicodeString1,
486 if (!NT_SUCCESS(Status))
488 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
490 LayoutArray[i] = NULL;
496 /* Dump layout array */
497 for (i = 0; i < ConfigInfo->DiskCount; i++)
499 DPRINT("Harddisk %d:\n",
502 if (LayoutArray[i] == NULL)
505 DPRINT("Logical partitions: %d\n",
506 LayoutArray[i]->PartitionCount);
508 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
510 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
512 LayoutArray[i]->PartitionEntry[j].PartitionNumber,
513 LayoutArray[i]->PartitionEntry[j].BootIndicator,
514 LayoutArray[i]->PartitionEntry[j].PartitionType,
515 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
516 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
521 /* Assign pre-assigned (registry) partitions */
524 /* Assign bootable partition on first harddisk */
525 DPRINT("Assigning bootable primary partition on first harddisk:\n");
526 if (ConfigInfo->DiskCount > 0)
528 /* Search for bootable partition */
529 for (j = 0; j < LayoutArray[0]->PartitionCount; j++)
531 if ((LayoutArray[0]->PartitionEntry[j].BootIndicator == TRUE) &&
532 IsRecognizedPartition(LayoutArray[0]->PartitionEntry[j].PartitionType))
535 L"\\Device\\Harddisk0\\Partition%d",
536 LayoutArray[0]->PartitionEntry[j].PartitionNumber);
537 RtlInitUnicodeString(&UnicodeString2,
541 DPRINT(" %wZ\n", &UnicodeString2);
542 HalpAssignDrive(&UnicodeString2,
544 DOSDEVICE_DRIVE_FIXED);
549 /* Assign remaining primary partitions */
550 DPRINT("Assigning remaining primary partitions:\n");
551 for (i = 0; i < ConfigInfo->DiskCount; i++)
553 /* Search for primary partitions */
554 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[i]->PartitionCount); j++)
556 if ((i == 0) && (LayoutArray[i]->PartitionEntry[j].BootIndicator == TRUE))
559 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType))
562 L"\\Device\\Harddisk%d\\Partition%d",
564 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
565 RtlInitUnicodeString(&UnicodeString2,
571 HalpAssignDrive(&UnicodeString2,
573 DOSDEVICE_DRIVE_FIXED);
578 /* Assign extended (logical) partitions */
579 DPRINT("Assigning extended (logical) partitions:\n");
580 for (i = 0; i < ConfigInfo->DiskCount; i++)
584 /* Search for extended partitions */
585 for (j = PARTITION_TBL_SIZE; j < LayoutArray[i]->PartitionCount; j++)
587 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
588 (LayoutArray[i]->PartitionEntry[j].PartitionNumber != 0))
591 L"\\Device\\Harddisk%d\\Partition%d",
593 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
594 RtlInitUnicodeString(&UnicodeString2,
600 HalpAssignDrive(&UnicodeString2,
602 DOSDEVICE_DRIVE_FIXED);
608 /* Assign removable disk drives */
609 DPRINT("Assigning removable disk drives:\n");
610 for (i = 0; i < ConfigInfo->DiskCount; i++)
612 /* Search for virtual partitions */
613 if (LayoutArray[i]->PartitionCount == 1 &&
614 LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
617 L"\\Device\\Harddisk%d\\Partition1",
619 RtlInitUnicodeString(&UnicodeString2,
625 HalpAssignDrive(&UnicodeString2,
627 DOSDEVICE_DRIVE_REMOVABLE);
631 /* Free layout array */
632 for (i = 0; i < ConfigInfo->DiskCount; i++)
634 if (LayoutArray[i] != NULL)
635 ExFreePool(LayoutArray[i]);
637 ExFreePool(LayoutArray);
639 /* Assign floppy drives */
640 DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount);
641 for (i = 0; i < ConfigInfo->FloppyCount; i++)
644 L"\\Device\\Floppy%d",
646 RtlInitUnicodeString(&UnicodeString1,
649 /* Assign drive letters A: or B: or first free drive letter */
652 HalpAssignDrive(&UnicodeString1,
653 (i < 2) ? i : AUTO_DRIVE,
654 DOSDEVICE_DRIVE_REMOVABLE);
657 /* Assign cdrom drives */
658 DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount);
659 for (i = 0; i < ConfigInfo->CdRomCount; i++)
662 L"\\Device\\CdRom%d",
664 RtlInitUnicodeString(&UnicodeString1,
667 /* Assign first free drive letter */
668 DPRINT(" %wZ\n", &UnicodeString1);
669 HalpAssignDrive(&UnicodeString1,
671 DOSDEVICE_DRIVE_CDROM);
674 /* Anything else to do? */
682 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
684 BOOLEAN ReturnRecognizedPartitions,
685 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
687 LARGE_INTEGER RealPartitionOffset;
688 ULONGLONG PartitionOffset;
689 ULONGLONG nextPartitionOffset;
690 ULONGLONG containerOffset;
692 PPARTITION_SECTOR PartitionSector;
693 PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
697 BOOLEAN ExtendedFound = FALSE;
699 DISK_MANAGER DiskManager = NoDiskManager;
701 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
704 ReturnRecognizedPartitions,
707 *PartitionBuffer = NULL;
709 /* Check sector size */
710 if (SectorSize < 512)
712 if (SectorSize > 4096)
715 /* Check for 'Ontrack Disk Manager' */
716 xHalExamineMBR(DeviceObject,
720 if (MbrBuffer != NULL)
722 DPRINT("Found 'Ontrack Disk Manager'\n");
723 DiskManager = OntrackDiskManager;
724 ExFreePool(MbrBuffer);
727 /* Check for 'EZ-Drive' */
728 xHalExamineMBR(DeviceObject,
732 if (MbrBuffer != NULL)
734 DPRINT("Found 'EZ-Drive'\n");
735 DiskManager = EZ_Drive;
736 ExFreePool(MbrBuffer);
739 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
741 if (PartitionSector == NULL)
743 return(STATUS_INSUFFICIENT_RESOURCES);
746 LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool,
748 if (LayoutBuffer == NULL)
750 ExFreePool(PartitionSector);
751 return(STATUS_INSUFFICIENT_RESOURCES);
754 RtlZeroMemory(LayoutBuffer,
757 PartitionOffset = 0ULL;
758 containerOffset = 0ULL;
762 DPRINT("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
764 /* Handle disk managers */
765 if (DiskManager == OntrackDiskManager)
767 /* Shift offset by 63 sectors */
768 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
770 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
772 /* Use sector 1 instead of sector 0 */
773 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
777 RealPartitionOffset.QuadPart = PartitionOffset;
780 DPRINT ("RealPartitionOffset: %I64u\n",
781 RealPartitionOffset.QuadPart / SectorSize);
783 Status = xHalpReadSector (DeviceObject,
785 &RealPartitionOffset,
787 if (!NT_SUCCESS(Status))
789 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
791 ExFreePool (PartitionSector);
792 ExFreePool (LayoutBuffer);
796 /* Check the boot sector id */
797 DPRINT("Magic %x\n", PartitionSector->Magic);
798 if (PartitionSector->Magic != PARTITION_MAGIC)
800 DPRINT ("Invalid partition sector magic\n");
801 ExFreePool (PartitionSector);
802 *PartitionBuffer = LayoutBuffer;
803 return STATUS_SUCCESS;
807 for (i = 0; i < PARTITION_TBL_SIZE; i++)
809 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
811 PartitionSector->Partition[i].BootFlags,
812 PartitionSector->Partition[i].PartitionType,
813 PartitionSector->Partition[i].StartingHead,
814 PartitionSector->Partition[i].StartingSector & 0x3f,
815 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
816 PartitionSector->Partition[i].StartingCylinder,
817 PartitionSector->Partition[i].EndingHead,
818 PartitionSector->Partition[i].EndingSector & 0x3f,
819 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
820 PartitionSector->Partition[i].EndingCylinder,
821 PartitionSector->Partition[i].StartingBlock,
822 PartitionSector->Partition[i].SectorCount);
826 if (PartitionOffset == 0ULL)
828 LayoutBuffer->Signature = PartitionSector->Signature;
829 DPRINT("Disk signature: %lx\n", LayoutBuffer->Signature);
832 ExtendedFound = FALSE;
834 for (i = 0; i < PARTITION_TBL_SIZE; i++)
836 if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
838 ExtendedFound = TRUE;
839 if ((ULONGLONG) containerOffset == (ULONGLONG) 0)
841 containerOffset = PartitionOffset;
843 nextPartitionOffset = (ULONGLONG) containerOffset +
844 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
845 (ULONGLONG) SectorSize;
848 if ((ReturnRecognizedPartitions == FALSE) ||
849 ((ReturnRecognizedPartitions == TRUE) &&
850 IsRecognizedPartition(PartitionSector->Partition[i].PartitionType)))
852 /* handle normal partition */
853 DPRINT("Partition %u: Normal Partition\n", i);
854 Count = LayoutBuffer->PartitionCount;
855 DPRINT("Logical Partition %u\n", Count);
857 if (PartitionSector->Partition[i].StartingBlock == 0)
859 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
861 else if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
863 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
864 (ULONGLONG) containerOffset +
865 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
866 (ULONGLONG) SectorSize;
870 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
871 (ULONGLONG)PartitionOffset +
872 ((ULONGLONG)PartitionSector->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
874 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
875 (ULONGLONG)PartitionSector->Partition[i].SectorCount * (ULONGLONG)SectorSize;
876 LayoutBuffer->PartitionEntry[Count].HiddenSectors =
877 PartitionSector->Partition[i].StartingBlock;
879 if (IsRecognizedPartition(PartitionSector->Partition[i].PartitionType))
881 LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number;
886 LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0;
889 LayoutBuffer->PartitionEntry[Count].PartitionType =
890 PartitionSector->Partition[i].PartitionType;
891 LayoutBuffer->PartitionEntry[Count].BootIndicator =
892 (PartitionSector->Partition[i].BootFlags & 0x80)?TRUE:FALSE;
893 LayoutBuffer->PartitionEntry[Count].RecognizedPartition =
894 IsRecognizedPartition (PartitionSector->Partition[i].PartitionType);
895 LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE;
897 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
899 LayoutBuffer->PartitionEntry[Count].PartitionNumber,
900 LayoutBuffer->PartitionEntry[Count].BootIndicator,
901 LayoutBuffer->PartitionEntry[Count].PartitionType,
902 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart,
903 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart);
905 LayoutBuffer->PartitionCount++;
909 PartitionOffset = nextPartitionOffset;
911 while (ExtendedFound == TRUE);
913 *PartitionBuffer = LayoutBuffer;
914 ExFreePool(PartitionSector);
916 return(STATUS_SUCCESS);
921 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
923 IN ULONG PartitionNumber,
924 IN ULONG PartitionType)
926 PPARTITION_SECTOR PartitionSector;
927 LARGE_INTEGER RealPartitionOffset;
928 ULONGLONG PartitionOffset;
929 ULONGLONG nextPartitionOffset;
930 ULONGLONG containerOffset;
934 BOOLEAN ExtendedFound = FALSE;
935 DISK_MANAGER DiskManager = NoDiskManager;
937 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
943 /* Check sector size */
944 if (SectorSize < 512)
946 if (SectorSize > 4096)
949 /* Check for 'Ontrack Disk Manager' */
950 xHalExamineMBR (DeviceObject,
953 (PVOID*) &PartitionSector);
954 if (PartitionSector != NULL)
956 DPRINT ("Found 'Ontrack Disk Manager'\n");
957 DiskManager = OntrackDiskManager;
958 ExFreePool (PartitionSector);
961 /* Check for 'EZ-Drive' */
962 xHalExamineMBR (DeviceObject,
965 (PVOID*) &PartitionSector);
966 if (PartitionSector != NULL)
968 DPRINT ("Found 'EZ-Drive'\n");
969 DiskManager = EZ_Drive;
970 ExFreePool (PartitionSector);
973 /* Allocate partition sector */
974 PartitionSector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
976 if (PartitionSector == NULL)
978 return STATUS_INSUFFICIENT_RESOURCES;
981 PartitionOffset = 0ULL;
982 containerOffset = 0ULL;
986 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
988 /* Handle disk managers */
989 if (DiskManager == OntrackDiskManager)
991 /* Shift offset by 63 sectors */
992 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
994 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
996 /* Use sector 1 instead of sector 0 */
997 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1001 RealPartitionOffset.QuadPart = PartitionOffset;
1004 DPRINT ("RealPartitionOffset: %I64u\n",
1005 RealPartitionOffset.QuadPart / SectorSize);
1007 Status = xHalpReadSector (DeviceObject,
1009 &RealPartitionOffset,
1011 if (!NT_SUCCESS (Status))
1013 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1015 ExFreePool (PartitionSector);
1019 /* Check the boot sector id */
1020 DPRINT("Magic %x\n", PartitionSector->Magic);
1021 if (PartitionSector->Magic != PARTITION_MAGIC)
1023 DPRINT ("Invalid partition sector magic\n");
1024 ExFreePool (PartitionSector);
1025 return STATUS_UNSUCCESSFUL;
1029 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1031 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1033 PartitionSector->Partition[i].BootFlags,
1034 PartitionSector->Partition[i].PartitionType,
1035 PartitionSector->Partition[i].StartingHead,
1036 PartitionSector->Partition[i].StartingSector & 0x3f,
1037 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1038 PartitionSector->Partition[i].StartingCylinder,
1039 PartitionSector->Partition[i].EndingHead,
1040 PartitionSector->Partition[i].EndingSector & 0x3f,
1041 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1042 PartitionSector->Partition[i].EndingCylinder,
1043 PartitionSector->Partition[i].StartingBlock,
1044 PartitionSector->Partition[i].SectorCount);
1048 ExtendedFound = FALSE;
1049 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1051 if (IsContainerPartition (PartitionSector->Partition[i].PartitionType))
1053 ExtendedFound = TRUE;
1054 if (containerOffset == 0ULL)
1056 containerOffset = PartitionOffset;
1058 nextPartitionOffset = containerOffset +
1059 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1060 (ULONGLONG) SectorSize;
1063 /* Handle recognized partition */
1064 if (IsRecognizedPartition (PartitionSector->Partition[i].PartitionType))
1066 if (Number == PartitionNumber)
1068 /* Set partition type */
1069 PartitionSector->Partition[i].PartitionType = PartitionType;
1071 /* Write partition sector */
1072 Status = xHalpWriteSector (DeviceObject,
1074 &RealPartitionOffset,
1076 if (!NT_SUCCESS(Status))
1078 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1081 ExFreePool (PartitionSector);
1088 PartitionOffset = nextPartitionOffset;
1090 while (ExtendedFound == TRUE);
1092 ExFreePool(PartitionSector);
1094 return STATUS_UNSUCCESSFUL;
1099 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
1100 IN ULONG SectorSize,
1101 IN ULONG SectorsPerTrack,
1102 IN ULONG NumberOfHeads,
1103 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
1105 PPARTITION_SECTOR PartitionSector;
1106 LARGE_INTEGER RealPartitionOffset;
1107 ULONGLONG PartitionOffset;
1108 ULONGLONG NextPartitionOffset;
1109 ULONGLONG ContainerOffset;
1110 BOOLEAN ContainerEntry;
1111 DISK_MANAGER DiskManager;
1116 ULONG StartCylinder;
1126 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1133 assert(DeviceObject);
1134 assert(PartitionBuffer);
1136 DiskManager = NoDiskManager;
1138 /* Check sector size */
1139 if (SectorSize < 512)
1141 if (SectorSize > 4096)
1144 /* Check for 'Ontrack Disk Manager' */
1145 xHalExamineMBR (DeviceObject,
1148 (PVOID *) &PartitionSector);
1149 if (PartitionSector != NULL)
1151 DPRINT ("Found 'Ontrack Disk Manager'\n");
1152 DiskManager = OntrackDiskManager;
1153 ExFreePool (PartitionSector);
1156 /* Check for 'EZ-Drive' */
1157 xHalExamineMBR (DeviceObject,
1160 (PVOID *) &PartitionSector);
1161 if (PartitionSector != NULL)
1163 DPRINT ("Found 'EZ-Drive'\n");
1164 DiskManager = EZ_Drive;
1165 ExFreePool (PartitionSector);
1168 /* Allocate partition sector */
1169 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1171 if (PartitionSector == NULL)
1173 return STATUS_INSUFFICIENT_RESOURCES;
1176 Status = STATUS_SUCCESS;
1177 PartitionOffset = 0ULL;
1178 ContainerOffset = 0ULL;
1179 for (i = 0; i < PartitionBuffer->PartitionCount; i += 4)
1181 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset);
1182 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset);
1184 /* Handle disk managers */
1185 if (DiskManager == OntrackDiskManager)
1187 /* Shift offset by 63 sectors */
1188 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1190 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1192 /* Use sector 1 instead of sector 0 */
1193 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1197 RealPartitionOffset.QuadPart = PartitionOffset;
1200 /* Write modified partition tables */
1201 if (PartitionBuffer->PartitionEntry[i].RewritePartition == TRUE ||
1202 PartitionBuffer->PartitionEntry[i + 1].RewritePartition == TRUE ||
1203 PartitionBuffer->PartitionEntry[i + 2].RewritePartition == TRUE ||
1204 PartitionBuffer->PartitionEntry[i + 3].RewritePartition == TRUE)
1206 /* Read partition sector */
1207 Status = xHalpReadSector (DeviceObject,
1209 &RealPartitionOffset,
1211 if (!NT_SUCCESS(Status))
1213 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status);
1217 /* Initialize a new partition sector */
1218 if (PartitionSector->Magic != PARTITION_MAGIC)
1220 /* Create empty partition sector */
1221 RtlZeroMemory (PartitionSector,
1223 PartitionSector->Magic = PARTITION_MAGIC;
1226 /* Update partition sector entries */
1227 for (j = 0; j < 4; j++)
1229 if (PartitionBuffer->PartitionEntry[i + j].RewritePartition == TRUE)
1231 /* Set partition boot flag */
1232 if (PartitionBuffer->PartitionEntry[i + j].BootIndicator)
1234 PartitionSector->Partition[j].BootFlags |= 0x80;
1238 PartitionSector->Partition[j].BootFlags &= ~0x80;
1241 /* Set partition type */
1242 PartitionSector->Partition[j].PartitionType =
1243 PartitionBuffer->PartitionEntry[i + j].PartitionType;
1245 /* Set partition data */
1246 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0ULL &&
1247 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0ULL)
1249 PartitionSector->Partition[j].StartingBlock = 0;
1250 PartitionSector->Partition[j].SectorCount = 0;
1251 PartitionSector->Partition[j].StartingCylinder = 0;
1252 PartitionSector->Partition[j].StartingHead = 0;
1253 PartitionSector->Partition[j].StartingSector = 0;
1254 PartitionSector->Partition[j].EndingCylinder = 0;
1255 PartitionSector->Partition[j].EndingHead = 0;
1256 PartitionSector->Partition[j].EndingSector = 0;
1262 * x = LBA DIV SectorsPerTrack
1263 * cylinder = (x DIV NumberOfHeads) % 1024
1264 * head = x MOD NumberOfHeads
1265 * sector = (LBA MOD SectorsPerTrack) + 1
1268 /* Compute starting CHS values */
1269 lba = (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart) / SectorSize;
1270 x = lba / SectorsPerTrack;
1271 StartCylinder = (x / NumberOfHeads) %1024;
1272 StartHead = x % NumberOfHeads;
1273 StartSector = (lba % SectorsPerTrack) + 1;
1274 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1275 lba, StartCylinder, StartHead, StartSector);
1277 /* Compute ending CHS values */
1278 lba = (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart +
1279 (PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart - 1)) / SectorSize;
1280 x = lba / SectorsPerTrack;
1281 EndCylinder = (x / NumberOfHeads) % 1024;
1282 EndHead = x % NumberOfHeads;
1283 EndSector = (lba % SectorsPerTrack) + 1;
1284 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1285 lba, EndCylinder, EndHead, EndSector);
1287 /* Set starting CHS values */
1288 PartitionSector->Partition[j].StartingCylinder = StartCylinder & 0xff;
1289 PartitionSector->Partition[j].StartingHead = StartHead;
1290 PartitionSector->Partition[j].StartingSector =
1291 ((StartCylinder & 0x0300) >> 2) + (StartSector & 0x3f);
1293 /* Set ending CHS values */
1294 PartitionSector->Partition[j].EndingCylinder = EndCylinder & 0xff;
1295 PartitionSector->Partition[j].EndingHead = EndHead;
1296 PartitionSector->Partition[j].EndingSector =
1297 ((EndCylinder & 0x0300) >> 2) + (EndSector & 0x3f);
1299 /* Calculate start sector and sector count */
1301 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - ContainerOffset) / SectorSize;
1303 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart / SectorSize;
1304 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1305 StartBlock, SectorCount);
1307 /* Set start sector and sector count */
1308 PartitionSector->Partition[j].StartingBlock = StartBlock;
1309 PartitionSector->Partition[j].SectorCount = SectorCount;
1314 /* Write partition sector */
1315 Status = xHalpWriteSector (DeviceObject,
1317 &RealPartitionOffset,
1319 if (!NT_SUCCESS(Status))
1321 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1326 ContainerEntry = FALSE;
1327 for (j = 0; j < 4; j++)
1329 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1331 ContainerEntry = TRUE;
1332 NextPartitionOffset =
1333 PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart;
1335 if (ContainerOffset == 0ULL)
1337 ContainerOffset = NextPartitionOffset;
1342 if (ContainerEntry == FALSE)
1344 DPRINT ("No container entry in partition sector!\n");
1348 PartitionOffset = NextPartitionOffset;
1351 ExFreePool (PartitionSector);