1 /* $Id: xhaldrv.c,v 1.41 2003/12/14 17:56:22 hbirr Exp $
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
= 0LL;
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
= 0LL;
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
= 0LL;
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
);