1 /* $Id: xhaldrv.c,v 1.26 2003/02/26 14:12:43 ekohl 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 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 } PACKED PARTITION
, *PPARTITION
;
45 typedef struct _PARTITION_TABLE
47 PARTITION Partition
[PARTITION_TBL_SIZE
];
49 } PACKED PARTITION_TABLE
, *PPARTITION_TABLE
;
53 UCHAR MbrBootCode
[442]; /* 0x000 */
54 ULONG Signature
; /* 0x1B8 */
55 USHORT Unused
; /* 0x1BC */
56 PARTITION Partition
[PARTITION_TBL_SIZE
]; /* 0x1BE */
57 USHORT Magic
; /* 0x1FE */
61 /* FUNCTIONS *****************************************************************/
64 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
65 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
67 IO_STATUS_BLOCK StatusBlock
;
68 DISK_GEOMETRY DiskGeometry
;
69 PDEVICE_OBJECT DeviceObject
= NULL
;
70 PFILE_OBJECT FileObject
;
75 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
79 /* Get the drives sector size */
80 Status
= IoGetDeviceObjectPointer(DeviceName
,
84 if (!NT_SUCCESS(Status
))
86 DPRINT("Status %x\n",Status
);
90 KeInitializeEvent(&Event
,
94 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
99 sizeof(DISK_GEOMETRY
),
105 ObDereferenceObject(FileObject
);
106 return(STATUS_INSUFFICIENT_RESOURCES
);
109 Status
= IoCallDriver(DeviceObject
,
111 if (Status
== STATUS_PENDING
)
113 KeWaitForSingleObject(&Event
,
118 Status
= StatusBlock
.Status
;
120 if (!NT_SUCCESS(Status
))
122 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
124 DiskGeometry
.BytesPerSector
= 512;
128 ObDereferenceObject(FileObject
);
133 DPRINT("DiskGeometry.BytesPerSector: %d\n",
134 DiskGeometry
.BytesPerSector
);
136 /* read the partition table */
137 Status
= IoReadPartitionTable(DeviceObject
,
138 DiskGeometry
.BytesPerSector
,
142 if ((!NT_SUCCESS(Status
) || (*LayoutInfo
)->PartitionCount
== 0) &&
143 DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
145 PDRIVE_LAYOUT_INFORMATION Buffer
;
147 if (NT_SUCCESS(Status
))
149 ExFreePool(*LayoutInfo
);
152 /* Allocate a partition list for a single entry. */
153 Buffer
= ExAllocatePool(NonPagedPool
,
154 sizeof(DRIVE_LAYOUT_INFORMATION
));
157 RtlZeroMemory(Buffer
,
158 sizeof(DRIVE_LAYOUT_INFORMATION
));
159 Buffer
->PartitionCount
= 1;
160 *LayoutInfo
= Buffer
;
162 Status
= STATUS_SUCCESS
;
166 ObDereferenceObject(FileObject
);
173 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
175 IN ULONG MBRTypeIdentifier
,
179 IO_STATUS_BLOCK StatusBlock
;
180 LARGE_INTEGER Offset
;
186 DPRINT1("xHalExamineMBR()\n");
189 if (SectorSize
< 512)
191 if (SectorSize
> 4096)
194 Mbr
= (PMBR
)ExAllocatePool(PagedPool
,
199 KeInitializeEvent(&Event
,
203 /* Read MBR (Master Boot Record) */
205 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
213 Status
= IoCallDriver(DeviceObject
,
215 if (Status
== STATUS_PENDING
)
217 KeWaitForSingleObject(&Event
,
222 Status
= StatusBlock
.Status
;
225 if (!NT_SUCCESS(Status
))
227 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
233 if (Mbr
->Magic
!= PARTITION_MAGIC
)
235 DPRINT("xHalExamineMBR: invalid MBR magic value\n");
240 if (Mbr
->Partition
[0].PartitionType
!= MBRTypeIdentifier
)
242 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
247 if (Mbr
->Partition
[0].PartitionType
== 0x54)
249 /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
254 *Buffer
= (PVOID
)Mbr
;
259 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
260 IN ULONG DriveNumber
,
263 WCHAR DriveNameBuffer
[8];
264 UNICODE_STRING DriveName
;
267 DPRINT("HalpAssignDrive()\n");
269 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
271 /* Force assignment */
272 if ((SharedUserData
->DosDeviceMap
& (1 << DriveNumber
)) != 0)
274 DbgPrint("Drive letter already used!\n");
280 /* Automatic assignment */
281 DriveNumber
= AUTO_DRIVE
;
283 for (i
= 2; i
< 24; i
++)
285 if ((SharedUserData
->DosDeviceMap
& (1 << i
)) == 0)
292 if (DriveNumber
== AUTO_DRIVE
)
294 DbgPrint("No drive letter available!\n");
299 DPRINT("DriveNumber %d\n", DriveNumber
);
301 /* Update the shared user page */
302 SharedUserData
->DosDeviceMap
|= (1 << DriveNumber
);
303 SharedUserData
->DosDeviceDriveType
[DriveNumber
] = DriveType
;
305 /* Build drive name */
306 swprintf(DriveNameBuffer
,
309 RtlInitUnicodeString(&DriveName
,
312 DPRINT(" %wZ ==> %wZ\n",
316 /* Create symbolic link */
317 IoCreateSymbolicLink(&DriveName
,
323 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
324 IN PSTRING NtDeviceName
,
325 OUT PUCHAR NtSystemPath
,
326 OUT PSTRING NtSystemPathString
)
328 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
329 PCONFIGURATION_INFORMATION ConfigInfo
;
330 OBJECT_ATTRIBUTES ObjectAttributes
;
331 IO_STATUS_BLOCK StatusBlock
;
332 UNICODE_STRING UnicodeString1
;
333 UNICODE_STRING UnicodeString2
;
341 DPRINT("xHalIoAssignDriveLetters()\n");
343 ConfigInfo
= IoGetConfigurationInformation();
345 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
347 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
350 /* Create PhysicalDrive links */
351 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
352 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
355 L
"\\Device\\Harddisk%d\\Partition0",
357 RtlInitUnicodeString(&UnicodeString1
,
360 InitializeObjectAttributes(&ObjectAttributes
,
366 Status
= NtOpenFile(&FileHandle
,
371 FILE_SYNCHRONOUS_IO_NONALERT
);
372 if (NT_SUCCESS(Status
))
377 L
"\\??\\PhysicalDrive%d",
379 RtlInitUnicodeString(&UnicodeString2
,
382 DPRINT("Creating link: %S ==> %S\n",
386 IoCreateSymbolicLink(&UnicodeString2
,
391 /* Initialize layout array */
392 LayoutArray
= ExAllocatePool(NonPagedPool
,
393 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
394 RtlZeroMemory(LayoutArray
,
395 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
396 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
399 L
"\\Device\\Harddisk%d\\Partition0",
401 RtlInitUnicodeString(&UnicodeString1
,
404 Status
= xHalQueryDriveLayout(&UnicodeString1
,
406 if (!NT_SUCCESS(Status
))
408 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
410 LayoutArray
[i
] = NULL
;
416 /* Dump layout array */
417 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
419 DPRINT("Harddisk %d:\n",
422 if (LayoutArray
[i
] == NULL
)
425 DPRINT("Logical partitions: %d\n",
426 LayoutArray
[i
]->PartitionCount
);
428 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
430 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
432 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
433 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
434 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
435 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
436 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
441 /* Assign pre-assigned (registry) partitions */
444 /* Assign bootable partition on first harddisk */
445 DPRINT("Assigning bootable primary partition on first harddisk:\n");
446 if (ConfigInfo
->DiskCount
> 0)
448 /* Search for bootable partition */
449 for (j
= 0; j
< LayoutArray
[0]->PartitionCount
; j
++)
451 if ((LayoutArray
[0]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
452 IsRecognizedPartition(LayoutArray
[0]->PartitionEntry
[j
].PartitionType
))
455 L
"\\Device\\Harddisk0\\Partition%d",
456 LayoutArray
[0]->PartitionEntry
[j
].PartitionNumber
);
457 RtlInitUnicodeString(&UnicodeString2
,
461 DPRINT(" %wZ\n", &UnicodeString2
);
462 HalpAssignDrive(&UnicodeString2
,
464 DOSDEVICE_DRIVE_FIXED
);
469 /* Assign remaining primary partitions */
470 DPRINT("Assigning remaining primary partitions:\n");
471 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
473 /* Search for primary partitions */
474 for (j
= 0; (j
< PARTITION_TBL_SIZE
) && (j
< LayoutArray
[i
]->PartitionCount
); j
++)
476 if ((i
== 0) && (LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== TRUE
))
479 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
482 L
"\\Device\\Harddisk%d\\Partition%d",
484 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
485 RtlInitUnicodeString(&UnicodeString2
,
491 HalpAssignDrive(&UnicodeString2
,
493 DOSDEVICE_DRIVE_FIXED
);
498 /* Assign extended (logical) partitions */
499 DPRINT("Assigning extended (logical) partitions:\n");
500 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
504 /* Search for extended partitions */
505 for (j
= PARTITION_TBL_SIZE
; j
< LayoutArray
[i
]->PartitionCount
; j
++)
507 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
508 (LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
!= 0))
511 L
"\\Device\\Harddisk%d\\Partition%d",
513 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
514 RtlInitUnicodeString(&UnicodeString2
,
520 HalpAssignDrive(&UnicodeString2
,
522 DOSDEVICE_DRIVE_FIXED
);
528 /* Assign removable disk drives */
529 DPRINT("Assigning removable disk drives:\n");
530 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
532 /* Search for virtual partitions */
533 if (LayoutArray
[i
]->PartitionCount
== 1 &&
534 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
537 L
"\\Device\\Harddisk%d\\Partition1",
539 RtlInitUnicodeString(&UnicodeString2
,
545 HalpAssignDrive(&UnicodeString2
,
547 DOSDEVICE_DRIVE_REMOVABLE
);
551 /* Free layout array */
552 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
554 if (LayoutArray
[i
] != NULL
)
555 ExFreePool(LayoutArray
[i
]);
557 ExFreePool(LayoutArray
);
559 /* Assign floppy drives */
560 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
561 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
564 L
"\\Device\\Floppy%d",
566 RtlInitUnicodeString(&UnicodeString1
,
569 /* Assign drive letters A: or B: or first free drive letter */
572 HalpAssignDrive(&UnicodeString1
,
573 (i
< 2) ? i
: AUTO_DRIVE
,
574 DOSDEVICE_DRIVE_REMOVABLE
);
577 /* Assign cdrom drives */
578 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
579 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
582 L
"\\Device\\CdRom%d",
584 RtlInitUnicodeString(&UnicodeString1
,
587 /* Assign first free drive letter */
588 DPRINT(" %wZ\n", &UnicodeString1
);
589 HalpAssignDrive(&UnicodeString1
,
591 DOSDEVICE_DRIVE_CDROM
);
594 /* Anything else ?? */
602 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
604 BOOLEAN ReturnRecognizedPartitions
,
605 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
608 IO_STATUS_BLOCK StatusBlock
;
609 ULARGE_INTEGER PartitionOffset
;
610 ULARGE_INTEGER nextPartitionOffset
;
611 ULARGE_INTEGER containerOffset
;
615 PPARTITION_TABLE PartitionTable
;
616 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
620 BOOLEAN ExtendedFound
= FALSE
;
622 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
625 ReturnRecognizedPartitions
,
628 *PartitionBuffer
= NULL
;
630 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
632 if (SectorBuffer
== NULL
)
634 return(STATUS_INSUFFICIENT_RESOURCES
);
637 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
639 if (LayoutBuffer
== NULL
)
641 ExFreePool(SectorBuffer
);
642 return(STATUS_INSUFFICIENT_RESOURCES
);
645 RtlZeroMemory(LayoutBuffer
,
648 PartitionOffset
.QuadPart
= 0;
649 containerOffset
.QuadPart
= 0;
653 KeInitializeEvent(&Event
,
657 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
659 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
663 (PLARGE_INTEGER
)&PartitionOffset
,
666 Status
= IoCallDriver(DeviceObject
,
668 if (Status
== STATUS_PENDING
)
670 KeWaitForSingleObject(&Event
,
675 Status
= StatusBlock
.Status
;
678 if (!NT_SUCCESS(Status
))
680 DPRINT("Failed to read partition table sector (Status = 0x%08lx)\n",
682 ExFreePool(SectorBuffer
);
683 ExFreePool(LayoutBuffer
);
687 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+ PARTITION_OFFSET
);
689 /* check the boot sector id */
690 DPRINT("Magic %x\n", PartitionTable
->Magic
);
691 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
693 DbgPrint("Invalid partition table magic\n");
694 ExFreePool(SectorBuffer
);
695 *PartitionBuffer
= LayoutBuffer
;
696 return(STATUS_SUCCESS
);
700 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
702 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
704 PartitionTable
->Partition
[i
].BootFlags
,
705 PartitionTable
->Partition
[i
].PartitionType
,
706 PartitionTable
->Partition
[i
].StartingHead
,
707 PartitionTable
->Partition
[i
].StartingSector
& 0x3f,
708 (((PartitionTable
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
709 PartitionTable
->Partition
[i
].StartingCylinder
,
710 PartitionTable
->Partition
[i
].EndingHead
,
711 PartitionTable
->Partition
[i
].EndingSector
,
712 PartitionTable
->Partition
[i
].EndingCylinder
,
713 PartitionTable
->Partition
[i
].StartingBlock
,
714 PartitionTable
->Partition
[i
].SectorCount
);
718 if (ExtendedFound
== FALSE
);
720 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
723 ExtendedFound
= FALSE
;
725 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
727 if ((ReturnRecognizedPartitions
== FALSE
) ||
728 ((ReturnRecognizedPartitions
== TRUE
) &&
729 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
731 /* handle normal partition */
732 DPRINT("Partition %u: Normal Partition\n", i
);
733 Count
= LayoutBuffer
->PartitionCount
;
734 DPRINT("Logical Partition %u\n", Count
);
735 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
737 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
739 else if (IsContainerPartition(PartitionTable
->Partition
[i
].PartitionType
))
741 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
742 (ULONGLONG
)PartitionOffset
.QuadPart
;
746 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
747 (ULONGLONG
)PartitionOffset
.QuadPart
+
748 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
750 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
751 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
752 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
754 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
756 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
761 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
764 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
765 PartitionTable
->Partition
[i
].PartitionType
;
766 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
767 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
768 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
769 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
770 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
772 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
774 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
775 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
776 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
777 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
778 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
780 LayoutBuffer
->PartitionCount
++;
783 if (IsContainerPartition(PartitionTable
->Partition
[i
].PartitionType
))
785 ExtendedFound
= TRUE
;
786 if ((ULONGLONG
) containerOffset
.QuadPart
== (ULONGLONG
) 0)
788 containerOffset
= PartitionOffset
;
790 nextPartitionOffset
.QuadPart
= (ULONGLONG
) containerOffset
.QuadPart
+
791 (ULONGLONG
) PartitionTable
->Partition
[i
].StartingBlock
*
792 (ULONGLONG
) SectorSize
;
795 PartitionOffset
= nextPartitionOffset
;
797 while (ExtendedFound
== TRUE
);
799 *PartitionBuffer
= LayoutBuffer
;
800 ExFreePool(SectorBuffer
);
802 return(STATUS_SUCCESS
);
807 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
809 IN ULONG PartitionNumber
,
810 IN ULONG PartitionType
)
812 return(STATUS_NOT_IMPLEMENTED
);
817 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
819 IN ULONG SectorsPerTrack
,
820 IN ULONG NumberOfHeads
,
821 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
823 return(STATUS_NOT_IMPLEMENTED
);