1 /* $Id: xhaldrv.c,v 1.24 2002/09/07 15:12:53 chorns 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)
12 /* INCLUDES *****************************************************************/
17 #include <internal/debug.h>
20 /* LOCAL MACROS and TYPES ***************************************************/
22 #define AUTO_DRIVE ((ULONG)-1)
24 #define PARTITION_MAGIC 0xaa55
25 #define PART_MAGIC_OFFSET 0x01fe
26 #define PARTITION_OFFSET 0x01be
27 #define SIGNATURE_OFFSET 0x01b8
28 #define PARTITION_TBL_SIZE 4
31 typedef struct _PARTITION
33 unsigned char BootFlags
;
34 unsigned char StartingHead
;
35 unsigned char StartingSector
;
36 unsigned char StartingCylinder
;
37 unsigned char PartitionType
;
38 unsigned char EndingHead
;
39 unsigned char EndingSector
;
40 unsigned char EndingCylinder
;
41 unsigned int StartingBlock
;
42 unsigned int SectorCount
;
43 } PARTITION
, *PPARTITION
;
45 typedef struct _PARTITION_TABLE
47 PARTITION Partition
[PARTITION_TBL_SIZE
];
49 } PARTITION_TABLE
, *PPARTITION_TABLE
;
51 /* FUNCTIONS *****************************************************************/
54 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
55 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
57 IO_STATUS_BLOCK StatusBlock
;
58 DISK_GEOMETRY DiskGeometry
;
59 PDEVICE_OBJECT DeviceObject
= NULL
;
60 PFILE_OBJECT FileObject
;
65 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
69 /* Get the drives sector size */
70 Status
= IoGetDeviceObjectPointer(DeviceName
,
74 if (!NT_SUCCESS(Status
))
76 DPRINT("Status %x\n",Status
);
80 KeInitializeEvent(&Event
,
84 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
89 sizeof(DISK_GEOMETRY
),
95 ObDereferenceObject(FileObject
);
96 return(STATUS_INSUFFICIENT_RESOURCES
);
99 Status
= IoCallDriver(DeviceObject
,
101 if (Status
== STATUS_PENDING
)
103 KeWaitForSingleObject(&Event
,
108 Status
= StatusBlock
.Status
;
110 if (!NT_SUCCESS(Status
))
112 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
114 DiskGeometry
.BytesPerSector
= 512;
118 ObDereferenceObject(FileObject
);
123 DPRINT("DiskGeometry.BytesPerSector: %d\n",
124 DiskGeometry
.BytesPerSector
);
126 /* read the partition table */
127 Status
= IoReadPartitionTable(DeviceObject
,
128 DiskGeometry
.BytesPerSector
,
132 if ((!NT_SUCCESS(Status
) || (*LayoutInfo
)->PartitionCount
== 0) &&
133 DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
135 PDRIVE_LAYOUT_INFORMATION Buffer
;
137 if (NT_SUCCESS(Status
))
139 ExFreePool(*LayoutInfo
);
142 /* Allocate a partition list for a single entry. */
143 Buffer
= ExAllocatePool(NonPagedPool
,
144 sizeof(DRIVE_LAYOUT_INFORMATION
));
147 RtlZeroMemory(Buffer
,
148 sizeof(DRIVE_LAYOUT_INFORMATION
));
149 Buffer
->PartitionCount
= 1;
150 *LayoutInfo
= Buffer
;
152 Status
= STATUS_SUCCESS
;
156 ObDereferenceObject(FileObject
);
163 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
165 IN ULONG MBRTypeIdentifier
,
169 IO_STATUS_BLOCK StatusBlock
;
170 LARGE_INTEGER Offset
;
175 DPRINT("xHalExamineMBR()\n");
178 if (SectorSize
< 512)
180 if (SectorSize
> 4096)
183 LocalBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
185 if (LocalBuffer
== NULL
)
188 KeInitializeEvent(&Event
,
194 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
202 Status
= IoCallDriver(DeviceObject
,
204 if (Status
== STATUS_PENDING
)
206 KeWaitForSingleObject(&Event
,
211 Status
= StatusBlock
.Status
;
214 if (!NT_SUCCESS(Status
))
216 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
218 ExFreePool(LocalBuffer
);
222 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
224 DPRINT("xHalExamineMBR: invalid MBR signature\n");
225 ExFreePool(LocalBuffer
);
229 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
231 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
232 ExFreePool(LocalBuffer
);
236 *Buffer
= (PVOID
)LocalBuffer
;
241 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
242 IN ULONG DriveNumber
,
245 WCHAR DriveNameBuffer
[8];
246 UNICODE_STRING DriveName
;
249 DPRINT("HalpAssignDrive()\n");
251 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
253 /* Force assignment */
254 if ((SharedUserData
->DosDeviceMap
& (1 << DriveNumber
)) != 0)
256 DbgPrint("Drive letter already used!\n");
262 /* Automatic assignment */
263 DriveNumber
= AUTO_DRIVE
;
265 for (i
= 2; i
< 24; i
++)
267 if ((SharedUserData
->DosDeviceMap
& (1 << i
)) == 0)
274 if (DriveNumber
== AUTO_DRIVE
)
276 DbgPrint("No drive letter available!\n");
281 DPRINT("DriveNumber %d\n", DriveNumber
);
283 /* Update the shared user page */
284 SharedUserData
->DosDeviceMap
|= (1 << DriveNumber
);
285 SharedUserData
->DosDeviceDriveType
[DriveNumber
] = DriveType
;
287 /* Build drive name */
288 swprintf(DriveNameBuffer
,
291 RtlInitUnicodeString(&DriveName
,
294 DPRINT(" %wZ ==> %wZ\n",
298 /* Create symbolic link */
299 IoCreateSymbolicLink(&DriveName
,
305 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
306 IN PSTRING NtDeviceName
,
307 OUT PUCHAR NtSystemPath
,
308 OUT PSTRING NtSystemPathString
)
310 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
311 PCONFIGURATION_INFORMATION ConfigInfo
;
312 OBJECT_ATTRIBUTES ObjectAttributes
;
313 IO_STATUS_BLOCK StatusBlock
;
314 UNICODE_STRING UnicodeString1
;
315 UNICODE_STRING UnicodeString2
;
323 DPRINT("xHalIoAssignDriveLetters()\n");
325 ConfigInfo
= IoGetConfigurationInformation();
327 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
329 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
332 /* Create PhysicalDrive links */
333 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
334 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
337 L
"\\Device\\Harddisk%d\\Partition0",
339 RtlInitUnicodeString(&UnicodeString1
,
342 InitializeObjectAttributes(&ObjectAttributes
,
348 Status
= NtOpenFile(&FileHandle
,
353 FILE_SYNCHRONOUS_IO_NONALERT
);
354 if (NT_SUCCESS(Status
))
359 L
"\\??\\PhysicalDrive%d",
361 RtlInitUnicodeString(&UnicodeString2
,
364 DPRINT("Creating link: %S ==> %S\n",
368 IoCreateSymbolicLink(&UnicodeString2
,
373 /* Initialize layout array */
374 LayoutArray
= ExAllocatePool(NonPagedPool
,
375 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
376 RtlZeroMemory(LayoutArray
,
377 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
378 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
381 L
"\\Device\\Harddisk%d\\Partition0",
383 RtlInitUnicodeString(&UnicodeString1
,
386 Status
= xHalQueryDriveLayout(&UnicodeString1
,
388 if (!NT_SUCCESS(Status
))
390 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
392 LayoutArray
[i
] = NULL
;
398 /* Dump layout array */
399 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
401 DPRINT("Harddisk %d:\n",
404 if (LayoutArray
[i
] == NULL
)
407 DPRINT("Logical partitions: %d\n",
408 LayoutArray
[i
]->PartitionCount
);
410 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
412 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
414 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
415 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
416 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
417 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
418 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
423 /* Assign pre-assigned (registry) partitions */
426 /* Assign bootable partition on first harddisk */
427 DPRINT("Assigning bootable primary partition on first harddisk:\n");
428 if (ConfigInfo
->DiskCount
> 0)
430 /* Search for bootable partition */
431 for (j
= 0; j
< LayoutArray
[0]->PartitionCount
; j
++)
433 if ((LayoutArray
[0]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
434 IsRecognizedPartition(LayoutArray
[0]->PartitionEntry
[j
].PartitionType
))
437 L
"\\Device\\Harddisk0\\Partition%d",
438 LayoutArray
[0]->PartitionEntry
[j
].PartitionNumber
);
439 RtlInitUnicodeString(&UnicodeString2
,
443 DPRINT(" %wZ\n", &UnicodeString2
);
444 HalpAssignDrive(&UnicodeString2
,
446 DOSDEVICE_DRIVE_FIXED
);
451 /* Assign remaining primary partitions */
452 DPRINT("Assigning remaining primary partitions:\n");
453 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
455 /* Search for primary partitions */
456 for (j
= 0; (j
< PARTITION_TBL_SIZE
) && (j
< LayoutArray
[i
]->PartitionCount
); j
++)
458 if ((i
== 0) && (LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== TRUE
))
461 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
464 L
"\\Device\\Harddisk%d\\Partition%d",
466 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
467 RtlInitUnicodeString(&UnicodeString2
,
473 HalpAssignDrive(&UnicodeString2
,
475 DOSDEVICE_DRIVE_FIXED
);
480 /* Assign extended (logical) partitions */
481 DPRINT("Assigning extended (logical) partitions:\n");
482 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
486 /* Search for extended partitions */
487 for (j
= PARTITION_TBL_SIZE
; j
< LayoutArray
[i
]->PartitionCount
; j
++)
489 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
490 (LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
!= 0))
493 L
"\\Device\\Harddisk%d\\Partition%d",
495 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
496 RtlInitUnicodeString(&UnicodeString2
,
502 HalpAssignDrive(&UnicodeString2
,
504 DOSDEVICE_DRIVE_FIXED
);
510 /* Assign removable disk drives */
511 DPRINT("Assigning removable disk drives:\n");
512 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
514 /* Search for virtual partitions */
515 if (LayoutArray
[i
]->PartitionCount
== 1 &&
516 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
519 L
"\\Device\\Harddisk%d\\Partition1",
521 RtlInitUnicodeString(&UnicodeString2
,
527 HalpAssignDrive(&UnicodeString2
,
529 DOSDEVICE_DRIVE_REMOVABLE
);
533 /* Free layout array */
534 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
536 if (LayoutArray
[i
] != NULL
)
537 ExFreePool(LayoutArray
[i
]);
539 ExFreePool(LayoutArray
);
541 /* Assign floppy drives */
542 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
543 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
546 L
"\\Device\\Floppy%d",
548 RtlInitUnicodeString(&UnicodeString1
,
551 /* Assign drive letters A: or B: or first free drive letter */
554 HalpAssignDrive(&UnicodeString1
,
555 (i
< 2) ? i
: AUTO_DRIVE
,
556 DOSDEVICE_DRIVE_REMOVABLE
);
559 /* Assign cdrom drives */
560 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
561 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
564 L
"\\Device\\CdRom%d",
566 RtlInitUnicodeString(&UnicodeString1
,
569 /* Assign first free drive letter */
570 DPRINT(" %wZ\n", &UnicodeString1
);
571 HalpAssignDrive(&UnicodeString1
,
573 DOSDEVICE_DRIVE_CDROM
);
576 /* Anything else ?? */
584 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
586 BOOLEAN ReturnRecognizedPartitions
,
587 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
590 IO_STATUS_BLOCK StatusBlock
;
591 ULARGE_INTEGER PartitionOffset
;
592 ULARGE_INTEGER nextPartitionOffset
;
593 ULARGE_INTEGER containerOffset
;
597 PPARTITION_TABLE PartitionTable
;
598 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
602 BOOLEAN ExtendedFound
= FALSE
;
604 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
607 ReturnRecognizedPartitions
,
610 *PartitionBuffer
= NULL
;
612 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
614 if (SectorBuffer
== NULL
)
616 return(STATUS_INSUFFICIENT_RESOURCES
);
619 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
621 if (LayoutBuffer
== NULL
)
623 ExFreePool(SectorBuffer
);
624 return(STATUS_INSUFFICIENT_RESOURCES
);
627 RtlZeroMemory(LayoutBuffer
,
630 PartitionOffset
.QuadPart
= 0;
631 containerOffset
.QuadPart
= 0;
635 KeInitializeEvent(&Event
,
639 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
641 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
645 (PLARGE_INTEGER
)&PartitionOffset
,
648 Status
= IoCallDriver(DeviceObject
,
650 if (Status
== STATUS_PENDING
)
652 KeWaitForSingleObject(&Event
,
657 Status
= StatusBlock
.Status
;
660 if (!NT_SUCCESS(Status
))
662 DPRINT("Failed to read partition table sector (Status = 0x%08lx)\n",
664 ExFreePool(SectorBuffer
);
665 ExFreePool(LayoutBuffer
);
669 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+ PARTITION_OFFSET
);
671 /* check the boot sector id */
672 DPRINT("Magic %x\n", PartitionTable
->Magic
);
673 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
675 DbgPrint("Invalid partition table magic\n");
676 ExFreePool(SectorBuffer
);
677 *PartitionBuffer
= LayoutBuffer
;
678 return(STATUS_SUCCESS
);
682 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
684 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
686 PartitionTable
->Partition
[i
].BootFlags
,
687 PartitionTable
->Partition
[i
].PartitionType
,
688 PartitionTable
->Partition
[i
].StartingHead
,
689 PartitionTable
->Partition
[i
].StartingSector
& 0x3f,
690 (((PartitionTable
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
691 PartitionTable
->Partition
[i
].StartingCylinder
,
692 PartitionTable
->Partition
[i
].EndingHead
,
693 PartitionTable
->Partition
[i
].EndingSector
,
694 PartitionTable
->Partition
[i
].EndingCylinder
,
695 PartitionTable
->Partition
[i
].StartingBlock
,
696 PartitionTable
->Partition
[i
].SectorCount
);
700 if (ExtendedFound
== FALSE
);
702 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
705 ExtendedFound
= FALSE
;
707 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
709 if ((ReturnRecognizedPartitions
== FALSE
) ||
710 ((ReturnRecognizedPartitions
== TRUE
) &&
711 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
713 /* handle normal partition */
714 DPRINT("Partition %u: Normal Partition\n", i
);
715 Count
= LayoutBuffer
->PartitionCount
;
716 DPRINT("Logical Partition %u\n", Count
);
717 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
719 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
721 else if (IsContainerPartition(PartitionTable
->Partition
[i
].PartitionType
))
723 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
724 (ULONGLONG
)PartitionOffset
.QuadPart
;
728 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
729 (ULONGLONG
)PartitionOffset
.QuadPart
+
730 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
732 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
733 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
734 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
736 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
738 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
743 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
746 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
747 PartitionTable
->Partition
[i
].PartitionType
;
748 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
749 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
750 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
751 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
752 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
754 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
756 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
757 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
758 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
759 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
760 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
762 LayoutBuffer
->PartitionCount
++;
765 if (IsContainerPartition(PartitionTable
->Partition
[i
].PartitionType
))
767 ExtendedFound
= TRUE
;
768 if ((ULONGLONG
) containerOffset
.QuadPart
== (ULONGLONG
) 0)
770 containerOffset
= PartitionOffset
;
772 nextPartitionOffset
.QuadPart
= (ULONGLONG
) containerOffset
.QuadPart
+
773 (ULONGLONG
) PartitionTable
->Partition
[i
].StartingBlock
*
774 (ULONGLONG
) SectorSize
;
777 PartitionOffset
= nextPartitionOffset
;
779 while (ExtendedFound
== TRUE
);
781 *PartitionBuffer
= LayoutBuffer
;
782 ExFreePool(SectorBuffer
);
784 return(STATUS_SUCCESS
);
789 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
791 IN ULONG PartitionNumber
,
792 IN ULONG PartitionType
)
794 return(STATUS_NOT_IMPLEMENTED
);
799 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
801 IN ULONG SectorsPerTrack
,
802 IN ULONG NumberOfHeads
,
803 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
805 return(STATUS_NOT_IMPLEMENTED
);