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;
88 HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable
=
90 HAL_PRIVATE_DISPATCH_VERSION
93 /* 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 IsRecognizedPartition(PartitionSector
->Partition
[i
].PartitionType
)))
912 /* handle normal partition */
913 DPRINT("Partition %u: Normal Partition\n", i
);
914 Count
= LayoutBuffer
->PartitionCount
;
915 DPRINT("Logical Partition %u\n", Count
);
917 if (PartitionSector
->Partition
[i
].StartingBlock
== 0)
919 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
921 else if (IsContainerPartition(PartitionSector
->Partition
[i
].PartitionType
))
923 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
924 (ULONGLONG
) containerOffset
+
925 (ULONGLONG
) PartitionSector
->Partition
[i
].StartingBlock
*
926 (ULONGLONG
) SectorSize
;
930 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
931 (ULONGLONG
)PartitionOffset
+
932 ((ULONGLONG
)PartitionSector
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
934 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
935 (ULONGLONG
)PartitionSector
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
936 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
=
937 PartitionSector
->Partition
[i
].StartingBlock
;
939 if (IsRecognizedPartition(PartitionSector
->Partition
[i
].PartitionType
))
941 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
946 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
949 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
950 PartitionSector
->Partition
[i
].PartitionType
;
951 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
952 (PartitionSector
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
953 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
954 IsRecognizedPartition (PartitionSector
->Partition
[i
].PartitionType
);
955 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
957 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
959 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
960 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
961 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
962 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
963 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
,
964 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
);
966 LayoutBuffer
->PartitionCount
++;
970 PartitionOffset
= nextPartitionOffset
;
972 while (ExtendedFound
== TRUE
);
974 *PartitionBuffer
= LayoutBuffer
;
975 ExFreePool(PartitionSector
);
977 return(STATUS_SUCCESS
);
982 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
984 IN ULONG PartitionNumber
,
985 IN ULONG PartitionType
)
987 PPARTITION_SECTOR PartitionSector
;
988 LARGE_INTEGER RealPartitionOffset
;
989 ULONGLONG PartitionOffset
;
990 #if defined(__GNUC__)
991 ULONGLONG nextPartitionOffset
= 0LL;
993 ULONGLONG nextPartitionOffset
= 0;
995 ULONGLONG containerOffset
;
999 BOOLEAN ExtendedFound
= FALSE
;
1000 DISK_MANAGER DiskManager
= NoDiskManager
;
1002 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
1008 /* Check sector size */
1009 if (SectorSize
< 512)
1011 if (SectorSize
> 4096)
1014 /* Check for 'Ontrack Disk Manager' */
1015 HalExamineMBR (DeviceObject
,
1018 (PVOID
*)(PVOID
)&PartitionSector
);
1019 if (PartitionSector
!= NULL
)
1021 DPRINT ("Found 'Ontrack Disk Manager'\n");
1022 DiskManager
= OntrackDiskManager
;
1023 ExFreePool (PartitionSector
);
1026 /* Check for 'EZ-Drive' */
1027 HalExamineMBR (DeviceObject
,
1030 (PVOID
*)(PVOID
)&PartitionSector
);
1031 if (PartitionSector
!= NULL
)
1033 DPRINT ("Found 'EZ-Drive'\n");
1034 DiskManager
= EZ_Drive
;
1035 ExFreePool (PartitionSector
);
1038 /* Allocate partition sector */
1039 PartitionSector
= (PPARTITION_SECTOR
) ExAllocatePool (PagedPool
,
1041 if (PartitionSector
== NULL
)
1043 return STATUS_INSUFFICIENT_RESOURCES
;
1046 #if defined(__GNUC__)
1047 PartitionOffset
= 0ULL;
1048 containerOffset
= 0ULL;
1050 PartitionOffset
= 0;
1051 containerOffset
= 0;
1056 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset
/ SectorSize
);
1058 /* Handle disk managers */
1059 if (DiskManager
== OntrackDiskManager
)
1061 /* Shift offset by 63 sectors */
1062 RealPartitionOffset
.QuadPart
= PartitionOffset
+ (ULONGLONG
)(63 * SectorSize
);
1064 #if defined(__GNUC__)
1065 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0ULL)
1067 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0)
1070 /* Use sector 1 instead of sector 0 */
1071 RealPartitionOffset
.QuadPart
= (ULONGLONG
)SectorSize
;
1075 RealPartitionOffset
.QuadPart
= PartitionOffset
;
1078 DPRINT ("RealPartitionOffset: %I64u\n",
1079 RealPartitionOffset
.QuadPart
/ SectorSize
);
1081 Status
= xHalpReadSector (DeviceObject
,
1083 &RealPartitionOffset
,
1085 if (!NT_SUCCESS (Status
))
1087 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1089 ExFreePool (PartitionSector
);
1093 /* Check the boot sector id */
1094 DPRINT("Magic %x\n", PartitionSector
->Magic
);
1095 if (PartitionSector
->Magic
!= PARTITION_MAGIC
)
1097 DPRINT ("Invalid partition sector magic\n");
1098 ExFreePool (PartitionSector
);
1099 return STATUS_UNSUCCESSFUL
;
1103 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
1105 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1107 PartitionSector
->Partition
[i
].BootFlags
,
1108 PartitionSector
->Partition
[i
].PartitionType
,
1109 PartitionSector
->Partition
[i
].StartingHead
,
1110 PartitionSector
->Partition
[i
].StartingSector
& 0x3f,
1111 (((PartitionSector
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
1112 PartitionSector
->Partition
[i
].StartingCylinder
,
1113 PartitionSector
->Partition
[i
].EndingHead
,
1114 PartitionSector
->Partition
[i
].EndingSector
& 0x3f,
1115 (((PartitionSector
->Partition
[i
].EndingSector
) & 0xc0) << 2) +
1116 PartitionSector
->Partition
[i
].EndingCylinder
,
1117 PartitionSector
->Partition
[i
].StartingBlock
,
1118 PartitionSector
->Partition
[i
].SectorCount
);
1122 ExtendedFound
= FALSE
;
1123 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
1125 if (IsContainerPartition (PartitionSector
->Partition
[i
].PartitionType
))
1127 ExtendedFound
= TRUE
;
1128 #if defined(__GNUC__)
1129 if (containerOffset
== 0ULL)
1131 if (containerOffset
== 0)
1134 containerOffset
= PartitionOffset
;
1136 nextPartitionOffset
= containerOffset
+
1137 (ULONGLONG
) PartitionSector
->Partition
[i
].StartingBlock
*
1138 (ULONGLONG
) SectorSize
;
1141 /* Handle recognized partition */
1142 if (IsRecognizedPartition (PartitionSector
->Partition
[i
].PartitionType
))
1144 if (Number
== PartitionNumber
)
1146 /* Set partition type */
1147 PartitionSector
->Partition
[i
].PartitionType
= PartitionType
;
1149 /* Write partition sector */
1150 Status
= xHalpWriteSector (DeviceObject
,
1152 &RealPartitionOffset
,
1154 if (!NT_SUCCESS(Status
))
1156 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status
);
1159 ExFreePool (PartitionSector
);
1166 PartitionOffset
= nextPartitionOffset
;
1168 while (ExtendedFound
== TRUE
);
1170 ExFreePool(PartitionSector
);
1172 return STATUS_UNSUCCESSFUL
;
1177 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1178 IN ULONG SectorSize
,
1179 IN ULONG SectorsPerTrack
,
1180 IN ULONG NumberOfHeads
,
1181 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1183 PPARTITION_SECTOR PartitionSector
;
1184 LARGE_INTEGER RealPartitionOffset
;
1185 ULONGLONG PartitionOffset
;
1186 #if defined(__GNUC__)
1187 ULONGLONG NextPartitionOffset
= 0LL;
1189 ULONGLONG NextPartitionOffset
= 0;
1191 ULONGLONG ContainerOffset
;
1192 BOOLEAN ContainerEntry
;
1193 DISK_MANAGER DiskManager
;
1198 ULONG StartCylinder
;
1208 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1215 ASSERT(DeviceObject
);
1216 ASSERT(PartitionBuffer
);
1218 DiskManager
= NoDiskManager
;
1220 /* Check sector size */
1221 if (SectorSize
< 512)
1223 if (SectorSize
> 4096)
1226 /* Check for 'Ontrack Disk Manager' */
1227 HalExamineMBR (DeviceObject
,
1230 (PVOID
*)(PVOID
)&PartitionSector
);
1231 if (PartitionSector
!= NULL
)
1233 DPRINT ("Found 'Ontrack Disk Manager'\n");
1234 DiskManager
= OntrackDiskManager
;
1235 ExFreePool (PartitionSector
);
1238 /* Check for 'EZ-Drive' */
1239 HalExamineMBR (DeviceObject
,
1242 (PVOID
*)(PVOID
)&PartitionSector
);
1243 if (PartitionSector
!= NULL
)
1245 DPRINT ("Found 'EZ-Drive'\n");
1246 DiskManager
= EZ_Drive
;
1247 ExFreePool (PartitionSector
);
1250 /* Allocate partition sector */
1251 PartitionSector
= (PPARTITION_SECTOR
)ExAllocatePool(PagedPool
,
1253 if (PartitionSector
== NULL
)
1255 return STATUS_INSUFFICIENT_RESOURCES
;
1258 Status
= STATUS_SUCCESS
;
1259 #if defined(__GNUC__)
1260 PartitionOffset
= 0ULL;
1261 ContainerOffset
= 0ULL;
1263 PartitionOffset
= 0;
1264 ContainerOffset
= 0;
1266 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
+= 4)
1268 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset
);
1269 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset
);
1271 /* Handle disk managers */
1272 if (DiskManager
== OntrackDiskManager
)
1274 /* Shift offset by 63 sectors */
1275 RealPartitionOffset
.QuadPart
= PartitionOffset
+ (ULONGLONG
)(63 * SectorSize
);
1277 #if defined(__GNUC__)
1278 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0ULL)
1280 else if (DiskManager
== EZ_Drive
&& PartitionOffset
== 0)
1283 /* Use sector 1 instead of sector 0 */
1284 RealPartitionOffset
.QuadPart
= (ULONGLONG
)SectorSize
;
1288 RealPartitionOffset
.QuadPart
= PartitionOffset
;
1291 /* Write modified partition tables */
1292 if (PartitionBuffer
->PartitionEntry
[i
].RewritePartition
== TRUE
||
1293 PartitionBuffer
->PartitionEntry
[i
+ 1].RewritePartition
== TRUE
||
1294 PartitionBuffer
->PartitionEntry
[i
+ 2].RewritePartition
== TRUE
||
1295 PartitionBuffer
->PartitionEntry
[i
+ 3].RewritePartition
== TRUE
)
1297 /* Read partition sector */
1298 Status
= xHalpReadSector (DeviceObject
,
1300 &RealPartitionOffset
,
1302 if (!NT_SUCCESS(Status
))
1304 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status
);
1308 /* Initialize a new partition sector */
1309 if (PartitionSector
->Magic
!= PARTITION_MAGIC
)
1311 /* Create empty partition sector */
1312 RtlZeroMemory (PartitionSector
,
1314 PartitionSector
->Magic
= PARTITION_MAGIC
;
1317 /* Update partition sector entries */
1318 for (j
= 0; j
< 4; j
++)
1320 if (PartitionBuffer
->PartitionEntry
[i
+ j
].RewritePartition
== TRUE
)
1322 /* Set partition boot flag */
1323 if (PartitionBuffer
->PartitionEntry
[i
+ j
].BootIndicator
)
1325 PartitionSector
->Partition
[j
].BootFlags
|= 0x80;
1329 PartitionSector
->Partition
[j
].BootFlags
&= ~0x80;
1332 /* Set partition type */
1333 PartitionSector
->Partition
[j
].PartitionType
=
1334 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
;
1336 /* Set partition data */
1337 #if defined(__GNUC__)
1338 if (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
== 0ULL &&
1339 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
== 0ULL)
1341 if (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
== 0 &&
1342 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
== 0)
1345 PartitionSector
->Partition
[j
].StartingBlock
= 0;
1346 PartitionSector
->Partition
[j
].SectorCount
= 0;
1347 PartitionSector
->Partition
[j
].StartingCylinder
= 0;
1348 PartitionSector
->Partition
[j
].StartingHead
= 0;
1349 PartitionSector
->Partition
[j
].StartingSector
= 0;
1350 PartitionSector
->Partition
[j
].EndingCylinder
= 0;
1351 PartitionSector
->Partition
[j
].EndingHead
= 0;
1352 PartitionSector
->Partition
[j
].EndingSector
= 0;
1358 * x = LBA DIV SectorsPerTrack
1359 * cylinder = (x DIV NumberOfHeads) % 1024
1360 * head = x MOD NumberOfHeads
1361 * sector = (LBA MOD SectorsPerTrack) + 1
1364 /* Compute starting CHS values */
1365 lba
= (ULONG
)((PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
) / SectorSize
);
1366 x
= lba
/ SectorsPerTrack
;
1367 StartCylinder
= (x
/ NumberOfHeads
) %1024;
1368 StartHead
= x
% NumberOfHeads
;
1369 StartSector
= (lba
% SectorsPerTrack
) + 1;
1370 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1371 lba
, StartCylinder
, StartHead
, StartSector
);
1373 /* Compute ending CHS values */
1374 lba
= (ULONG
)((PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
+
1375 (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
- 1)) / SectorSize
);
1376 x
= lba
/ SectorsPerTrack
;
1377 EndCylinder
= (x
/ NumberOfHeads
) % 1024;
1378 EndHead
= x
% NumberOfHeads
;
1379 EndSector
= (lba
% SectorsPerTrack
) + 1;
1380 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1381 lba
, EndCylinder
, EndHead
, EndSector
);
1383 /* Set starting CHS values */
1384 PartitionSector
->Partition
[j
].StartingCylinder
= StartCylinder
& 0xff;
1385 PartitionSector
->Partition
[j
].StartingHead
= StartHead
;
1386 PartitionSector
->Partition
[j
].StartingSector
=
1387 ((StartCylinder
& 0x0300) >> 2) + (StartSector
& 0x3f);
1389 /* Set ending CHS values */
1390 PartitionSector
->Partition
[j
].EndingCylinder
= EndCylinder
& 0xff;
1391 PartitionSector
->Partition
[j
].EndingHead
= EndHead
;
1392 PartitionSector
->Partition
[j
].EndingSector
=
1393 ((EndCylinder
& 0x0300) >> 2) + (EndSector
& 0x3f);
1395 /* Calculate start sector and sector count */
1396 if (IsContainerPartition (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
))
1399 (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
- ContainerOffset
) / SectorSize
;
1404 (PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
- NextPartitionOffset
) / SectorSize
;
1407 PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionLength
.QuadPart
/ SectorSize
;
1408 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1409 StartBlock
, SectorCount
);
1411 /* Set start sector and sector count */
1412 PartitionSector
->Partition
[j
].StartingBlock
= StartBlock
;
1413 PartitionSector
->Partition
[j
].SectorCount
= SectorCount
;
1418 /* Write partition sector */
1419 Status
= xHalpWriteSector (DeviceObject
,
1421 &RealPartitionOffset
,
1423 if (!NT_SUCCESS(Status
))
1425 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status
);
1430 ContainerEntry
= FALSE
;
1431 for (j
= 0; j
< 4; j
++)
1433 if (IsContainerPartition (PartitionBuffer
->PartitionEntry
[i
+ j
].PartitionType
))
1435 ContainerEntry
= TRUE
;
1436 NextPartitionOffset
=
1437 PartitionBuffer
->PartitionEntry
[i
+ j
].StartingOffset
.QuadPart
;
1439 #if defined(__GNUC__)
1440 if (ContainerOffset
== 0ULL)
1442 if (ContainerOffset
== 0)
1445 ContainerOffset
= NextPartitionOffset
;
1450 if (ContainerEntry
== FALSE
)
1452 DPRINT ("No container entry in partition sector!\n");
1456 PartitionOffset
= NextPartitionOffset
;
1459 ExFreePool (PartitionSector
);
1469 IoAssignDriveLetters(
1470 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1471 IN PSTRING NtDeviceName,
1472 OUT PUCHAR NtSystemPath,
1473 OUT PSTRING NtSystemPathString
1485 IN PDEVICE_OBJECT DeviceObject
,
1486 IN
struct _CREATE_DISK
* Disk
1490 return STATUS_NOT_IMPLEMENTED
;
1498 IoGetBootDiskInformation(
1499 IN OUT PBOOTDISK_INFORMATION BootDiskInformation
,
1504 return STATUS_NOT_IMPLEMENTED
;
1513 IoReadDiskSignature(
1514 IN PDEVICE_OBJECT DeviceObject
,
1515 IN ULONG BytesPerSector
,
1516 OUT PDISK_SIGNATURE Signature
1520 return STATUS_NOT_IMPLEMENTED
;
1528 IoReadPartitionTableEx(
1529 IN PDEVICE_OBJECT DeviceObject
,
1530 IN
struct _DRIVE_LAYOUT_INFORMATION_EX
** DriveLayout
1534 return STATUS_NOT_IMPLEMENTED
;
1542 IoSetPartitionInformationEx(
1543 IN PDEVICE_OBJECT DeviceObject
,
1544 IN ULONG PartitionNumber
,
1545 IN
struct _SET_PARTITION_INFORMATION_EX
* PartitionInfo
1549 return STATUS_NOT_IMPLEMENTED
;
1557 IoSetSystemPartition(
1558 PUNICODE_STRING VolumeNameString
1562 return STATUS_NOT_IMPLEMENTED
;
1570 IoVerifyPartitionTable(
1571 IN PDEVICE_OBJECT DeviceObject
,
1572 IN BOOLEAN FixErrors
1576 return STATUS_NOT_IMPLEMENTED
;
1584 IoVolumeDeviceToDosName(
1585 IN PVOID VolumeDeviceObject
,
1586 OUT PUNICODE_STRING DosName
1590 return STATUS_NOT_IMPLEMENTED
;
1598 IoWritePartitionTableEx(
1599 IN PDEVICE_OBJECT DeviceObject
,
1600 IN
struct _DRIVE_LAYOUT_INFORMATION_EX
* DriveLayfout
1604 return STATUS_NOT_IMPLEMENTED
;
1611 IoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
1613 BOOLEAN ReturnRecognizedPartitions
,
1614 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1616 return(HalIoReadPartitionTable(DeviceObject
,
1618 ReturnRecognizedPartitions
,
1624 IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject
,
1626 ULONG PartitionNumber
,
1627 ULONG PartitionType
)
1629 return(HalIoSetPartitionInformation(DeviceObject
,
1637 IoWritePartitionTable(PDEVICE_OBJECT DeviceObject
,
1639 ULONG SectorsPerTrack
,
1640 ULONG NumberOfHeads
,
1641 PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1643 return(HalIoWritePartitionTable(DeviceObject
,