1 /* $Id: xhaldrv.c,v 1.10 2001/06/08 15:11:04 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) \
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)
46 typedef struct _PARTITION
48 unsigned char BootFlags
;
49 unsigned char StartingHead
;
50 unsigned char StartingSector
;
51 unsigned char StartingCylinder
;
52 unsigned char PartitionType
;
53 unsigned char EndingHead
;
54 unsigned char EndingSector
;
55 unsigned char EndingCylinder
;
56 unsigned int StartingBlock
;
57 unsigned int SectorCount
;
58 } PARTITION
, *PPARTITION
;
60 typedef struct _PARTITION_TABLE
62 PARTITION Partition
[PARTITION_TBL_SIZE
];
64 } PARTITION_TABLE
, *PPARTITION_TABLE
;
66 /* FUNCTIONS *****************************************************************/
69 xHalpQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
70 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
72 IO_STATUS_BLOCK StatusBlock
;
73 DISK_GEOMETRY DiskGeometry
;
74 PDEVICE_OBJECT DeviceObject
= NULL
;
75 PFILE_OBJECT FileObject
;
80 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
84 /* Get the drives sector size */
85 Status
= IoGetDeviceObjectPointer(DeviceName
,
89 if (!NT_SUCCESS(Status
))
91 DPRINT("Status %x\n",Status
);
95 KeInitializeEvent(&Event
,
99 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
104 sizeof(DISK_GEOMETRY
),
110 ObDereferenceObject(FileObject
);
111 return STATUS_INSUFFICIENT_RESOURCES
;
114 Status
= IoCallDriver(DeviceObject
,
116 if (Status
== STATUS_PENDING
)
118 KeWaitForSingleObject(&Event
,
123 Status
= StatusBlock
.Status
;
125 if (!NT_SUCCESS(Status
))
127 ObDereferenceObject(FileObject
);
131 DPRINT("DiskGeometry.BytesPerSector: %d\n",
132 DiskGeometry
.BytesPerSector
);
134 /* read the partition table */
135 Status
= IoReadPartitionTable(DeviceObject
,
136 DiskGeometry
.BytesPerSector
,
140 ObDereferenceObject(FileObject
);
147 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
149 IN ULONG MBRTypeIdentifier
,
153 IO_STATUS_BLOCK StatusBlock
;
154 LARGE_INTEGER Offset
;
159 DPRINT("xHalExamineMBR()\n");
162 if (SectorSize
< 512)
164 if (SectorSize
> 4096)
167 LocalBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
169 if (LocalBuffer
== NULL
)
172 KeInitializeEvent(&Event
,
178 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
186 Status
= IoCallDriver(DeviceObject
,
188 if (Status
== STATUS_PENDING
)
190 KeWaitForSingleObject(&Event
,
195 Status
= StatusBlock
.Status
;
198 if (!NT_SUCCESS(Status
))
200 DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
202 ExFreePool(LocalBuffer
);
206 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
208 DPRINT("xHalExamineMBR: invalid MBR signature\n");
209 ExFreePool(LocalBuffer
);
213 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
215 DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
216 ExFreePool(LocalBuffer
);
220 *Buffer
= (PVOID
)LocalBuffer
;
225 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
226 IN OUT PULONG DriveMap
,
227 IN ULONG DriveNumber
)
229 WCHAR DriveNameBuffer
[8];
230 UNICODE_STRING DriveName
;
233 DPRINT("HalpAssignDrive()\n");
235 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
237 /* force assignment */
238 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
240 DbgPrint("Drive letter already used!\n");
246 /* automatic assignment */
247 DriveNumber
= AUTO_DRIVE
;
249 for (i
= 2; i
< 24; i
++)
251 if ((*DriveMap
& (1 << i
)) == 0)
258 if (DriveNumber
== AUTO_DRIVE
)
260 DbgPrint("No drive letter available!\n");
265 DPRINT("DriveNumber %d\n", DriveNumber
);
267 /* set bit in drive map */
268 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
270 /* build drive name */
271 swprintf(DriveNameBuffer
,
274 RtlInitUnicodeString(&DriveName
,
277 DPRINT(" %wZ ==> %wZ\n",
281 /* create symbolic link */
282 IoCreateSymbolicLink(&DriveName
,
288 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
289 IN PSTRING NtDeviceName
,
290 OUT PUCHAR NtSystemPath
,
291 OUT PSTRING NtSystemPathString
)
293 PDRIVE_LAYOUT_INFORMATION LayoutInfo
;
294 PCONFIGURATION_INFORMATION ConfigInfo
;
295 OBJECT_ATTRIBUTES ObjectAttributes
;
296 IO_STATUS_BLOCK StatusBlock
;
297 UNICODE_STRING UnicodeString1
;
298 UNICODE_STRING UnicodeString2
;
307 DPRINT("xHalIoAssignDriveLetters()\n");
309 ConfigInfo
= IoGetConfigurationInformation ();
311 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
313 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
316 /* Create PhysicalDrive links */
317 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
318 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
321 L
"\\Device\\Harddisk%d\\Partition0",
323 RtlInitUnicodeString(&UnicodeString1
,
326 InitializeObjectAttributes(&ObjectAttributes
,
332 Status
= NtOpenFile(&FileHandle
,
337 FILE_SYNCHRONOUS_IO_NONALERT
);
338 if (NT_SUCCESS(Status
))
343 L
"\\??\\PhysicalDrive%d",
345 RtlInitUnicodeString(&UnicodeString2
,
348 DPRINT("Creating link: %S ==> %S\n",
352 IoCreateSymbolicLink(&UnicodeString2
,
357 /* Assign pre-assigned (registry) partitions */
359 /* Assign bootable partitions */
360 DPRINT("Assigning bootable partitions:\n");
361 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
364 L
"\\Device\\Harddisk%d\\Partition0",
366 RtlInitUnicodeString(&UnicodeString1
,
369 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
371 if (!NT_SUCCESS(Status
))
373 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
378 DPRINT("Logical partitions: %d\n",
379 LayoutInfo
->PartitionCount
);
381 /* search for bootable partitions */
382 for (j
= 0; j
< LayoutInfo
->PartitionCount
; j
++)
384 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
386 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
387 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
388 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
389 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
390 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
392 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
393 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
396 L
"\\Device\\Harddisk%d\\Partition%d",
398 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
399 RtlInitUnicodeString(&UnicodeString2
,
402 DPRINT(" %wZ\n", &UnicodeString2
);
405 HalpAssignDrive(&UnicodeString2
,
411 ExFreePool (LayoutInfo
);
414 /* Assign remaining primary partitions */
415 DPRINT("Assigning primary partitions:\n");
416 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
419 L
"\\Device\\Harddisk%d\\Partition0",
421 RtlInitUnicodeString(&UnicodeString1
,
424 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
426 if (!NT_SUCCESS(Status
))
428 DbgPrint("xHalpQueryDriveLayout(%wZ) failed (Status = 0x%lx)\n",
434 DPRINT("Logical partitions: %d\n",
435 LayoutInfo
->PartitionCount
);
437 /* search for primary (non-bootable) partitions */
438 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
440 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
442 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
443 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
444 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
445 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
446 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
448 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== FALSE
) &&
449 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
452 L
"\\Device\\Harddisk%d\\Partition%d",
454 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
455 RtlInitUnicodeString(&UnicodeString2
,
461 HalpAssignDrive(&UnicodeString2
,
467 ExFreePool(LayoutInfo
);
470 /* Assign extended (logical) partitions */
471 DPRINT("Assigning extended (logical) partitions:\n");
472 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
475 L
"\\Device\\Harddisk%d\\Partition0",
477 RtlInitUnicodeString(&UnicodeString1
,
480 Status
= xHalpQueryDriveLayout(&UnicodeString1
,
482 if (!NT_SUCCESS(Status
))
484 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
489 DPRINT("Logical partitions: %d\n",
490 LayoutInfo
->PartitionCount
);
492 /* search for extended partitions */
493 for (j
= PARTITION_TBL_SIZE
; j
< LayoutInfo
->PartitionCount
; j
++)
495 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
497 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
498 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
499 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
500 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
501 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
503 if (IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
) &&
504 (LayoutInfo
->PartitionEntry
[j
].PartitionNumber
!= 0))
507 L
"\\Device\\Harddisk%d\\Partition%d",
509 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
510 RtlInitUnicodeString(&UnicodeString2
,
516 HalpAssignDrive(&UnicodeString2
,
522 ExFreePool(LayoutInfo
);
525 /* Assign floppy drives */
526 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
527 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
530 L
"\\Device\\Floppy%d",
532 RtlInitUnicodeString(&UnicodeString1
,
535 /* assign drive letters A: or B: or first free drive letter */
538 HalpAssignDrive(&UnicodeString1
,
540 (i
< 2) ? i
: AUTO_DRIVE
);
543 /* Assign cdrom drives */
544 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
545 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
548 L
"\\Device\\Cdrom%d",
550 RtlInitUnicodeString(&UnicodeString1
,
553 /* assign first free drive letter */
554 DPRINT(" %wZ\n", &UnicodeString1
);
555 HalpAssignDrive(&UnicodeString1
,
560 /* Anything else ?? */
569 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject
,
571 BOOLEAN ReturnRecognizedPartitions
,
572 PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
575 IO_STATUS_BLOCK StatusBlock
;
576 ULARGE_INTEGER PartitionOffset
;
580 PPARTITION_TABLE PartitionTable
;
581 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
585 BOOLEAN ExtendedFound
= FALSE
;
587 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
590 ReturnRecognizedPartitions
,
593 *PartitionBuffer
= NULL
;
595 SectorBuffer
= (PUCHAR
)ExAllocatePool(PagedPool
,
597 if (SectorBuffer
== NULL
)
599 return STATUS_INSUFFICIENT_RESOURCES
;
602 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool(NonPagedPool
,
604 if (LayoutBuffer
== NULL
)
606 ExFreePool (SectorBuffer
);
607 return STATUS_INSUFFICIENT_RESOURCES
;
610 RtlZeroMemory(LayoutBuffer
,
613 PartitionOffset
.QuadPart
= 0;
617 KeInitializeEvent(&Event
,
621 DPRINT("PartitionOffset: %I64u\n", PartitionOffset
.QuadPart
/ SectorSize
);
623 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
627 (PLARGE_INTEGER
)&PartitionOffset
,
630 Status
= IoCallDriver(DeviceObject
,
632 if (Status
== STATUS_PENDING
)
634 KeWaitForSingleObject(&Event
,
639 Status
= StatusBlock
.Status
;
642 if (!NT_SUCCESS(Status
))
644 DPRINT("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
646 ExFreePool(SectorBuffer
);
647 ExFreePool(LayoutBuffer
);
651 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
653 /* check the boot sector id */
654 DPRINT("Magic %x\n", PartitionTable
->Magic
);
655 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
657 DPRINT("Invalid partition table magic\n");
658 ExFreePool(SectorBuffer
);
659 *PartitionBuffer
= LayoutBuffer
;
660 return STATUS_SUCCESS
;
664 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
666 DPRINT(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
668 PartitionTable
->Partition
[i
].BootFlags
,
669 PartitionTable
->Partition
[i
].PartitionType
,
670 PartitionTable
->Partition
[i
].StartingHead
,
671 PartitionTable
->Partition
[i
].StartingSector
,
672 PartitionTable
->Partition
[i
].StartingCylinder
,
673 PartitionTable
->Partition
[i
].EndingHead
,
674 PartitionTable
->Partition
[i
].EndingSector
,
675 PartitionTable
->Partition
[i
].EndingCylinder
,
676 PartitionTable
->Partition
[i
].StartingBlock
,
677 PartitionTable
->Partition
[i
].SectorCount
);
681 if (ExtendedFound
== FALSE
);
683 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
686 ExtendedFound
= FALSE
;
688 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
690 if ((ReturnRecognizedPartitions
== FALSE
) ||
691 ((ReturnRecognizedPartitions
== TRUE
) &&
692 IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
)))
694 /* handle normal partition */
695 DPRINT("Partition %u: Normal Partition\n", i
);
696 Count
= LayoutBuffer
->PartitionCount
;
697 DPRINT("Logical Partition %u\n", Count
);
698 if (PartitionTable
->Partition
[i
].StartingBlock
== 0)
700 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
702 else if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
704 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
705 (ULONGLONG
)PartitionOffset
.QuadPart
;
709 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
710 (ULONGLONG
)PartitionOffset
.QuadPart
+
711 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
713 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
714 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
715 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
717 if (IsRecognizedPartition(PartitionTable
->Partition
[i
].PartitionType
))
719 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
724 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
727 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
728 PartitionTable
->Partition
[i
].PartitionType
;
729 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
730 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
731 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
732 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
733 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
735 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
737 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
738 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
739 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
740 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
741 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
743 LayoutBuffer
->PartitionCount
++;
746 if (IsUsablePartition(PartitionTable
->Partition
[i
].PartitionType
))
748 PartitionOffset
.QuadPart
= (ULONGLONG
)PartitionOffset
.QuadPart
+
749 (((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
+
750 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
)* (ULONGLONG
)SectorSize
);
753 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
755 ExtendedFound
= TRUE
;
759 while (ExtendedFound
== TRUE
);
761 *PartitionBuffer
= LayoutBuffer
;
762 ExFreePool(SectorBuffer
);
764 return STATUS_SUCCESS
;
769 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
771 IN ULONG PartitionNumber
,
772 IN ULONG PartitionType
)
774 return STATUS_NOT_IMPLEMENTED
;
779 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
781 IN ULONG SectorsPerTrack
,
782 IN ULONG NumberOfHeads
,
783 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
785 return STATUS_NOT_IMPLEMENTED
;