2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/disk.c
5 * PURPOSE: I/O Support for Hal Disk (Partition Table/MBR) Routines.
7 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* LOCAL MACROS and TYPES ***************************************************/
19 #define AUTO_DRIVE ((ULONG)-1)
21 #define PARTITION_MAGIC 0xaa55
23 #define PARTITION_TBL_SIZE 4
27 typedef struct _PARTITION
29 unsigned char BootFlags
; /* bootable? 0=no, 128=yes */
30 unsigned char StartingHead
; /* beginning head number */
31 unsigned char StartingSector
; /* beginning sector number */
32 unsigned char StartingCylinder
; /* 10 bit nmbr, with high 2 bits put in begsect */
33 unsigned char PartitionType
; /* Operating System type indicator code */
34 unsigned char EndingHead
; /* ending head number */
35 unsigned char EndingSector
; /* ending sector number */
36 unsigned char EndingCylinder
; /* also a 10 bit nmbr, with same high 2 bit trick */
37 unsigned int StartingBlock
; /* first sector relative to start of disk */
38 unsigned int SectorCount
; /* number of sectors in partition */
39 } PARTITION
, *PPARTITION
;
42 typedef struct _PARTITION_SECTOR
44 UCHAR BootCode
[440]; /* 0x000 */
45 ULONG Signature
; /* 0x1B8 */
46 UCHAR Reserved
[2]; /* 0x1BC */
47 PARTITION Partition
[PARTITION_TBL_SIZE
]; /* 0x1BE */
48 USHORT Magic
; /* 0x1FE */
49 } PARTITION_SECTOR
, *PPARTITION_SECTOR
;
54 typedef enum _DISK_MANAGER
61 HAL_DISPATCH EXPORTED HalDispatchTable
=
64 (pHalQuerySystemInformation
) NULL
, // HalQuerySystemInformation
65 (pHalSetSystemInformation
) NULL
, // HalSetSystemInformation
66 (pHalQueryBusSlots
) NULL
, // HalQueryBusSlots
68 (pHalExamineMBR
) HalExamineMBR
,
69 (pHalIoAssignDriveLetters
) xHalIoAssignDriveLetters
,
70 (pHalIoReadPartitionTable
) xHalIoReadPartitionTable
,
71 (pHalIoSetPartitionInformation
) xHalIoSetPartitionInformation
,
72 (pHalIoWritePartitionTable
) xHalIoWritePartitionTable
,
73 (pHalHandlerForBus
) NULL
, // HalReferenceHandlerForBus
74 (pHalReferenceBusHandler
) NULL
, // HalReferenceBusHandler
75 (pHalReferenceBusHandler
) NULL
, // HalDereferenceBusHandler
76 (pHalInitPnpDriver
) NULL
, //HalInitPnpDriver;
77 (pHalInitPowerManagement
) NULL
, //HalInitPowerManagement;
78 (pHalGetDmaAdapter
) NULL
, //HalGetDmaAdapter;
79 (pHalGetInterruptTranslator
) NULL
, //HalGetInterruptTranslator;
80 (pHalStartMirroring
) NULL
, //HalStartMirroring;
81 (pHalEndMirroring
) NULL
, //HalEndMirroring;
82 (pHalMirrorPhysicalMemory
) NULL
, //HalMirrorPhysicalMemory;
83 (pHalEndOfBoot
) NULL
, //HalEndOfBoot;
84 (pHalMirrorVerify
) NULL
//HalMirrorVerify;
87 HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable
=
89 HAL_PRIVATE_DISPATCH_VERSION
92 /* FUNCTIONS *****************************************************************/
96 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
97 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
99 IO_STATUS_BLOCK StatusBlock
;
100 DISK_GEOMETRY DiskGeometry
;
101 PDEVICE_OBJECT DeviceObject
= NULL
;
102 PFILE_OBJECT FileObject
;
107 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
111 /* Get the drives sector size */
112 Status
= IoGetDeviceObjectPointer(DeviceName
,
116 if (!NT_SUCCESS(Status
))
118 DPRINT("Status %x\n", Status
);
122 KeInitializeEvent(&Event
,
126 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
131 sizeof(DISK_GEOMETRY
),
137 ObDereferenceObject(FileObject
);
138 return(STATUS_INSUFFICIENT_RESOURCES
);
141 Status
= IoCallDriver(DeviceObject
,
143 if (Status
== STATUS_PENDING
)
145 KeWaitForSingleObject(&Event
,
150 Status
= StatusBlock
.Status
;
152 if (!NT_SUCCESS(Status
))
154 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
156 DiskGeometry
.BytesPerSector
= 512;
160 ObDereferenceObject(FileObject
);
165 DPRINT("DiskGeometry.BytesPerSector: %d\n",
166 DiskGeometry
.BytesPerSector
);
168 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
170 PDRIVE_LAYOUT_INFORMATION Buffer
;
172 /* Allocate a partition list for a single entry. */
173 Buffer
= ExAllocatePool(NonPagedPool
,
174 sizeof(DRIVE_LAYOUT_INFORMATION
));
177 RtlZeroMemory(Buffer
,
178 sizeof(DRIVE_LAYOUT_INFORMATION
));
179 Buffer
->PartitionCount
= 1;
180 *LayoutInfo
= Buffer
;
182 Status
= STATUS_SUCCESS
;
186 Status
= STATUS_UNSUCCESSFUL
;
191 /* Read the partition table */
192 Status
= IoReadPartitionTable(DeviceObject
,
193 DiskGeometry
.BytesPerSector
,
198 ObDereferenceObject(FileObject
);
205 xHalpReadSector (IN PDEVICE_OBJECT DeviceObject
,
207 IN PLARGE_INTEGER SectorOffset
,
210 IO_STATUS_BLOCK StatusBlock
;
215 DPRINT("xHalpReadSector() called\n");
217 ASSERT(DeviceObject
);
220 KeInitializeEvent(&Event
,
224 /* Read the sector */
225 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
233 Status
= IoCallDriver(DeviceObject
,
235 if (Status
== STATUS_PENDING
)
237 KeWaitForSingleObject(&Event
,
242 Status
= StatusBlock
.Status
;
245 if (!NT_SUCCESS(Status
))
247 DPRINT("Reading sector failed (Status 0x%08lx)\n",
257 xHalpWriteSector (IN PDEVICE_OBJECT DeviceObject
,
259 IN PLARGE_INTEGER SectorOffset
,
262 IO_STATUS_BLOCK StatusBlock
;
267 DPRINT("xHalpWriteSector() called\n");
269 KeInitializeEvent(&Event
,
273 /* Write the sector */
274 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
282 Status
= IoCallDriver(DeviceObject
,
284 if (Status
== STATUS_PENDING
)
286 KeWaitForSingleObject(&Event
,
291 Status
= StatusBlock
.Status
;
294 if (!NT_SUCCESS(Status
))
296 DPRINT("Writing sector failed (Status 0x%08lx)\n",
305 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
307 IN ULONG MBRTypeIdentifier
,
310 LARGE_INTEGER SectorOffset
;
311 PPARTITION_SECTOR Sector
;
314 DPRINT("HalExamineMBR()\n");
318 if (SectorSize
< 512)
320 if (SectorSize
> 4096)
323 Sector
= (PPARTITION_SECTOR
) ExAllocatePool (PagedPool
,
327 DPRINT ("Partition sector allocation failed\n");
331 #if defined(__GNUC__)
332 SectorOffset
.QuadPart
= 0LL;
334 SectorOffset
.QuadPart
= 0;
336 Status
= xHalpReadSector (DeviceObject
,
340 if (!NT_SUCCESS(Status
))
342 DPRINT("xHalpReadSector() failed (Status %lx)\n", Status
);
347 if (Sector
->Magic
!= PARTITION_MAGIC
)
349 DPRINT("Invalid MBR magic value\n");
354 if (Sector
->Partition
[0].PartitionType
!= MBRTypeIdentifier
)
356 DPRINT("Invalid MBRTypeIdentifier\n");
361 if (Sector
->Partition
[0].PartitionType
== 0x54)
363 /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
364 DPRINT("Found 'Ontrack Disk Manager'!\n");
365 *((PULONG
)Sector
) = 63;
368 *Buffer
= (PVOID
)Sector
;
373 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
374 IN ULONG DriveNumber
,
377 WCHAR DriveNameBuffer
[8];
378 UNICODE_STRING DriveName
;
381 DPRINT("HalpAssignDrive()\n");
383 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
385 /* Force assignment */
386 if ((ObSystemDeviceMap
->DriveMap
& (1 << DriveNumber
)) != 0)
388 DbgPrint("Drive letter already used!\n");
394 /* Automatic assignment */
395 DriveNumber
= AUTO_DRIVE
;
397 for (i
= 2; i
< 24; i
++)
399 if ((ObSystemDeviceMap
->DriveMap
& (1 << i
)) == 0)
406 if (DriveNumber
== AUTO_DRIVE
)
408 DbgPrint("No drive letter available!\n");
413 DPRINT("DriveNumber %d\n", DriveNumber
);
415 /* Update the System Device Map */
416 ObSystemDeviceMap
->DriveMap
|= (1 << DriveNumber
);
417 ObSystemDeviceMap
->DriveType
[DriveNumber
] = DriveType
;
419 /* Build drive name */
420 swprintf(DriveNameBuffer
,
423 RtlInitUnicodeString(&DriveName
,
426 DPRINT(" %wZ ==> %wZ\n",
430 /* Create symbolic link */
431 IoCreateSymbolicLink(&DriveName
,
437 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
438 IN PSTRING NtDeviceName
,
439 OUT PUCHAR NtSystemPath
,
440 OUT PSTRING NtSystemPathString
)
442 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
443 PCONFIGURATION_INFORMATION ConfigInfo
;
444 OBJECT_ATTRIBUTES ObjectAttributes
;
445 IO_STATUS_BLOCK StatusBlock
;
446 UNICODE_STRING UnicodeString1
;
447 UNICODE_STRING UnicodeString2
;
455 DPRINT("xHalIoAssignDriveLetters()\n");
457 ConfigInfo
= IoGetConfigurationInformation();
459 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
461 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
464 /* Create PhysicalDrive links */
465 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
466 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
469 L
"\\Device\\Harddisk%d\\Partition0",
471 RtlInitUnicodeString(&UnicodeString1
,
474 InitializeObjectAttributes(&ObjectAttributes
,
480 Status
= ZwOpenFile(&FileHandle
,
485 FILE_SYNCHRONOUS_IO_NONALERT
);
486 if (NT_SUCCESS(Status
))
491 L
"\\??\\PhysicalDrive%d",
493 RtlInitUnicodeString(&UnicodeString2
,
496 DPRINT("Creating link: %S ==> %S\n",
500 IoCreateSymbolicLink(&UnicodeString2
,
505 /* Initialize layout array */
506 LayoutArray
= ExAllocatePool(NonPagedPool
,
507 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
508 RtlZeroMemory(LayoutArray
,
509 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
510 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
513 L
"\\Device\\Harddisk%d\\Partition0",
515 RtlInitUnicodeString(&UnicodeString1
,
518 Status
= xHalQueryDriveLayout(&UnicodeString1
,
520 if (!NT_SUCCESS(Status
))
522 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
524 LayoutArray
[i
] = NULL
;
530 /* Dump layout array */
531 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
533 DPRINT("Harddisk %d:\n",
536 if (LayoutArray
[i
] == NULL
)
539 DPRINT("Logical partitions: %d\n",
540 LayoutArray
[i
]->PartitionCount
);
542 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
544 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
546 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
547 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
548 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
549 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
550 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
555 /* Assign pre-assigned (registry) partitions */
558 /* Assign bootable partition on first harddisk */
559 DPRINT("Assigning bootable primary partition on first harddisk:\n");
560 if (ConfigInfo
->DiskCount
> 0)
564 /* Search for bootable partition */
565 for (j
= 0; j
< LayoutArray
[0]->PartitionCount
; j
++)
567 if ((LayoutArray
[0]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
568 IsRecognizedPartition(LayoutArray
[0]->PartitionEntry
[j
].PartitionType
))
571 L
"\\Device\\Harddisk0\\Partition%d",
572 LayoutArray
[0]->PartitionEntry
[j
].PartitionNumber
);
573 RtlInitUnicodeString(&UnicodeString2
,
577 DPRINT(" %wZ\n", &UnicodeString2
);
578 HalpAssignDrive(&UnicodeString2
,
580 DOSDEVICE_DRIVE_FIXED
);
586 /* Assign remaining primary partitions */
587 DPRINT("Assigning remaining primary partitions:\n");
588 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
592 /* Search for primary partitions */
593 for (j
= 0; (j
< PARTITION_TBL_SIZE
) && (j
< LayoutArray
[i
]->PartitionCount
); j
++)
595 if ((i
== 0) && (LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== TRUE
))
598 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
601 L
"\\Device\\Harddisk%d\\Partition%d",
603 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
604 RtlInitUnicodeString(&UnicodeString2
,
610 HalpAssignDrive(&UnicodeString2
,
612 DOSDEVICE_DRIVE_FIXED
);
618 /* Assign extended (logical) partitions */
619 DPRINT("Assigning extended (logical) partitions:\n");
620 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
624 /* Search for extended partitions */
625 for (j
= PARTITION_TBL_SIZE
; j
< LayoutArray
[i
]->PartitionCount
; j
++)
627 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
628 (LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
!= 0))
631 L
"\\Device\\Harddisk%d\\Partition%d",
633 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
634 RtlInitUnicodeString(&UnicodeString2
,
640 HalpAssignDrive(&UnicodeString2
,
642 DOSDEVICE_DRIVE_FIXED
);
648 /* Assign removable disk drives */
649 DPRINT("Assigning removable disk drives:\n");
650 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
654 /* Search for virtual partitions */
655 if (LayoutArray
[i
]->PartitionCount
== 1 &&
656 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
659 L
"\\Device\\Harddisk%d\\Partition1",
661 RtlInitUnicodeString(&UnicodeString2
,
667 HalpAssignDrive(&UnicodeString2
,
669 DOSDEVICE_DRIVE_REMOVABLE
);
674 /* Free layout array */
675 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
677 if (LayoutArray
[i
] != NULL
)
678 ExFreePool(LayoutArray
[i
]);
680 ExFreePool(LayoutArray
);
682 /* Assign floppy drives */
683 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
684 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
687 L
"\\Device\\Floppy%d",
689 RtlInitUnicodeString(&UnicodeString1
,
692 /* Assign drive letters A: or B: or first free drive letter */
695 HalpAssignDrive(&UnicodeString1
,
696 (i
< 2) ? i
: AUTO_DRIVE
,
697 DOSDEVICE_DRIVE_REMOVABLE
);
700 /* Assign cdrom drives */
701 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CdRomCount
);
702 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
705 L
"\\Device\\CdRom%d",
707 RtlInitUnicodeString(&UnicodeString1
,
710 /* Assign first free drive letter */
711 DPRINT(" %wZ\n", &UnicodeString1
);
712 HalpAssignDrive(&UnicodeString1
,
714 DOSDEVICE_DRIVE_CDROM
);
717 /* Anything else to do? */
725 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
727 BOOLEAN ReturnRecognizedPartitions
,
728 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
730 LARGE_INTEGER RealPartitionOffset
;
731 ULONGLONG PartitionOffset
;
732 #if defined(__GNUC__)
733 ULONGLONG nextPartitionOffset
= 0LL;
735 ULONGLONG nextPartitionOffset
= 0;
737 ULONGLONG containerOffset
;
739 PPARTITION_SECTOR PartitionSector
;
740 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
744 BOOLEAN ExtendedFound
= FALSE
;
746 DISK_MANAGER DiskManager
= NoDiskManager
;
748 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
751 ReturnRecognizedPartitions
,
754 *PartitionBuffer
= NULL
;
756 /* Check sector size */
757 if (SectorSize
< 512)
759 if (SectorSize
> 4096)
762 /* Check for 'Ontrack Disk Manager' */
763 HalExamineMBR(DeviceObject
,
767 if (MbrBuffer
!= NULL
)
769 DPRINT("Found 'Ontrack Disk Manager'\n");
770 DiskManager
= OntrackDiskManager
;
771 ExFreePool(MbrBuffer
);
774 /* Check for 'EZ-Drive' */
775 HalExamineMBR(DeviceObject
,
779 if (MbrBuffer
!= NULL
)
781 DPRINT("Found 'EZ-Drive'\n");
782 DiskManager
= EZ_Drive
;
783 ExFreePool(MbrBuffer
);
786 PartitionSector
= (PPARTITION_SECTOR
)ExAllocatePool(PagedPool
,
788 if (PartitionSector
== NULL
)
790 return(STATUS_INSUFFICIENT_RESOURCES
);
793 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
795 if (LayoutBuffer
== NULL
)
797 ExFreePool(PartitionSector
);
798 return(STATUS_INSUFFICIENT_RESOURCES
);
801 RtlZeroMemory(LayoutBuffer
,
804 #if defined(__GNUC__)
805 PartitionOffset
= 0ULL;
806 containerOffset
= 0ULL;
814 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
/ SectorSize
);
816 /* Handle disk managers */
817 if (DiskManager
== OntrackDiskManager
)
819 /* Shift offset by 63 sectors */
820 RealPartitionOffset
.QuadPart
= PartitionOffset
+ (ULONGLONG
)(63 * SectorSize
);
822 #if defined(__GNUC__)
823 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0ULL)
825 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0)
828 /* Use sector 1 instead of sector 0 */
829 RealPartitionOffset
.QuadPart
= (ULONGLONG
)SectorSize
;
833 RealPartitionOffset
.QuadPart
= PartitionOffset
;
836 DPRINT ("RealPartitionOffset: %I64u\n",
837 RealPartitionOffset
.QuadPart
/ SectorSize
);
839 Status
= xHalpReadSector (DeviceObject
,
841 &RealPartitionOffset
,
843 if (!NT_SUCCESS(Status
))
845 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
847 ExFreePool (PartitionSector
);
848 ExFreePool (LayoutBuffer
);
852 /* Check the boot sector id */
853 DPRINT("Magic %x\n", PartitionSector
->Magic
);
854 if (PartitionSector
->Magic
!= PARTITION_MAGIC
)
856 DPRINT ("Invalid partition sector magic\n");
857 ExFreePool (PartitionSector
);
858 *PartitionBuffer
= LayoutBuffer
;
859 return STATUS_SUCCESS
;
863 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
865 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
867 PartitionSector
->Partition
[i
].BootFlags
,
868 PartitionSector
->Partition
[i
].PartitionType
,
869 PartitionSector
->Partition
[i
].StartingHead
,
870 PartitionSector
->Partition
[i
].StartingSector
& 0x3f,
871 (((PartitionSector
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
872 PartitionSector
->Partition
[i
].StartingCylinder
,
873 PartitionSector
->Partition
[i
].EndingHead
,
874 PartitionSector
->Partition
[i
].EndingSector
& 0x3f,
875 (((PartitionSector
->Partition
[i
].EndingSector
) & 0xc0) << 2) +
876 PartitionSector
->Partition
[i
].EndingCylinder
,
877 PartitionSector
->Partition
[i
].StartingBlock
,
878 PartitionSector
->Partition
[i
].SectorCount
);
882 #if defined(__GNUC__)
883 if (PartitionOffset
== 0ULL)
885 if (PartitionOffset
== 0)
888 LayoutBuffer
->Signature
= PartitionSector
->Signature
;
889 DPRINT("Disk signature: %lx\n", LayoutBuffer
->Signature
);
892 ExtendedFound
= FALSE
;
894 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
896 if (IsContainerPartition(PartitionSector
->Partition
[i
].PartitionType
))
898 ExtendedFound
= TRUE
;
899 if ((ULONGLONG
) containerOffset
== (ULONGLONG
) 0)
901 containerOffset
= PartitionOffset
;
903 nextPartitionOffset
= (ULONGLONG
) containerOffset
+
904 (ULONGLONG
) PartitionSector
->Partition
[i
].StartingBlock
*
905 (ULONGLONG
) SectorSize
;
908 if ((ReturnRecognizedPartitions
== FALSE
) ||
909 ((ReturnRecognizedPartitions
== TRUE
) &&
910 !IsContainerPartition(PartitionSector
->Partition
[i
].PartitionType
) &&
911 PartitionSector
->Partition
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
))
913 /* handle normal partition */
914 DPRINT("Partition %u: Normal Partition\n", i
);
915 Count
= LayoutBuffer
->PartitionCount
;
916 DPRINT("Logical Partition %u\n", Count
);
918 if (PartitionSector
->Partition
[i
].StartingBlock
== 0)
920 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
922 else if (IsContainerPartition(PartitionSector
->Partition
[i
].PartitionType
))
924 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
925 (ULONGLONG
) containerOffset
+
926 (ULONGLONG
) PartitionSector
->Partition
[i
].StartingBlock
*
927 (ULONGLONG
) SectorSize
;
931 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
932 (ULONGLONG
)PartitionOffset
+
933 ((ULONGLONG
)PartitionSector
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
935 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
936 (ULONGLONG
)PartitionSector
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
937 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
=
938 PartitionSector
->Partition
[i
].StartingBlock
;
940 if (!IsContainerPartition(PartitionSector
->Partition
[i
].PartitionType
) &&
941 PartitionSector
->Partition
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
943 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
= TRUE
;
944 /* WinXP returns garbage as PartitionNumber */
945 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
950 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
= FALSE
;
951 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
954 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
955 PartitionSector
->Partition
[i
].PartitionType
;
956 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
957 (PartitionSector
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
958 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
960 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
962 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
963 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
964 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
965 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
966 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
,
967 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
);
969 LayoutBuffer
->PartitionCount
++;
973 PartitionOffset
= nextPartitionOffset
;
975 while (ExtendedFound
== TRUE
);
977 *PartitionBuffer
= LayoutBuffer
;
978 ExFreePool(PartitionSector
);
980 return(STATUS_SUCCESS
);
985 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
987 IN ULONG PartitionNumber
,
988 IN ULONG PartitionType
)
990 PPARTITION_SECTOR PartitionSector
;
991 LARGE_INTEGER RealPartitionOffset
;
992 ULONGLONG PartitionOffset
;
993 #if defined(__GNUC__)
994 ULONGLONG nextPartitionOffset
= 0LL;
996 ULONGLONG nextPartitionOffset
= 0;
998 ULONGLONG containerOffset
;
1002 BOOLEAN ExtendedFound
= FALSE
;
1003 DISK_MANAGER DiskManager
= NoDiskManager
;
1005 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
1011 /* Check sector size */
1012 if (SectorSize
< 512)
1014 if (SectorSize
> 4096)
1017 /* Check for 'Ontrack Disk Manager' */
1018 HalExamineMBR (DeviceObject
,
1021 (PVOID
*)(PVOID
)&PartitionSector
);
1022 if (PartitionSector
!= NULL
)
1024 DPRINT ("Found 'Ontrack Disk Manager'\n");
1025 DiskManager
= OntrackDiskManager
;
1026 ExFreePool (PartitionSector
);
1029 /* Check for 'EZ-Drive' */
1030 HalExamineMBR (DeviceObject
,
1033 (PVOID
*)(PVOID
)&PartitionSector
);
1034 if (PartitionSector
!= NULL
)
1036 DPRINT ("Found 'EZ-Drive'\n");
1037 DiskManager
= EZ_Drive
;
1038 ExFreePool (PartitionSector
);
1041 /* Allocate partition sector */
1042 PartitionSector
= (PPARTITION_SECTOR
) ExAllocatePool (PagedPool
,
1044 if (PartitionSector
== NULL
)
1046 return STATUS_INSUFFICIENT_RESOURCES
;
1049 #if defined(__GNUC__)
1050 PartitionOffset
= 0ULL;
1051 containerOffset
= 0ULL;
1053 PartitionOffset
= 0;
1054 containerOffset
= 0;
1059 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset
/ SectorSize
);
1061 /* Handle disk managers */
1062 if (DiskManager
== OntrackDiskManager
)
1064 /* Shift offset by 63 sectors */
1065 RealPartitionOffset
.QuadPart
= PartitionOffset
+ (ULONGLONG
)(63 * SectorSize
);
1067 #if defined(__GNUC__)
1068 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0ULL)
1070 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0)
1073 /* Use sector 1 instead of sector 0 */
1074 RealPartitionOffset
.QuadPart
= (ULONGLONG
)SectorSize
;
1078 RealPartitionOffset
.QuadPart
= PartitionOffset
;
1081 DPRINT ("RealPartitionOffset: %I64u\n",
1082 RealPartitionOffset
.QuadPart
/ SectorSize
);
1084 Status
= xHalpReadSector (DeviceObject
,
1086 &RealPartitionOffset
,
1088 if (!NT_SUCCESS (Status
))
1090 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1092 ExFreePool (PartitionSector
);
1096 /* Check the boot sector id */
1097 DPRINT("Magic %x\n", PartitionSector
->Magic
);
1098 if (PartitionSector
->Magic
!= PARTITION_MAGIC
)
1100 DPRINT ("Invalid partition sector magic\n");
1101 ExFreePool (PartitionSector
);
1102 return STATUS_UNSUCCESSFUL
;
1106 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
1108 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1110 PartitionSector
->Partition
[i
].BootFlags
,
1111 PartitionSector
->Partition
[i
].PartitionType
,
1112 PartitionSector
->Partition
[i
].StartingHead
,
1113 PartitionSector
->Partition
[i
].StartingSector
& 0x3f,
1114 (((PartitionSector
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
1115 PartitionSector
->Partition
[i
].StartingCylinder
,
1116 PartitionSector
->Partition
[i
].EndingHead
,
1117 PartitionSector
->Partition
[i
].EndingSector
& 0x3f,
1118 (((PartitionSector
->Partition
[i
].EndingSector
) & 0xc0) << 2) +
1119 PartitionSector
->Partition
[i
].EndingCylinder
,
1120 PartitionSector
->Partition
[i
].StartingBlock
,
1121 PartitionSector
->Partition
[i
].SectorCount
);
1125 ExtendedFound
= FALSE
;
1126 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
1128 if (IsContainerPartition (PartitionSector
->Partition
[i
].PartitionType
))
1130 ExtendedFound
= TRUE
;
1131 #if defined(__GNUC__)
1132 if (containerOffset
== 0ULL)
1134 if (containerOffset
== 0)
1137 containerOffset
= PartitionOffset
;
1139 nextPartitionOffset
= containerOffset
+
1140 (ULONGLONG
) PartitionSector
->Partition
[i
].StartingBlock
*
1141 (ULONGLONG
) SectorSize
;
1144 /* Handle recognized partition */
1145 if (IsRecognizedPartition (PartitionSector
->Partition
[i
].PartitionType
))
1147 if (Number
== PartitionNumber
)
1149 /* Set partition type */
1150 PartitionSector
->Partition
[i
].PartitionType
= PartitionType
;
1152 /* Write partition sector */
1153 Status
= xHalpWriteSector (DeviceObject
,
1155 &RealPartitionOffset
,
1157 if (!NT_SUCCESS(Status
))
1159 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status
);
1162 ExFreePool (PartitionSector
);
1169 PartitionOffset
= nextPartitionOffset
;
1171 while (ExtendedFound
== TRUE
);
1173 ExFreePool(PartitionSector
);
1175 return STATUS_UNSUCCESSFUL
;
1180 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1181 IN ULONG SectorSize
,
1182 IN ULONG SectorsPerTrack
,
1183 IN ULONG NumberOfHeads
,
1184 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1186 PPARTITION_SECTOR PartitionSector
;
1187 LARGE_INTEGER RealPartitionOffset
;
1188 ULONGLONG PartitionOffset
;
1189 #if defined(__GNUC__)
1190 ULONGLONG NextPartitionOffset
= 0LL;
1192 ULONGLONG NextPartitionOffset
= 0;
1194 ULONGLONG ContainerOffset
;
1195 BOOLEAN ContainerEntry
;
1196 DISK_MANAGER DiskManager
;
1201 ULONG StartCylinder
;
1211 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1218 ASSERT(DeviceObject
);
1219 ASSERT(PartitionBuffer
);
1221 DiskManager
= NoDiskManager
;
1223 /* Check sector size */
1224 if (SectorSize
< 512)
1226 if (SectorSize
> 4096)
1229 /* Check for 'Ontrack Disk Manager' */
1230 HalExamineMBR (DeviceObject
,
1233 (PVOID
*)(PVOID
)&PartitionSector
);
1234 if (PartitionSector
!= NULL
)
1236 DPRINT ("Found 'Ontrack Disk Manager'\n");
1237 DiskManager
= OntrackDiskManager
;
1238 ExFreePool (PartitionSector
);
1241 /* Check for 'EZ-Drive' */
1242 HalExamineMBR (DeviceObject
,
1245 (PVOID
*)(PVOID
)&PartitionSector
);
1246 if (PartitionSector
!= NULL
)
1248 DPRINT ("Found 'EZ-Drive'\n");
1249 DiskManager
= EZ_Drive
;
1250 ExFreePool (PartitionSector
);
1253 /* Allocate partition sector */
1254 PartitionSector
= (PPARTITION_SECTOR
)ExAllocatePool(PagedPool
,
1256 if (PartitionSector
== NULL
)
1258 return STATUS_INSUFFICIENT_RESOURCES
;
1261 Status
= STATUS_SUCCESS
;
1262 #if defined(__GNUC__)
1263 PartitionOffset
= 0ULL;
1264 ContainerOffset
= 0ULL;
1266 PartitionOffset
= 0;
1267 ContainerOffset
= 0;
1269 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
+= 4)
1271 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset
);
1272 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset
);
1274 /* Handle disk managers */
1275 if (DiskManager
== OntrackDiskManager
)
1277 /* Shift offset by 63 sectors */
1278 RealPartitionOffset
.QuadPart
= PartitionOffset
+ (ULONGLONG
)(63 * SectorSize
);
1280 #if defined(__GNUC__)
1281 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0ULL)
1283 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0)
1286 /* Use sector 1 instead of sector 0 */
1287 RealPartitionOffset
.QuadPart
= (ULONGLONG
)SectorSize
;
1291 RealPartitionOffset
.QuadPart
= PartitionOffset
;
1294 /* Write modified partition tables */
1295 if (PartitionBuffer
->PartitionEntry
[i
].RewritePartition
== TRUE
||
1296 PartitionBuffer
->PartitionEntry
[i
+ 1].RewritePartition
== TRUE
||
1297 PartitionBuffer
->PartitionEntry
[i
+ 2].RewritePartition
== TRUE
||
1298 PartitionBuffer
->PartitionEntry
[i
+ 3].RewritePartition
== TRUE
)
1300 /* Read partition sector */
1301 Status
= xHalpReadSector (DeviceObject
,
1303 &RealPartitionOffset
,
1305 if (!NT_SUCCESS(Status
))
1307 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status
);
1311 /* Initialize a new partition sector */
1312 if (PartitionSector
->Magic
!= PARTITION_MAGIC
)
1314 /* Create empty partition sector */
1315 RtlZeroMemory (PartitionSector
,
1317 PartitionSector
->Magic
= PARTITION_MAGIC
;
1320 /* Update partition sector entries */
1321 for (j
= 0; j
< 4; j
++)
1323 if (PartitionBuffer
->PartitionEntry
[i
+ j
].RewritePartition
== TRUE
)
1325 /* Set partition boot flag */
1326 if (PartitionBuffer
->PartitionEntry
[i
+ j
].BootIndicator
)
1328 PartitionSector
->Partition
[j
].BootFlags
|= 0x80;
1332 PartitionSector
->Partition
[j
].BootFlags
&= ~0x80;
1335 /* Set partition type */
1336 PartitionSector
->Partition
[j
].PartitionType
=
1337 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
;
1339 /* Set partition data */
1340 #if defined(__GNUC__)
1341 if (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
== 0ULL &&
1342 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
== 0ULL)
1344 if (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
== 0 &&
1345 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
== 0)
1348 PartitionSector
->Partition
[j
].StartingBlock
= 0;
1349 PartitionSector
->Partition
[j
].SectorCount
= 0;
1350 PartitionSector
->Partition
[j
].StartingCylinder
= 0;
1351 PartitionSector
->Partition
[j
].StartingHead
= 0;
1352 PartitionSector
->Partition
[j
].StartingSector
= 0;
1353 PartitionSector
->Partition
[j
].EndingCylinder
= 0;
1354 PartitionSector
->Partition
[j
].EndingHead
= 0;
1355 PartitionSector
->Partition
[j
].EndingSector
= 0;
1361 * x = LBA DIV SectorsPerTrack
1362 * cylinder = (x DIV NumberOfHeads) % 1024
1363 * head = x MOD NumberOfHeads
1364 * sector = (LBA MOD SectorsPerTrack) + 1
1367 /* Compute starting CHS values */
1368 lba
= (ULONG
)((PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
) / SectorSize
);
1369 x
= lba
/ SectorsPerTrack
;
1370 StartCylinder
= (x
/ NumberOfHeads
) %1024;
1371 StartHead
= x
% NumberOfHeads
;
1372 StartSector
= (lba
% SectorsPerTrack
) + 1;
1373 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1374 lba
, StartCylinder
, StartHead
, StartSector
);
1376 /* Compute ending CHS values */
1377 lba
= (ULONG
)((PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
+
1378 (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
- 1)) / SectorSize
);
1379 x
= lba
/ SectorsPerTrack
;
1380 EndCylinder
= (x
/ NumberOfHeads
) % 1024;
1381 EndHead
= x
% NumberOfHeads
;
1382 EndSector
= (lba
% SectorsPerTrack
) + 1;
1383 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1384 lba
, EndCylinder
, EndHead
, EndSector
);
1386 /* Set starting CHS values */
1387 PartitionSector
->Partition
[j
].StartingCylinder
= StartCylinder
& 0xff;
1388 PartitionSector
->Partition
[j
].StartingHead
= StartHead
;
1389 PartitionSector
->Partition
[j
].StartingSector
=
1390 ((StartCylinder
& 0x0300) >> 2) + (StartSector
& 0x3f);
1392 /* Set ending CHS values */
1393 PartitionSector
->Partition
[j
].EndingCylinder
= EndCylinder
& 0xff;
1394 PartitionSector
->Partition
[j
].EndingHead
= EndHead
;
1395 PartitionSector
->Partition
[j
].EndingSector
=
1396 ((EndCylinder
& 0x0300) >> 2) + (EndSector
& 0x3f);
1398 /* Calculate start sector and sector count */
1399 if (IsContainerPartition (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
))
1402 (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
- ContainerOffset
) / SectorSize
;
1407 (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
- NextPartitionOffset
) / SectorSize
;
1410 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
/ SectorSize
;
1411 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1412 StartBlock
, SectorCount
);
1414 /* Set start sector and sector count */
1415 PartitionSector
->Partition
[j
].StartingBlock
= StartBlock
;
1416 PartitionSector
->Partition
[j
].SectorCount
= SectorCount
;
1421 /* Write partition sector */
1422 Status
= xHalpWriteSector (DeviceObject
,
1424 &RealPartitionOffset
,
1426 if (!NT_SUCCESS(Status
))
1428 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status
);
1433 ContainerEntry
= FALSE
;
1434 for (j
= 0; j
< 4; j
++)
1436 if (IsContainerPartition (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
))
1438 ContainerEntry
= TRUE
;
1439 NextPartitionOffset
=
1440 PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
;
1442 #if defined(__GNUC__)
1443 if (ContainerOffset
== 0ULL)
1445 if (ContainerOffset
== 0)
1448 ContainerOffset
= NextPartitionOffset
;
1453 if (ContainerEntry
== FALSE
)
1455 DPRINT ("No container entry in partition sector!\n");
1459 PartitionOffset
= NextPartitionOffset
;
1462 ExFreePool (PartitionSector
);
1472 IoAssignDriveLetters(
1473 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1474 IN PSTRING NtDeviceName,
1475 OUT PUCHAR NtSystemPath,
1476 OUT PSTRING NtSystemPathString
1488 IN PDEVICE_OBJECT DeviceObject
,
1489 IN
struct _CREATE_DISK
* Disk
1493 return STATUS_NOT_IMPLEMENTED
;
1501 IoGetBootDiskInformation(
1502 IN OUT PBOOTDISK_INFORMATION BootDiskInformation
,
1507 return STATUS_NOT_IMPLEMENTED
;
1516 IoReadDiskSignature(
1517 IN PDEVICE_OBJECT DeviceObject
,
1518 IN ULONG BytesPerSector
,
1519 OUT PDISK_SIGNATURE Signature
1523 return STATUS_NOT_IMPLEMENTED
;
1531 IoReadPartitionTableEx(
1532 IN PDEVICE_OBJECT DeviceObject
,
1533 IN
struct _DRIVE_LAYOUT_INFORMATION_EX
** DriveLayout
1537 return STATUS_NOT_IMPLEMENTED
;
1545 IoSetPartitionInformationEx(
1546 IN PDEVICE_OBJECT DeviceObject
,
1547 IN ULONG PartitionNumber
,
1548 IN
struct _SET_PARTITION_INFORMATION_EX
* PartitionInfo
1552 return STATUS_NOT_IMPLEMENTED
;
1560 IoSetSystemPartition(
1561 PUNICODE_STRING VolumeNameString
1565 return STATUS_NOT_IMPLEMENTED
;
1573 IoVerifyPartitionTable(
1574 IN PDEVICE_OBJECT DeviceObject
,
1575 IN BOOLEAN FixErrors
1579 return STATUS_NOT_IMPLEMENTED
;
1587 IoVolumeDeviceToDosName(
1588 IN PVOID VolumeDeviceObject
,
1589 OUT PUNICODE_STRING DosName
1593 return STATUS_NOT_IMPLEMENTED
;
1601 IoWritePartitionTableEx(
1602 IN PDEVICE_OBJECT DeviceObject
,
1603 IN
struct _DRIVE_LAYOUT_INFORMATION_EX
* DriveLayfout
1607 return STATUS_NOT_IMPLEMENTED
;
1614 IoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
1616 BOOLEAN ReturnRecognizedPartitions
,
1617 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1619 return(HalIoReadPartitionTable(DeviceObject
,
1621 ReturnRecognizedPartitions
,
1627 IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject
,
1629 ULONG PartitionNumber
,
1630 ULONG PartitionType
)
1632 return(HalIoSetPartitionInformation(DeviceObject
,
1640 IoWritePartitionTable(PDEVICE_OBJECT DeviceObject
,
1642 ULONG SectorsPerTrack
,
1643 ULONG NumberOfHeads
,
1644 PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1646 return(HalIoWritePartitionTable(DeviceObject
,