1 /* $Id: xhaldrv.c,v 1.19 2002/04/17 18:26:53 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 #define IsUsablePartition(P) \
32 ((P) == PTDOS3xPrimary || \
33 (P) == PTOLDDOS16Bit || \
34 (P) == PTDos5xPrimary || \
35 (P) == PTWin95FAT32 || \
36 (P) == PTWin95FAT32LBA || \
37 (P) == PTWin95FAT16LBA)
40 typedef struct _PARTITION
42 unsigned char BootFlags
;
43 unsigned char StartingHead
;
44 unsigned char StartingSector
;
45 unsigned char StartingCylinder
;
46 unsigned char PartitionType
;
47 unsigned char EndingHead
;
48 unsigned char EndingSector
;
49 unsigned char EndingCylinder
;
50 unsigned int StartingBlock
;
51 unsigned int SectorCount
;
52 } PARTITION
, *PPARTITION
;
54 typedef struct _PARTITION_TABLE
56 PARTITION Partition
[PARTITION_TBL_SIZE
];
58 } PARTITION_TABLE
, *PPARTITION_TABLE
;
60 /* FUNCTIONS *****************************************************************/
63 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
64 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
66 IO_STATUS_BLOCK StatusBlock
;
67 DISK_GEOMETRY DiskGeometry
;
68 PDEVICE_OBJECT DeviceObject
= NULL
;
69 PFILE_OBJECT FileObject
;
74 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
78 /* Get the drives sector size */
79 Status
= IoGetDeviceObjectPointer(DeviceName
,
83 if (!NT_SUCCESS(Status
))
85 DPRINT("Status %x\n",Status
);
89 KeInitializeEvent(&Event
,
93 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
98 sizeof(DISK_GEOMETRY
),
104 ObDereferenceObject(FileObject
);
105 return STATUS_INSUFFICIENT_RESOURCES
;
108 Status
= IoCallDriver(DeviceObject
,
110 if (Status
== STATUS_PENDING
)
112 KeWaitForSingleObject(&Event
,
117 Status
= StatusBlock
.Status
;
119 if (!NT_SUCCESS(Status
))
121 ObDereferenceObject(FileObject
);
125 DPRINT("DiskGeometry.BytesPerSector: %d\n",
126 DiskGeometry
.BytesPerSector
);
128 /* read the partition table */
129 Status
= IoReadPartitionTable(DeviceObject
,
130 DiskGeometry
.BytesPerSector
,
134 if ((!NT_SUCCESS(Status
) || (*LayoutInfo
)->PartitionCount
== 0) &&
135 DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
137 PDRIVE_LAYOUT_INFORMATION Buffer
;
139 if (NT_SUCCESS(Status
))
141 ExFreePool(*LayoutInfo
);
144 /* Allocate a partition list for a single entry. */
145 Buffer
= ExAllocatePool(NonPagedPool
,
146 sizeof(DRIVE_LAYOUT_INFORMATION
));
149 RtlZeroMemory(Buffer
,
150 sizeof(DRIVE_LAYOUT_INFORMATION
));
151 Buffer
->PartitionCount
= 1;
152 *LayoutInfo
= Buffer
;
154 Status
= STATUS_SUCCESS
;
158 ObDereferenceObject(FileObject
);
165 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
167 IN ULONG MBRTypeIdentifier
,
171 IO_STATUS_BLOCK StatusBlock
;
172 LARGE_INTEGER Offset
;
177 DPRINT("xHalExamineMBR()\n");
180 if (SectorSize
< 512)
182 if (SectorSize
> 4096)
185 LocalBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
187 if (LocalBuffer
== NULL
)
190 KeInitializeEvent(&Event
,
196 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
204 Status
= IoCallDriver(DeviceObject
,
206 if (Status
== STATUS_PENDING
)
208 KeWaitForSingleObject(&Event
,
213 Status
= StatusBlock
.Status
;
216 if (!NT_SUCCESS(Status
))
218 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
220 ExFreePool(LocalBuffer
);
224 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
226 DPRINT("xHalExamineMBR: invalid MBR signature\n");
227 ExFreePool(LocalBuffer
);
231 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
233 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
234 ExFreePool(LocalBuffer
);
238 *Buffer
= (PVOID
)LocalBuffer
;
243 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
244 IN OUT PULONG DriveMap
,
245 IN ULONG DriveNumber
)
247 WCHAR DriveNameBuffer
[8];
248 UNICODE_STRING DriveName
;
251 DPRINT("HalpAssignDrive()\n");
253 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
255 /* force assignment */
256 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
258 DbgPrint("Drive letter already used!\n");
264 /* automatic assignment */
265 DriveNumber
= AUTO_DRIVE
;
267 for (i
= 2; i
< 24; i
++)
269 if ((*DriveMap
& (1 << i
)) == 0)
276 if (DriveNumber
== AUTO_DRIVE
)
278 DbgPrint("No drive letter available!\n");
283 DPRINT("DriveNumber %d\n", DriveNumber
);
285 /* set bit in drive map */
286 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
288 /* build drive name */
289 swprintf(DriveNameBuffer
,
292 RtlInitUnicodeString(&DriveName
,
295 DPRINT(" %wZ ==> %wZ\n",
299 /* create symbolic link */
300 IoCreateSymbolicLink(&DriveName
,
306 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
307 IN PSTRING NtDeviceName
,
308 OUT PUCHAR NtSystemPath
,
309 OUT PSTRING NtSystemPathString
)
311 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
312 PCONFIGURATION_INFORMATION ConfigInfo
;
313 OBJECT_ATTRIBUTES ObjectAttributes
;
314 IO_STATUS_BLOCK StatusBlock
;
315 UNICODE_STRING UnicodeString1
;
316 UNICODE_STRING UnicodeString2
;
325 DPRINT("xHalIoAssignDriveLetters()\n");
327 ConfigInfo
= IoGetConfigurationInformation ();
329 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
331 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
334 /* Create PhysicalDrive links */
335 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
336 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
339 L
"\\Device\\Harddisk%d\\Partition0",
341 RtlInitUnicodeString(&UnicodeString1
,
344 InitializeObjectAttributes(&ObjectAttributes
,
350 Status
= NtOpenFile(&FileHandle
,
355 FILE_SYNCHRONOUS_IO_NONALERT
);
356 if (NT_SUCCESS(Status
))
361 L
"\\??\\PhysicalDrive%d",
363 RtlInitUnicodeString(&UnicodeString2
,
366 DPRINT("Creating link: %S ==> %S\n",
370 IoCreateSymbolicLink(&UnicodeString2
,
375 /* Initialize layout array */
376 LayoutArray
= ExAllocatePool(NonPagedPool
,
377 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
378 RtlZeroMemory(LayoutArray
,
379 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
380 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
383 L
"\\Device\\Harddisk%d\\Partition0",
385 RtlInitUnicodeString(&UnicodeString1
,
388 Status
= xHalQueryDriveLayout(&UnicodeString1
,
390 if (!NT_SUCCESS(Status
))
392 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
394 LayoutArray
[i
] = NULL
;
400 /* Dump layout array */
401 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
403 DPRINT("Harddisk %d:\n",
406 if (LayoutArray
[i
] == NULL
)
409 DPRINT("Logical partitions: %d\n",
410 LayoutArray
[i
]->PartitionCount
);
412 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
414 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
416 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
417 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
418 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
419 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
420 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
425 /* Assign pre-assigned (registry) partitions */
428 /* Assign bootable partition on first harddisk */
429 DPRINT("Assigning bootable primary partition on first harddisk:\n");
430 if (ConfigInfo
->DiskCount
> 0)
432 /* search for bootable partition */
433 for (j
= 0; j
< LayoutArray
[0]->PartitionCount
; j
++)
435 if ((LayoutArray
[0]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
436 IsUsablePartition(LayoutArray
[0]->PartitionEntry
[j
].PartitionType
))
439 L
"\\Device\\Harddisk0\\Partition%d",
440 LayoutArray
[0]->PartitionEntry
[j
].PartitionNumber
);
441 RtlInitUnicodeString(&UnicodeString2
,
444 DPRINT(" %wZ\n", &UnicodeString2
);
447 HalpAssignDrive(&UnicodeString2
,
454 /* Assign remaining primary partitions */
455 DPRINT("Assigning remaining primary partitions:\n");
456 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
458 /* search for primary partitions */
459 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
462 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
463 IsUsablePartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
466 L
"\\Device\\Harddisk%d\\Partition%d",
468 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
469 RtlInitUnicodeString(&UnicodeString2
,
475 HalpAssignDrive(&UnicodeString2
,
482 /* Assign extended (logical) partitions */
483 DPRINT("Assigning extended (logical) partitions:\n");
484 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
486 if( LayoutArray
[i
] ){
487 /* search for extended partitions */
488 for (j
= PARTITION_TBL_SIZE
; j
< LayoutArray
[i
]->PartitionCount
; j
++)
490 if (IsUsablePartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
491 (LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
!= 0))
494 L
"\\Device\\Harddisk%d\\Partition%d",
496 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
497 RtlInitUnicodeString(&UnicodeString2
,
503 HalpAssignDrive(&UnicodeString2
,
513 /* Assign removable disk drives */
514 DPRINT("Assigning extended (logical) partitions:\n");
515 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
517 /* Search for virtual partitions */
518 if (LayoutArray
[i
]->PartitionCount
== 1 &&
519 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
522 L
"\\Device\\Harddisk%d\\Partition1",
524 RtlInitUnicodeString(&UnicodeString2
,
530 HalpAssignDrive(&UnicodeString2
,
538 /* Free layout array */
539 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
541 if (LayoutArray
[i
] != NULL
)
542 ExFreePool(LayoutArray
[i
]);
544 ExFreePool(LayoutArray
);
546 /* Assign floppy drives */
547 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
548 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
551 L
"\\Device\\Floppy%d",
553 RtlInitUnicodeString(&UnicodeString1
,
556 /* assign drive letters A: or B: or first free drive letter */
559 HalpAssignDrive(&UnicodeString1
,
561 (i
< 2) ? i
: AUTO_DRIVE
);
564 /* Assign cdrom drives */
565 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
566 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
569 L
"\\Device\\CdRom%d",
571 RtlInitUnicodeString(&UnicodeString1
,
574 /* assign first free drive letter */
575 DPRINT(" %wZ\n", &UnicodeString1
);
576 HalpAssignDrive(&UnicodeString1
,
581 /* Anything else ?? */
590 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
592 BOOLEAN ReturnRecognizedPartitions
,
593 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
596 IO_STATUS_BLOCK StatusBlock
;
597 ULARGE_INTEGER PartitionOffset
;
598 ULARGE_INTEGER nextPartitionOffset
;
599 ULARGE_INTEGER containerOffset
;
603 PPARTITION_TABLE PartitionTable
;
604 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
608 BOOLEAN ExtendedFound
= FALSE
;
610 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
613 ReturnRecognizedPartitions
,
616 *PartitionBuffer
= NULL
;
618 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
620 if (SectorBuffer
== NULL
)
622 return STATUS_INSUFFICIENT_RESOURCES
;
625 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
627 if (LayoutBuffer
== NULL
)
629 ExFreePool (SectorBuffer
);
630 return STATUS_INSUFFICIENT_RESOURCES
;
633 RtlZeroMemory(LayoutBuffer
,
636 PartitionOffset
.QuadPart
= 0;
637 containerOffset
.QuadPart
= 0;
641 KeInitializeEvent(&Event
,
645 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
647 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
651 (PLARGE_INTEGER
)&PartitionOffset
,
654 Status
= IoCallDriver(DeviceObject
,
656 if (Status
== STATUS_PENDING
)
658 KeWaitForSingleObject(&Event
,
663 Status
= StatusBlock
.Status
;
666 if (!NT_SUCCESS(Status
))
668 DbgPrint("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
670 ExFreePool(SectorBuffer
);
671 ExFreePool(LayoutBuffer
);
675 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
677 /* check the boot sector id */
678 DPRINT("Magic %x\n", PartitionTable
->Magic
);
679 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
681 DbgPrint("Invalid partition table magic\n");
682 ExFreePool(SectorBuffer
);
683 *PartitionBuffer
= LayoutBuffer
;
684 return STATUS_SUCCESS
;
688 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
690 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
692 PartitionTable
->Partition
[i
].BootFlags
,
693 PartitionTable
->Partition
[i
].PartitionType
,
694 PartitionTable
->Partition
[i
].StartingHead
,
695 PartitionTable
->Partition
[i
].StartingSector
& 0x3f,
696 (((PartitionTable
->Partition
[i
].StartingSector
) & 0xc0) << 2) +
697 PartitionTable
->Partition
[i
].StartingCylinder
,
698 PartitionTable
->Partition
[i
].EndingHead
,
699 PartitionTable
->Partition
[i
].EndingSector
,
700 PartitionTable
->Partition
[i
].EndingCylinder
,
701 PartitionTable
->Partition
[i
].StartingBlock
,
702 PartitionTable
->Partition
[i
].SectorCount
);
706 if (ExtendedFound
== FALSE
);
708 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
711 ExtendedFound
= FALSE
;
713 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
715 if ((ReturnRecognizedPartitions
== FALSE
) ||
716 ((ReturnRecognizedPartitions
== TRUE
) &&
717 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
719 /* handle normal partition */
720 DPRINT("Partition %u: Normal Partition\n", i
);
721 Count
= LayoutBuffer
->PartitionCount
;
722 DPRINT("Logical Partition %u\n", Count
);
723 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
725 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
727 else if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
729 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
730 (ULONGLONG
)PartitionOffset
.QuadPart
;
734 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
735 (ULONGLONG
)PartitionOffset
.QuadPart
+
736 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
738 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
739 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
740 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
742 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
744 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
749 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
752 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
753 PartitionTable
->Partition
[i
].PartitionType
;
754 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
755 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
756 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
757 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
758 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
760 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
762 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
763 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
764 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
765 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
766 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
768 LayoutBuffer
->PartitionCount
++;
772 if (IsNormalPartition(PartitionTable
->Partition
[i
].PartitionType
))
774 PartitionOffset
.QuadPart
= (ULONGLONG
)PartitionOffset
.QuadPart
+
775 (((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
+
776 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
)* (ULONGLONG
)SectorSize
);
780 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
782 ExtendedFound
= TRUE
;
783 if ((ULONGLONG
) containerOffset
.QuadPart
== (ULONGLONG
) 0)
785 containerOffset
= PartitionOffset
;
787 nextPartitionOffset
.QuadPart
= (ULONGLONG
) containerOffset
.QuadPart
+
788 (ULONGLONG
) PartitionTable
->Partition
[i
].StartingBlock
*
789 (ULONGLONG
) SectorSize
;
792 PartitionOffset
= nextPartitionOffset
;
794 while (ExtendedFound
== TRUE
);
796 *PartitionBuffer
= LayoutBuffer
;
797 ExFreePool(SectorBuffer
);
799 return STATUS_SUCCESS
;
803 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
805 IN ULONG PartitionNumber
,
806 IN ULONG PartitionType
)
808 return STATUS_NOT_IMPLEMENTED
;
813 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
815 IN ULONG SectorsPerTrack
,
816 IN ULONG NumberOfHeads
,
817 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
819 return STATUS_NOT_IMPLEMENTED
;