1 /* $Id: xhaldrv.c,v 1.14 2001/07/04 16:42:37 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) \
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 xHalpQueryDriveLayout(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 ObDereferenceObject(FileObject
);
141 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
143 IN ULONG MBRTypeIdentifier
,
147 IO_STATUS_BLOCK StatusBlock
;
148 LARGE_INTEGER Offset
;
153 DPRINT("xHalExamineMBR()\n");
156 if (SectorSize
< 512)
158 if (SectorSize
> 4096)
161 LocalBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
163 if (LocalBuffer
== NULL
)
166 KeInitializeEvent(&Event
,
172 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
180 Status
= IoCallDriver(DeviceObject
,
182 if (Status
== STATUS_PENDING
)
184 KeWaitForSingleObject(&Event
,
189 Status
= StatusBlock
.Status
;
192 if (!NT_SUCCESS(Status
))
194 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
196 ExFreePool(LocalBuffer
);
200 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
202 DPRINT("xHalExamineMBR: invalid MBR signature\n");
203 ExFreePool(LocalBuffer
);
207 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
209 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
210 ExFreePool(LocalBuffer
);
214 *Buffer
= (PVOID
)LocalBuffer
;
219 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
220 IN OUT PULONG DriveMap
,
221 IN ULONG DriveNumber
)
223 WCHAR DriveNameBuffer
[8];
224 UNICODE_STRING DriveName
;
227 DPRINT("HalpAssignDrive()\n");
229 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
231 /* force assignment */
232 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
234 DbgPrint("Drive letter already used!\n");
240 /* automatic assignment */
241 DriveNumber
= AUTO_DRIVE
;
243 for (i
= 2; i
< 24; i
++)
245 if ((*DriveMap
& (1 << i
)) == 0)
252 if (DriveNumber
== AUTO_DRIVE
)
254 DbgPrint("No drive letter available!\n");
259 DPRINT("DriveNumber %d\n", DriveNumber
);
261 /* set bit in drive map */
262 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
264 /* build drive name */
265 swprintf(DriveNameBuffer
,
268 RtlInitUnicodeString(&DriveName
,
271 DPRINT(" %wZ ==> %wZ\n",
275 /* create symbolic link */
276 IoCreateSymbolicLink(&DriveName
,
282 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
283 IN PSTRING NtDeviceName
,
284 OUT PUCHAR NtSystemPath
,
285 OUT PSTRING NtSystemPathString
)
287 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
288 PCONFIGURATION_INFORMATION ConfigInfo
;
289 OBJECT_ATTRIBUTES ObjectAttributes
;
290 IO_STATUS_BLOCK StatusBlock
;
291 UNICODE_STRING UnicodeString1
;
292 UNICODE_STRING UnicodeString2
;
301 DPRINT("xHalIoAssignDriveLetters()\n");
303 ConfigInfo
= IoGetConfigurationInformation ();
305 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
307 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
310 /* Create PhysicalDrive links */
311 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
312 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
315 L
"\\Device\\Harddisk%d\\Partition0",
317 RtlInitUnicodeString(&UnicodeString1
,
320 InitializeObjectAttributes(&ObjectAttributes
,
326 Status
= NtOpenFile(&FileHandle
,
331 FILE_SYNCHRONOUS_IO_NONALERT
);
332 if (NT_SUCCESS(Status
))
337 L
"\\??\\PhysicalDrive%d",
339 RtlInitUnicodeString(&UnicodeString2
,
342 DPRINT("Creating link: %S ==> %S\n",
346 IoCreateSymbolicLink(&UnicodeString2
,
351 /* Initialize layout array */
352 LayoutArray
= ExAllocatePool(NonPagedPool
,
353 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
354 RtlZeroMemory(LayoutArray
,
355 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
356 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
359 L
"\\Device\\Harddisk%d\\Partition0",
361 RtlInitUnicodeString(&UnicodeString1
,
364 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
366 if (!NT_SUCCESS(Status
))
368 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
370 LayoutArray
[i
] = NULL
;
376 /* Dump layout array */
377 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
379 DPRINT("Harddisk %d:\n",
382 if (LayoutArray
[i
] == NULL
)
385 DPRINT("Logical partitions: %d\n",
386 LayoutArray
[i
]->PartitionCount
);
388 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
390 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
392 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
393 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
394 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
395 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
396 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
401 /* Assign pre-assigned (registry) partitions */
403 /* Assign bootable partitions */
404 DPRINT("Assigning bootable primary partitions:\n");
405 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
407 /* search for bootable partitions */
408 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
410 if ((LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
411 IsUsablePartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
414 L
"\\Device\\Harddisk%d\\Partition%d",
416 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
417 RtlInitUnicodeString(&UnicodeString2
,
420 DPRINT(" %wZ\n", &UnicodeString2
);
423 HalpAssignDrive(&UnicodeString2
,
430 /* Assign non-bootable primary partitions */
431 DPRINT("Assigning non-bootable primary partitions:\n");
432 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
434 /* search for primary (non-bootable) partitions */
435 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
437 if ((LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
== FALSE
) &&
438 IsUsablePartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
))
441 L
"\\Device\\Harddisk%d\\Partition%d",
443 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
444 RtlInitUnicodeString(&UnicodeString2
,
450 HalpAssignDrive(&UnicodeString2
,
457 /* Assign extended (logical) partitions */
458 DPRINT("Assigning extended (logical) partitions:\n");
459 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
461 /* search for extended partitions */
462 for (j
= PARTITION_TBL_SIZE
; j
< LayoutArray
[i
]->PartitionCount
; j
++)
464 if (IsUsablePartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
465 (LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
!= 0))
468 L
"\\Device\\Harddisk%d\\Partition%d",
470 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
471 RtlInitUnicodeString(&UnicodeString2
,
477 HalpAssignDrive(&UnicodeString2
,
484 /* Free layout array */
485 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
487 if (LayoutArray
[i
] != NULL
)
488 ExFreePool(LayoutArray
[i
]);
490 ExFreePool(LayoutArray
);
492 /* Assign floppy drives */
493 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
494 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
497 L
"\\Device\\Floppy%d",
499 RtlInitUnicodeString(&UnicodeString1
,
502 /* assign drive letters A: or B: or first free drive letter */
505 HalpAssignDrive(&UnicodeString1
,
507 (i
< 2) ? i
: AUTO_DRIVE
);
510 /* Assign cdrom drives */
511 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
512 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
515 L
"\\Device\\Cdrom%d",
517 RtlInitUnicodeString(&UnicodeString1
,
520 /* assign first free drive letter */
521 DPRINT(" %wZ\n", &UnicodeString1
);
522 HalpAssignDrive(&UnicodeString1
,
527 /* Anything else ?? */
536 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
538 BOOLEAN ReturnRecognizedPartitions
,
539 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
542 IO_STATUS_BLOCK StatusBlock
;
543 ULARGE_INTEGER PartitionOffset
;
544 ULARGE_INTEGER nextPartitionOffset
;
545 ULARGE_INTEGER containerOffset
;
549 PPARTITION_TABLE PartitionTable
;
550 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
554 BOOLEAN ExtendedFound
= FALSE
;
556 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
559 ReturnRecognizedPartitions
,
562 *PartitionBuffer
= NULL
;
564 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
566 if (SectorBuffer
== NULL
)
568 return STATUS_INSUFFICIENT_RESOURCES
;
571 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
573 if (LayoutBuffer
== NULL
)
575 ExFreePool (SectorBuffer
);
576 return STATUS_INSUFFICIENT_RESOURCES
;
579 RtlZeroMemory(LayoutBuffer
,
582 PartitionOffset
.QuadPart
= 0;
583 containerOffset
.QuadPart
= 0;
587 KeInitializeEvent(&Event
,
591 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
593 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
597 (PLARGE_INTEGER
)&PartitionOffset
,
600 Status
= IoCallDriver(DeviceObject
,
602 if (Status
== STATUS_PENDING
)
604 KeWaitForSingleObject(&Event
,
609 Status
= StatusBlock
.Status
;
612 if (!NT_SUCCESS(Status
))
614 DbgPrint("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
616 ExFreePool(SectorBuffer
);
617 ExFreePool(LayoutBuffer
);
621 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
623 /* check the boot sector id */
624 DPRINT("Magic %x\n", PartitionTable
->Magic
);
625 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
627 DbgPrint("Invalid partition table magic\n");
628 ExFreePool(SectorBuffer
);
629 *PartitionBuffer
= LayoutBuffer
;
630 return STATUS_SUCCESS
;
634 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
636 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
638 PartitionTable
->Partition
[i
].BootFlags
,
639 PartitionTable
->Partition
[i
].PartitionType
,
640 PartitionTable
->Partition
[i
].StartingHead
,
641 PartitionTable
->Partition
[i
].StartingSector
,
642 PartitionTable
->Partition
[i
].StartingCylinder
,
643 PartitionTable
->Partition
[i
].EndingHead
,
644 PartitionTable
->Partition
[i
].EndingSector
,
645 PartitionTable
->Partition
[i
].EndingCylinder
,
646 PartitionTable
->Partition
[i
].StartingBlock
,
647 PartitionTable
->Partition
[i
].SectorCount
);
651 if (ExtendedFound
== FALSE
);
653 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
656 ExtendedFound
= FALSE
;
658 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
660 if ((ReturnRecognizedPartitions
== FALSE
) ||
661 ((ReturnRecognizedPartitions
== TRUE
) &&
662 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
664 /* handle normal partition */
665 DPRINT("Partition %u: Normal Partition\n", i
);
666 Count
= LayoutBuffer
->PartitionCount
;
667 DPRINT("Logical Partition %u\n", Count
);
668 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
670 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
672 else if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
674 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
675 (ULONGLONG
)PartitionOffset
.QuadPart
;
679 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
680 (ULONGLONG
)PartitionOffset
.QuadPart
+
681 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
683 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
684 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
685 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
687 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
689 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
694 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
697 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
698 PartitionTable
->Partition
[i
].PartitionType
;
699 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
700 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
701 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
702 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
703 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
705 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
707 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
708 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
709 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
710 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
711 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
713 LayoutBuffer
->PartitionCount
++;
717 if (IsNormalPartition(PartitionTable
->Partition
[i
].PartitionType
))
719 PartitionOffset
.QuadPart
= (ULONGLONG
)PartitionOffset
.QuadPart
+
720 (((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
+
721 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
)* (ULONGLONG
)SectorSize
);
725 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
727 ExtendedFound
= TRUE
;
728 if ((ULONGLONG
) containerOffset
.QuadPart
== (ULONGLONG
) 0)
730 containerOffset
= PartitionOffset
;
732 nextPartitionOffset
.QuadPart
= (ULONGLONG
) containerOffset
.QuadPart
+
733 (ULONGLONG
) PartitionTable
->Partition
[i
].StartingBlock
*
734 (ULONGLONG
) SectorSize
;
737 PartitionOffset
= nextPartitionOffset
;
739 while (ExtendedFound
== TRUE
);
741 *PartitionBuffer
= LayoutBuffer
;
742 ExFreePool(SectorBuffer
);
744 return STATUS_SUCCESS
;
748 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
750 IN ULONG PartitionNumber
,
751 IN ULONG PartitionType
)
753 return STATUS_NOT_IMPLEMENTED
;
758 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
760 IN ULONG SectorsPerTrack
,
761 IN ULONG NumberOfHeads
,
762 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
764 return STATUS_NOT_IMPLEMENTED
;