1 /* $Id: xhaldrv.c,v 1.12 2001/06/28 02:56:27 rex 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 *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/xhal.h>
18 #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 #define IsUsablePartition(P) \
33 (P) != PTDosExtended && \
34 (P) < PTWin95ExtendedLBA)
37 #define IsUsablePartition(P) \
38 ((P) == PTDOS3xPrimary || \
39 (P) == PTOLDDOS16Bit || \
40 (P) == PTDos5xPrimary || \
41 (P) == PTWin95FAT32 || \
42 (P) == PTWin95FAT32LBA || \
43 (P) == PTWin95FAT16LBA)
45 typedef struct _PARTITION
47 unsigned char BootFlags
;
48 unsigned char StartingHead
;
49 unsigned char StartingSector
;
50 unsigned char StartingCylinder
;
51 unsigned char PartitionType
;
52 unsigned char EndingHead
;
53 unsigned char EndingSector
;
54 unsigned char EndingCylinder
;
55 unsigned int StartingBlock
;
56 unsigned int SectorCount
;
57 } PARTITION
, *PPARTITION
;
59 typedef struct _PARTITION_TABLE
61 PARTITION Partition
[PARTITION_TBL_SIZE
];
63 } PARTITION_TABLE
, *PPARTITION_TABLE
;
65 /* FUNCTIONS *****************************************************************/
68 xHalpQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
69 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
71 IO_STATUS_BLOCK StatusBlock
;
72 DISK_GEOMETRY DiskGeometry
;
73 PDEVICE_OBJECT DeviceObject
= NULL
;
74 PFILE_OBJECT FileObject
;
79 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
83 /* Get the drives sector size */
84 Status
= IoGetDeviceObjectPointer(DeviceName
,
88 if (!NT_SUCCESS(Status
))
90 DPRINT("Status %x\n",Status
);
94 KeInitializeEvent(&Event
,
98 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
103 sizeof(DISK_GEOMETRY
),
109 ObDereferenceObject(FileObject
);
110 return STATUS_INSUFFICIENT_RESOURCES
;
113 Status
= IoCallDriver(DeviceObject
,
115 if (Status
== STATUS_PENDING
)
117 KeWaitForSingleObject(&Event
,
122 Status
= StatusBlock
.Status
;
124 if (!NT_SUCCESS(Status
))
126 ObDereferenceObject(FileObject
);
130 DPRINT("DiskGeometry.BytesPerSector: %d\n",
131 DiskGeometry
.BytesPerSector
);
133 /* read the partition table */
134 Status
= IoReadPartitionTable(DeviceObject
,
135 DiskGeometry
.BytesPerSector
,
139 ObDereferenceObject(FileObject
);
146 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
148 IN ULONG MBRTypeIdentifier
,
152 IO_STATUS_BLOCK StatusBlock
;
153 LARGE_INTEGER Offset
;
158 DPRINT("xHalExamineMBR()\n");
161 if (SectorSize
< 512)
163 if (SectorSize
> 4096)
166 LocalBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
168 if (LocalBuffer
== NULL
)
171 KeInitializeEvent(&Event
,
177 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
185 Status
= IoCallDriver(DeviceObject
,
187 if (Status
== STATUS_PENDING
)
189 KeWaitForSingleObject(&Event
,
194 Status
= StatusBlock
.Status
;
197 if (!NT_SUCCESS(Status
))
199 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
201 ExFreePool(LocalBuffer
);
205 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
207 DPRINT("xHalExamineMBR: invalid MBR signature\n");
208 ExFreePool(LocalBuffer
);
212 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
214 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
215 ExFreePool(LocalBuffer
);
219 *Buffer
= (PVOID
)LocalBuffer
;
224 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
225 IN OUT PULONG DriveMap
,
226 IN ULONG DriveNumber
)
228 WCHAR DriveNameBuffer
[8];
229 UNICODE_STRING DriveName
;
232 DPRINT("HalpAssignDrive()\n");
234 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
236 /* force assignment */
237 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
239 DbgPrint("Drive letter already used!\n");
245 /* automatic assignment */
246 DriveNumber
= AUTO_DRIVE
;
248 for (i
= 2; i
< 24; i
++)
250 if ((*DriveMap
& (1 << i
)) == 0)
257 if (DriveNumber
== AUTO_DRIVE
)
259 DbgPrint("No drive letter available!\n");
264 DPRINT("DriveNumber %d\n", DriveNumber
);
266 /* set bit in drive map */
267 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
269 /* build drive name */
270 swprintf(DriveNameBuffer
,
273 RtlInitUnicodeString(&DriveName
,
276 DPRINT(" %wZ ==> %wZ\n",
280 /* create symbolic link */
281 IoCreateSymbolicLink(&DriveName
,
287 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
288 IN PSTRING NtDeviceName
,
289 OUT PUCHAR NtSystemPath
,
290 OUT PSTRING NtSystemPathString
)
292 PDRIVE_LAYOUT_INFORMATION LayoutInfo
;
293 PCONFIGURATION_INFORMATION ConfigInfo
;
294 OBJECT_ATTRIBUTES ObjectAttributes
;
295 IO_STATUS_BLOCK StatusBlock
;
296 UNICODE_STRING UnicodeString1
;
297 UNICODE_STRING UnicodeString2
;
306 DPRINT("xHalIoAssignDriveLetters()\n");
308 ConfigInfo
= IoGetConfigurationInformation ();
310 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
312 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
315 /* Create PhysicalDrive links */
316 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
317 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
320 L
"\\Device\\Harddisk%d\\Partition0",
322 RtlInitUnicodeString(&UnicodeString1
,
325 InitializeObjectAttributes(&ObjectAttributes
,
331 Status
= NtOpenFile(&FileHandle
,
336 FILE_SYNCHRONOUS_IO_NONALERT
);
337 if (NT_SUCCESS(Status
))
342 L
"\\??\\PhysicalDrive%d",
344 RtlInitUnicodeString(&UnicodeString2
,
347 DPRINT("Creating link: %S ==> %S\n",
351 IoCreateSymbolicLink(&UnicodeString2
,
356 /* Assign pre-assigned (registry) partitions */
358 /* Assign bootable partitions */
359 DPRINT("Assigning bootable partitions:\n");
360 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
363 L
"\\Device\\Harddisk%d\\Partition0",
365 RtlInitUnicodeString(&UnicodeString1
,
368 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
370 if (!NT_SUCCESS(Status
))
372 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
377 DPRINT("Logical partitions: %d\n",
378 LayoutInfo
->PartitionCount
);
380 /* search for bootable partitions */
381 for (j
= 0; j
< LayoutInfo
->PartitionCount
; j
++)
383 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
385 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
386 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
387 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
388 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
389 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
391 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
392 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
395 L
"\\Device\\Harddisk%d\\Partition%d",
397 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
398 RtlInitUnicodeString(&UnicodeString2
,
401 DPRINT(" %wZ\n", &UnicodeString2
);
404 HalpAssignDrive(&UnicodeString2
,
410 ExFreePool (LayoutInfo
);
413 /* Assign remaining primary partitions */
414 DPRINT("Assigning primary partitions:\n");
415 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
418 L
"\\Device\\Harddisk%d\\Partition0",
420 RtlInitUnicodeString(&UnicodeString1
,
423 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
425 if (!NT_SUCCESS(Status
))
427 DbgPrint("xHalpQueryDriveLayout(%wZ) failed (Status = 0x%lx)\n",
433 DPRINT("Logical partitions: %d\n",
434 LayoutInfo
->PartitionCount
);
436 /* search for primary (non-bootable) partitions */
437 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
439 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
441 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
442 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
443 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
444 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
445 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
447 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== FALSE
) &&
448 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
451 L
"\\Device\\Harddisk%d\\Partition%d",
453 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
454 RtlInitUnicodeString(&UnicodeString2
,
460 HalpAssignDrive(&UnicodeString2
,
466 ExFreePool(LayoutInfo
);
469 /* Assign extended (logical) partitions */
470 DPRINT("Assigning extended (logical) partitions:\n");
471 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
474 L
"\\Device\\Harddisk%d\\Partition0",
476 RtlInitUnicodeString(&UnicodeString1
,
479 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
481 if (!NT_SUCCESS(Status
))
483 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
488 DPRINT("Logical partitions: %d\n",
489 LayoutInfo
->PartitionCount
);
491 /* search for extended partitions */
492 for (j
= PARTITION_TBL_SIZE
; j
< LayoutInfo
->PartitionCount
; j
++)
494 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
496 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
497 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
498 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
499 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
500 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
502 if (IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
) &&
503 (LayoutInfo
->PartitionEntry
[j
].PartitionNumber
!= 0))
506 L
"\\Device\\Harddisk%d\\Partition%d",
508 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
509 RtlInitUnicodeString(&UnicodeString2
,
515 HalpAssignDrive(&UnicodeString2
,
521 ExFreePool(LayoutInfo
);
524 /* Assign floppy drives */
525 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
526 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
529 L
"\\Device\\Floppy%d",
531 RtlInitUnicodeString(&UnicodeString1
,
534 /* assign drive letters A: or B: or first free drive letter */
537 HalpAssignDrive(&UnicodeString1
,
539 (i
< 2) ? i
: AUTO_DRIVE
);
542 /* Assign cdrom drives */
543 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
544 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
547 L
"\\Device\\Cdrom%d",
549 RtlInitUnicodeString(&UnicodeString1
,
552 /* assign first free drive letter */
553 DPRINT(" %wZ\n", &UnicodeString1
);
554 HalpAssignDrive(&UnicodeString1
,
559 /* Anything else ?? */
568 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
570 BOOLEAN ReturnRecognizedPartitions
,
571 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
574 IO_STATUS_BLOCK StatusBlock
;
575 ULARGE_INTEGER PartitionOffset
;
579 PPARTITION_TABLE PartitionTable
;
580 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
584 BOOLEAN ExtendedFound
= FALSE
;
586 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
589 ReturnRecognizedPartitions
,
592 *PartitionBuffer
= NULL
;
594 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
596 if (SectorBuffer
== NULL
)
598 return STATUS_INSUFFICIENT_RESOURCES
;
601 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
603 if (LayoutBuffer
== NULL
)
605 ExFreePool (SectorBuffer
);
606 return STATUS_INSUFFICIENT_RESOURCES
;
609 RtlZeroMemory(LayoutBuffer
,
612 PartitionOffset
.QuadPart
= 0;
616 KeInitializeEvent(&Event
,
620 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
622 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
626 (PLARGE_INTEGER
)&PartitionOffset
,
629 Status
= IoCallDriver(DeviceObject
,
631 if (Status
== STATUS_PENDING
)
633 KeWaitForSingleObject(&Event
,
638 Status
= StatusBlock
.Status
;
641 if (!NT_SUCCESS(Status
))
643 DbgPrint("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
645 ExFreePool(SectorBuffer
);
646 ExFreePool(LayoutBuffer
);
650 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
652 /* check the boot sector id */
653 DPRINT("Magic %x\n", PartitionTable
->Magic
);
654 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
656 DbgPrint("Invalid partition table magic\n");
657 ExFreePool(SectorBuffer
);
658 *PartitionBuffer
= LayoutBuffer
;
659 return STATUS_SUCCESS
;
663 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
665 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
667 PartitionTable
->Partition
[i
].BootFlags
,
668 PartitionTable
->Partition
[i
].PartitionType
,
669 PartitionTable
->Partition
[i
].StartingHead
,
670 PartitionTable
->Partition
[i
].StartingSector
,
671 PartitionTable
->Partition
[i
].StartingCylinder
,
672 PartitionTable
->Partition
[i
].EndingHead
,
673 PartitionTable
->Partition
[i
].EndingSector
,
674 PartitionTable
->Partition
[i
].EndingCylinder
,
675 PartitionTable
->Partition
[i
].StartingBlock
,
676 PartitionTable
->Partition
[i
].SectorCount
);
680 if (ExtendedFound
== FALSE
);
682 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
685 ExtendedFound
= FALSE
;
687 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
689 if ((ReturnRecognizedPartitions
== FALSE
) ||
690 ((ReturnRecognizedPartitions
== TRUE
) &&
691 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
693 /* handle normal partition */
694 DPRINT("Partition %u: Normal Partition\n", i
);
695 Count
= LayoutBuffer
->PartitionCount
;
696 DPRINT("Logical Partition %u\n", Count
);
697 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
699 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
701 else if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
703 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
704 (ULONGLONG
)PartitionOffset
.QuadPart
;
708 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
709 (ULONGLONG
)PartitionOffset
.QuadPart
+
710 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
712 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
713 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
714 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
716 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
718 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
723 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
726 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
727 PartitionTable
->Partition
[i
].PartitionType
;
728 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
729 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
730 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
731 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
732 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
734 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
736 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
737 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
738 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
739 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
740 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
742 LayoutBuffer
->PartitionCount
++;
745 if (IsNormalPartition(PartitionTable
->Partition
[i
].PartitionType
))
747 PartitionOffset
.QuadPart
= (ULONGLONG
)PartitionOffset
.QuadPart
+
748 (((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
+
749 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
)* (ULONGLONG
)SectorSize
);
752 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
754 ExtendedFound
= TRUE
;
758 while (ExtendedFound
== TRUE
);
760 *PartitionBuffer
= LayoutBuffer
;
761 ExFreePool(SectorBuffer
);
763 return STATUS_SUCCESS
;
768 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
770 IN ULONG PartitionNumber
,
771 IN ULONG PartitionType
)
773 return STATUS_NOT_IMPLEMENTED
;
778 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
780 IN ULONG SectorsPerTrack
,
781 IN ULONG NumberOfHeads
,
782 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
784 return STATUS_NOT_IMPLEMENTED
;