1 /* $Id: xhaldrv.c,v 1.7 2000/08/25 15:55:02 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
30 #define IsUsablePartition(P) \
32 (P) != PTDosExtended && \
33 (P) != PTWin95ExtendedLBA)
36 typedef struct _PARTITION
38 unsigned char BootFlags
;
39 unsigned char StartingHead
;
40 unsigned char StartingSector
;
41 unsigned char StartingCylinder
;
42 unsigned char PartitionType
;
43 unsigned char EndingHead
;
44 unsigned char EndingSector
;
45 unsigned char EndingCylinder
;
46 unsigned int StartingBlock
;
47 unsigned int SectorCount
;
48 } PARTITION
, *PPARTITION
;
50 typedef struct _PARTITION_TABLE
52 PARTITION Partition
[PARTITION_TBL_SIZE
];
54 } PARTITION_TABLE
, *PPARTITION_TABLE
;
56 /* FUNCTIONS *****************************************************************/
59 xHalpQueryDriveLayout (
60 IN PUNICODE_STRING DeviceName
,
61 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
64 IO_STATUS_BLOCK StatusBlock
;
65 DISK_GEOMETRY DiskGeometry
;
66 PDEVICE_OBJECT DeviceObject
= NULL
;
67 PFILE_OBJECT FileObject
;
72 DPRINT ("xHalpQueryDriveLayout %wZ %p\n",
77 * 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
, Irp
);
109 if (Status
== STATUS_PENDING
)
111 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
112 Status
= StatusBlock
.Status
;
114 if (!NT_SUCCESS(Status
))
116 ObDereferenceObject (FileObject
);
120 DPRINT("DiskGeometry.BytesPerSector: %d\n",
121 DiskGeometry
.BytesPerSector
);
123 /* read the partition table */
124 Status
= IoReadPartitionTable (DeviceObject
,
125 DiskGeometry
.BytesPerSector
,
129 ObDereferenceObject (FileObject
);
138 IN PDEVICE_OBJECT DeviceObject
,
140 IN ULONG MBRTypeIdentifier
,
145 IO_STATUS_BLOCK StatusBlock
;
146 LARGE_INTEGER Offset
;
151 DPRINT ("xHalExamineMBR()\n");
154 if (SectorSize
< 512)
156 if (SectorSize
> 4096)
159 LocalBuffer
= (PUCHAR
)ExAllocatePool (PagedPool
,
161 if (LocalBuffer
== NULL
)
164 KeInitializeEvent (&Event
,
170 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_READ
,
178 Status
= IoCallDriver (DeviceObject
,
180 if (Status
== STATUS_PENDING
)
182 KeWaitForSingleObject (&Event
,
187 Status
= StatusBlock
.Status
;
190 if (!NT_SUCCESS(Status
))
192 DPRINT ("xHalExamineMBR failed (Status = 0x%08lx)\n",
194 ExFreePool (LocalBuffer
);
198 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
200 DPRINT ("xHalExamineMBR: invalid MBR signature\n");
201 ExFreePool (LocalBuffer
);
205 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
207 DPRINT ("xHalExamineMBR: invalid MBRTypeIdentifier\n");
208 ExFreePool (LocalBuffer
);
212 *Buffer
= (PVOID
)LocalBuffer
;
217 IN PUNICODE_STRING PartitionName
,
218 IN OUT PULONG DriveMap
,
222 WCHAR DriveNameBuffer
[8];
223 UNICODE_STRING DriveName
;
226 DPRINT("HalpAssignDrive()\n");
228 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
230 /* force assignment */
231 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
233 DbgPrint("Drive letter already used!\n");
239 /* automatic assignment */
240 DriveNumber
= AUTO_DRIVE
;
242 for (i
= 2; i
< 24; i
++)
244 if ((*DriveMap
& (1 << i
)) == 0)
251 if (DriveNumber
== AUTO_DRIVE
)
253 DbgPrint("No drive letter available!\n");
258 DPRINT("DriveNumber %d\n", DriveNumber
);
260 /* set bit in drive map */
261 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
263 /* build drive name */
264 swprintf (DriveNameBuffer
,
267 RtlInitUnicodeString (&DriveName
,
270 DPRINT(" %wZ ==> %wZ\n",
274 /* create symbolic link */
275 IoCreateSymbolicLink (&DriveName
,
282 xHalIoAssignDriveLetters (
283 IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
284 IN PSTRING NtDeviceName
,
285 OUT PUCHAR NtSystemPath
,
286 OUT PSTRING NtSystemPathString
289 PDRIVE_LAYOUT_INFORMATION LayoutInfo
;
290 PCONFIGURATION_INFORMATION ConfigInfo
;
291 OBJECT_ATTRIBUTES ObjectAttributes
;
292 IO_STATUS_BLOCK StatusBlock
;
293 UNICODE_STRING UnicodeString1
;
294 UNICODE_STRING UnicodeString2
;
303 DPRINT("xHalIoAssignDriveLetters()\n");
305 ConfigInfo
= IoGetConfigurationInformation ();
307 Buffer1
= (PWSTR
)ExAllocatePool (PagedPool
,
309 Buffer2
= (PWSTR
)ExAllocatePool (PagedPool
,
312 /* Create PhysicalDrive links */
313 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
314 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
317 L
"\\Device\\Harddisk%d\\Partition0",
319 RtlInitUnicodeString (&UnicodeString1
,
322 InitializeObjectAttributes (&ObjectAttributes
,
328 Status
= NtOpenFile (&FileHandle
,
333 FILE_SYNCHRONOUS_IO_NONALERT
);
334 if (NT_SUCCESS(Status
))
336 NtClose (FileHandle
);
339 L
"\\??\\PhysicalDrive%d",
341 RtlInitUnicodeString (&UnicodeString2
,
344 DPRINT("Creating link: %S ==> %S\n",
348 IoCreateSymbolicLink (&UnicodeString2
,
353 /* Assign pre-assigned (registry) partitions */
355 /* Assign bootable partitions */
356 DPRINT("Assigning bootable partitions:\n");
357 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
360 L
"\\Device\\Harddisk%d\\Partition0",
362 RtlInitUnicodeString (&UnicodeString1
,
365 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
367 if (!NT_SUCCESS(Status
))
369 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
374 DPRINT("Logical partitions: %d\n",
375 LayoutInfo
->PartitionCount
);
377 /* search for bootable partitions */
378 for (j
= 0; j
< LayoutInfo
->PartitionCount
; j
++)
380 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
382 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
383 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
384 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
385 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
386 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
388 if (LayoutInfo
->PartitionEntry
[j
].BootIndicator
)
391 L
"\\Device\\Harddisk%d\\Partition%d",
393 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
394 RtlInitUnicodeString (&UnicodeString2
,
397 DPRINT(" %wZ\n", &UnicodeString2
);
400 HalpAssignDrive (&UnicodeString2
,
406 ExFreePool (LayoutInfo
);
409 /* Assign remaining primary partitions */
410 DPRINT("Assigning primary partitions:\n");
411 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
414 L
"\\Device\\Harddisk%d\\Partition0",
416 RtlInitUnicodeString (&UnicodeString1
,
419 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
421 if (!NT_SUCCESS(Status
))
423 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
428 DPRINT("Logical partitions: %d\n",
429 LayoutInfo
->PartitionCount
);
431 /* search for primary (non-bootable) partitions */
432 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
434 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
436 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
437 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
438 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
439 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
440 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
442 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== FALSE
) &&
443 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
446 L
"\\Device\\Harddisk%d\\Partition%d",
448 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
449 RtlInitUnicodeString (&UnicodeString2
,
453 DPRINT(" %wZ\n", &UnicodeString2
);
454 HalpAssignDrive (&UnicodeString2
, &DriveMap
, AUTO_DRIVE
);
458 ExFreePool (LayoutInfo
);
461 /* Assign extended (logical) partitions */
462 DPRINT("Assigning extended (logical) partitions:\n");
463 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
466 L
"\\Device\\Harddisk%d\\Partition0",
468 RtlInitUnicodeString (&UnicodeString1
,
471 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
473 if (!NT_SUCCESS(Status
))
475 DbgPrint("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
480 DPRINT("Logical partitions: %d\n",
481 LayoutInfo
->PartitionCount
);
483 /* search for extended partitions */
484 for (j
= PARTITION_TBL_SIZE
; j
< LayoutInfo
->PartitionCount
; j
++)
486 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
488 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
489 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
490 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
491 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
492 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
494 if (IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
) &&
495 (LayoutInfo
->PartitionEntry
[j
].PartitionNumber
!= 0))
498 L
"\\Device\\Harddisk%d\\Partition%d",
500 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
501 RtlInitUnicodeString (&UnicodeString2
,
505 DPRINT(" %wZ\n", &UnicodeString2
);
506 HalpAssignDrive (&UnicodeString2
, &DriveMap
, AUTO_DRIVE
);
510 ExFreePool (LayoutInfo
);
513 /* Assign floppy drives */
514 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
515 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
518 L
"\\Device\\Floppy%d",
520 RtlInitUnicodeString (&UnicodeString1
,
523 /* assign drive letters A: or B: or first free drive letter */
524 DPRINT(" %wZ\n", &UnicodeString1
);
525 HalpAssignDrive (&UnicodeString1
,
527 (i
< 2) ? i
: AUTO_DRIVE
);
530 /* Assign cdrom drives */
531 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
532 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
535 L
"\\Device\\Cdrom%d",
537 RtlInitUnicodeString (&UnicodeString1
,
540 /* assign first free drive letter */
541 DPRINT(" %wZ\n", &UnicodeString1
);
542 HalpAssignDrive (&UnicodeString1
,
547 /* Anything else ?? */
550 ExFreePool (Buffer2
);
551 ExFreePool (Buffer1
);
557 xHalIoReadPartitionTable (
558 PDEVICE_OBJECT DeviceObject
,
560 BOOLEAN ReturnRecognizedPartitions
,
561 PDRIVE_LAYOUT_INFORMATION
* PartitionBuffer
565 IO_STATUS_BLOCK StatusBlock
;
566 ULARGE_INTEGER Offset
;
570 PPARTITION_TABLE PartitionTable
;
571 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
575 BOOLEAN ExtendedFound
= FALSE
;
577 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
580 ReturnRecognizedPartitions
,
583 *PartitionBuffer
= NULL
;
585 SectorBuffer
= (PUCHAR
)ExAllocatePool (PagedPool
,
587 if (SectorBuffer
== NULL
)
589 return STATUS_INSUFFICIENT_RESOURCES
;
592 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool (NonPagedPool
,
594 if (LayoutBuffer
== NULL
)
596 ExFreePool (SectorBuffer
);
597 return STATUS_INSUFFICIENT_RESOURCES
;
600 RtlZeroMemory (LayoutBuffer
, 0x1000);
606 KeInitializeEvent (&Event
,
610 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_READ
,
614 (PLARGE_INTEGER
)&Offset
,
618 Status
= IoCallDriver (DeviceObject
,
620 if (Status
== STATUS_PENDING
)
622 KeWaitForSingleObject (&Event
,
627 Status
= StatusBlock
.Status
;
630 if (!NT_SUCCESS(Status
))
632 DPRINT1("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
634 ExFreePool (SectorBuffer
);
635 ExFreePool (LayoutBuffer
);
639 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
641 /* check the boot sector id */
642 DPRINT("Magic %x\n", PartitionTable
->Magic
);
643 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
645 DPRINT1("Invalid partition table magic\n");
646 ExFreePool (SectorBuffer
);
647 // ExFreePool (LayoutBuffer);
648 // return STATUS_UNSUCCESSFUL;
650 *PartitionBuffer
= LayoutBuffer
;
651 return STATUS_SUCCESS
;
655 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
657 DPRINT(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
659 PartitionTable
->Partition
[i
].BootFlags
,
660 PartitionTable
->Partition
[i
].PartitionType
,
661 PartitionTable
->Partition
[i
].StartingHead
,
662 PartitionTable
->Partition
[i
].StartingSector
,
663 PartitionTable
->Partition
[i
].StartingCylinder
,
664 PartitionTable
->Partition
[i
].EndingHead
,
665 PartitionTable
->Partition
[i
].EndingSector
,
666 PartitionTable
->Partition
[i
].EndingCylinder
,
667 PartitionTable
->Partition
[i
].StartingBlock
,
668 PartitionTable
->Partition
[i
].SectorCount
);
672 if (ExtendedFound
== FALSE
);
674 LayoutBuffer
->Signature
= *((PULONG
)(SectorBuffer
+ SIGNATURE_OFFSET
));
677 ExtendedFound
= FALSE
;
678 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
680 /* handle normal partition */
681 DPRINT("Partition %u: Normal Partition\n", i
);
682 Count
= LayoutBuffer
->PartitionCount
;
683 DPRINT("Logical Partition %u\n", Count
);
685 if (PartitionTable
->Partition
[i
].StartingBlock
)
687 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
688 (ULONGLONG
)Offset
.QuadPart
+
689 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
693 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
695 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
696 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
697 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
699 if (IsUsablePartition(PartitionTable
->Partition
[i
].PartitionType
))
701 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
706 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
709 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
710 PartitionTable
->Partition
[i
].PartitionType
;
711 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
712 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
713 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
714 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
715 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
717 DPRINT(" Offset: 0x%I64x", Offset
.QuadPart
);
719 if (IsUsablePartition(PartitionTable
->Partition
[i
].PartitionType
))
721 Offset
.QuadPart
= (ULONGLONG
)Offset
.QuadPart
+
722 (((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
+ (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
)* (ULONGLONG
)SectorSize
);
725 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
727 ExtendedFound
= TRUE
;
730 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
732 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
733 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
734 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
735 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
736 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
738 LayoutBuffer
->PartitionCount
++;
741 while (ExtendedFound
== TRUE
);
743 *PartitionBuffer
= LayoutBuffer
;
744 ExFreePool (SectorBuffer
);
746 return STATUS_SUCCESS
;