1 /* $Id: xhaldrv.c,v 1.4 2000/08/22 14:10:59 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)
14 * - Check/fix 'StartingOffset' and 'PartitionLength' in
15 * xHalIoReadPartitionTable().
16 * - Fix 'ReturnRecognizesPartitions' in xHalIoReadPartitionTable().
17 * - Read disk signature in xHalIoReadPartitionTable().
18 * - Build correct system path from nt device name or arc name.
19 * For example: \Device\Harddisk0\Partition1\reactos ==> C:\reactos
20 * Or: multi(0)disk(0)rdisk(0)partition(1)\reactos ==> C:\reactos
23 /* INCLUDES *****************************************************************/
25 #include <ddk/ntddk.h>
26 #include <internal/xhal.h>
29 #include <internal/debug.h>
31 /* LOCAL MACROS and TYPES ***************************************************/
33 #define AUTO_DRIVE ((ULONG)-1)
35 #define PARTITION_MAGIC 0xaa55
36 #define PART_MAGIC_OFFSET 0x01fe
37 #define PARTITION_OFFSET 0x01be
38 #define PARTITION_TBL_SIZE 4
41 #define PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \
42 (scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2)))
43 #define PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \
44 (s) = (lba) % (scnt) + 1, \
46 (h) = (lba) % (hcnt), \
49 (s) |= ((lba) >> 2) & 0xc0)
52 #define IsUsablePartition(P) \
54 (P) != PTDosExtended && \
55 (P) != PTWin95ExtendedLBA)
58 typedef struct _PARTITION
60 unsigned char BootFlags
;
61 unsigned char StartingHead
;
62 unsigned char StartingSector
;
63 unsigned char StartingCylinder
;
64 unsigned char PartitionType
;
65 unsigned char EndingHead
;
66 unsigned char EndingSector
;
67 unsigned char EndingCylinder
;
68 unsigned int StartingBlock
;
69 unsigned int SectorCount
;
70 } PARTITION
, *PPARTITION
;
72 typedef struct _PARTITION_TABLE
74 PARTITION Partition
[PARTITION_TBL_SIZE
];
76 } PARTITION_TABLE
, *PPARTITION_TABLE
;
78 /* FUNCTIONS *****************************************************************/
81 xHalpQueryDriveLayout (
82 IN PUNICODE_STRING DeviceName
,
83 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
86 IO_STATUS_BLOCK StatusBlock
;
87 DISK_GEOMETRY DiskGeometry
;
88 PDEVICE_OBJECT DeviceObject
= NULL
;
89 PFILE_OBJECT FileObject
;
94 DPRINT ("xHalpQueryDriveLayout %wZ %p\n",
99 * Get the drives sector size
101 Status
= IoGetDeviceObjectPointer (DeviceName
,
105 if (!NT_SUCCESS(Status
))
107 DPRINT ("Status %x\n",Status
);
111 KeInitializeEvent (&Event
,
115 Irp
= IoBuildDeviceIoControlRequest (IOCTL_DISK_GET_DRIVE_GEOMETRY
,
120 sizeof(DISK_GEOMETRY
),
126 ObDereferenceObject (FileObject
);
127 return STATUS_INSUFFICIENT_RESOURCES
;
130 Status
= IoCallDriver(DeviceObject
, Irp
);
131 if (Status
== STATUS_PENDING
)
133 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
134 Status
= StatusBlock
.Status
;
136 if (!NT_SUCCESS(Status
))
138 ObDereferenceObject (FileObject
);
142 DPRINT("DiskGeometry.BytesPerSector: %d\n",
143 DiskGeometry
.BytesPerSector
);
145 /* read the partition table */
146 Status
= IoReadPartitionTable (DeviceObject
,
147 DiskGeometry
.BytesPerSector
,
151 ObDereferenceObject (FileObject
);
160 IN PDEVICE_OBJECT DeviceObject
,
162 IN ULONG MBRTypeIdentifier
,
167 IO_STATUS_BLOCK StatusBlock
;
168 LARGE_INTEGER Offset
;
173 DPRINT ("xHalExamineMBR()\n");
176 if (SectorSize
< 512)
178 if (SectorSize
> 4096)
181 LocalBuffer
= (PUCHAR
)ExAllocatePool (PagedPool
,
183 if (LocalBuffer
== NULL
)
186 KeInitializeEvent (&Event
,
192 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_READ
,
200 Status
= IoCallDriver (DeviceObject
,
202 if (Status
== STATUS_PENDING
)
204 KeWaitForSingleObject (&Event
,
209 Status
= StatusBlock
.Status
;
212 if (!NT_SUCCESS(Status
))
214 DPRINT ("xHalExamineMBR failed (Status = 0x%08lx)\n",
216 ExFreePool (LocalBuffer
);
220 if (LocalBuffer
[0x1FE] != 0x55 || LocalBuffer
[0x1FF] != 0xAA)
222 DPRINT ("xHalExamineMBR: invalid MBR signature\n");
223 ExFreePool (LocalBuffer
);
227 if (LocalBuffer
[0x1C2] != MBRTypeIdentifier
)
229 DPRINT ("xHalExamineMBR: invalid MBRTypeIdentifier\n");
230 ExFreePool (LocalBuffer
);
234 *Buffer
= (PVOID
)LocalBuffer
;
239 IN PUNICODE_STRING PartitionName
,
240 IN OUT PULONG DriveMap
,
244 WCHAR DriveNameBuffer
[8];
245 UNICODE_STRING DriveName
;
248 DPRINT("HalpAssignDrive()\n");
250 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 24))
252 /* force assignment */
253 if ((*DriveMap
& (1 << DriveNumber
)) != 0)
255 DbgPrint("Drive letter already used!\n");
261 /* automatic assignment */
262 DriveNumber
= AUTO_DRIVE
;
264 for (i
= 2; i
< 24; i
++)
266 if ((*DriveMap
& (1 << i
)) == 0)
273 if (DriveNumber
== AUTO_DRIVE
)
275 DbgPrint("No drive letter available!\n");
280 DPRINT("DriveNumber %d\n", DriveNumber
);
282 /* set bit in drive map */
283 *DriveMap
= *DriveMap
| (1 << DriveNumber
);
285 /* build drive name */
286 swprintf (DriveNameBuffer
,
289 RtlInitUnicodeString (&DriveName
,
292 DPRINT1(" %wZ ==> %wZ\n",
296 /* create symbolic link */
297 IoCreateSymbolicLink (&DriveName
,
304 xHalIoAssignDriveLetters (
305 IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
306 IN PSTRING NtDeviceName
,
307 OUT PUCHAR NtSystemPath
,
308 OUT PSTRING NtSystemPathString
311 PDRIVE_LAYOUT_INFORMATION LayoutInfo
;
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
))
358 NtClose (FileHandle
);
361 L
"\\??\\PhysicalDrive%d",
363 RtlInitUnicodeString (&UnicodeString2
,
366 DPRINT1("Creating link: %S ==> %S\n",
370 IoCreateSymbolicLink (&UnicodeString2
,
375 /* Assign pre-assigned (registry) partitions */
377 /* Assign bootable partitions */
378 DPRINT("Assigning bootable partitions:\n");
379 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
382 L
"\\Device\\Harddisk%d\\Partition0",
384 RtlInitUnicodeString (&UnicodeString1
,
387 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
389 if (!NT_SUCCESS(Status
))
391 DPRINT1("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
396 DPRINT("Logical partitions: %d\n",
397 LayoutInfo
->PartitionCount
);
399 /* search for bootable partitions */
400 for (j
= 0; j
< LayoutInfo
->PartitionCount
; j
++)
402 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
404 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
405 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
406 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
407 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
408 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
410 if (LayoutInfo
->PartitionEntry
[j
].BootIndicator
)
413 L
"\\Device\\Harddisk%d\\Partition%d",
415 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
416 RtlInitUnicodeString (&UnicodeString2
,
419 DPRINT(" %wZ\n", &UnicodeString2
);
422 HalpAssignDrive (&UnicodeString2
,
428 ExFreePool (LayoutInfo
);
431 /* Assign remaining primary partitions */
432 DPRINT("Assigning primary partitions:\n");
433 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
436 L
"\\Device\\Harddisk%d\\Partition0",
438 RtlInitUnicodeString (&UnicodeString1
,
441 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
443 if (!NT_SUCCESS(Status
))
445 DPRINT1("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
450 DPRINT("Logical partitions: %d\n",
451 LayoutInfo
->PartitionCount
);
453 /* search for primary (non-bootable) partitions */
454 for (j
= 0; j
< PARTITION_TBL_SIZE
; j
++)
456 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
458 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
459 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
460 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
461 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
462 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
464 if ((LayoutInfo
->PartitionEntry
[j
].BootIndicator
== FALSE
) &&
465 IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
))
468 L
"\\Device\\Harddisk%d\\Partition%d",
470 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
471 RtlInitUnicodeString (&UnicodeString2
,
475 DPRINT(" %wZ\n", &UnicodeString2
);
476 HalpAssignDrive (&UnicodeString2
, &DriveMap
, AUTO_DRIVE
);
480 ExFreePool (LayoutInfo
);
483 /* Assign extended (logical) partitions */
484 DPRINT("Assigning extended (logical) partitions:\n");
485 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
488 L
"\\Device\\Harddisk%d\\Partition0",
490 RtlInitUnicodeString (&UnicodeString1
,
493 Status
= xHalpQueryDriveLayout (&UnicodeString1
,
495 if (!NT_SUCCESS(Status
))
497 DPRINT1("xHalpQueryDriveLayout() failed (Status = 0x%lx)\n",
502 DPRINT("Logical partitions: %d\n",
503 LayoutInfo
->PartitionCount
);
505 /* search for extended partitions */
506 for (j
= PARTITION_TBL_SIZE
; j
< LayoutInfo
->PartitionCount
; j
++)
508 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%lu count:%lu\n",
510 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
,
511 LayoutInfo
->PartitionEntry
[j
].BootIndicator
,
512 LayoutInfo
->PartitionEntry
[j
].PartitionType
,
513 LayoutInfo
->PartitionEntry
[j
].StartingOffset
.u
.LowPart
,
514 LayoutInfo
->PartitionEntry
[j
].PartitionLength
.u
.LowPart
);
516 if (IsUsablePartition(LayoutInfo
->PartitionEntry
[j
].PartitionType
) &&
517 (LayoutInfo
->PartitionEntry
[j
].PartitionNumber
!= 0))
520 L
"\\Device\\Harddisk%d\\Partition%d",
522 LayoutInfo
->PartitionEntry
[j
].PartitionNumber
);
523 RtlInitUnicodeString (&UnicodeString2
,
527 DPRINT(" %wZ\n", &UnicodeString2
);
528 HalpAssignDrive (&UnicodeString2
, &DriveMap
, AUTO_DRIVE
);
532 ExFreePool (LayoutInfo
);
535 /* Assign floppy drives */
536 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
537 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
540 L
"\\Device\\Floppy%d",
542 RtlInitUnicodeString (&UnicodeString1
,
545 /* assign drive letters A: or B: or first free drive letter */
546 DPRINT(" %wZ\n", &UnicodeString1
);
547 HalpAssignDrive (&UnicodeString1
,
549 (i
< 2) ? i
: AUTO_DRIVE
);
552 /* Assign cdrom drives */
553 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CDRomCount
);
554 for (i
= 0; i
< ConfigInfo
->CDRomCount
; i
++)
557 L
"\\Device\\Cdrom%d",
559 RtlInitUnicodeString (&UnicodeString1
,
562 /* assign first free drive letter */
563 DPRINT(" %wZ\n", &UnicodeString1
);
564 HalpAssignDrive (&UnicodeString1
,
569 /* Anything else ?? */
572 ExFreePool (Buffer2
);
573 ExFreePool (Buffer1
);
579 xHalIoReadPartitionTable (
580 PDEVICE_OBJECT DeviceObject
,
582 BOOLEAN ReturnRecognizedPartitions
,
583 PDRIVE_LAYOUT_INFORMATION
* PartitionBuffer
587 IO_STATUS_BLOCK StatusBlock
;
588 ULARGE_INTEGER Offset
;
592 PPARTITION_TABLE PartitionTable
;
593 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
597 BOOLEAN ExtendedFound
= FALSE
;
599 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
602 ReturnRecognizedPartitions
,
605 *PartitionBuffer
= NULL
;
607 SectorBuffer
= (PUCHAR
)ExAllocatePool (PagedPool
,
609 if (SectorBuffer
== NULL
)
611 return STATUS_INSUFFICIENT_RESOURCES
;
614 LayoutBuffer
= (PDRIVE_LAYOUT_INFORMATION
)ExAllocatePool (PagedPool
,
616 if (LayoutBuffer
== NULL
)
618 ExFreePool (SectorBuffer
);
619 return STATUS_INSUFFICIENT_RESOURCES
;
622 RtlZeroMemory (LayoutBuffer
, 0x1000);
628 KeInitializeEvent (&Event
,
632 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_READ
,
636 (PLARGE_INTEGER
)&Offset
,
640 Status
= IoCallDriver (DeviceObject
,
642 if (Status
== STATUS_PENDING
)
644 KeWaitForSingleObject (&Event
,
649 Status
= StatusBlock
.Status
;
652 if (!NT_SUCCESS(Status
))
654 DPRINT1("xHalIoReadPartitonTable failed (Status = 0x%08lx)\n",
656 ExFreePool (SectorBuffer
);
657 ExFreePool (LayoutBuffer
);
661 PartitionTable
= (PPARTITION_TABLE
)(SectorBuffer
+PARTITION_OFFSET
);
663 /* check the boot sector id */
664 DPRINT("Magic %x\n", PartitionTable
->Magic
);
665 if (PartitionTable
->Magic
!= PARTITION_MAGIC
)
667 DPRINT1("Invalid partition table magic\n");
668 ExFreePool (SectorBuffer
);
669 // ExFreePool (LayoutBuffer);
670 // return STATUS_UNSUCCESSFUL;
672 *PartitionBuffer
= LayoutBuffer
;
673 return STATUS_SUCCESS
;
677 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
679 DPRINT(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
681 PartitionTable
->Partition
[i
].BootFlags
,
682 PartitionTable
->Partition
[i
].PartitionType
,
683 PartitionTable
->Partition
[i
].StartingHead
,
684 PartitionTable
->Partition
[i
].StartingSector
,
685 PartitionTable
->Partition
[i
].StartingCylinder
,
686 PartitionTable
->Partition
[i
].EndingHead
,
687 PartitionTable
->Partition
[i
].EndingSector
,
688 PartitionTable
->Partition
[i
].EndingCylinder
,
689 PartitionTable
->Partition
[i
].StartingBlock
,
690 PartitionTable
->Partition
[i
].SectorCount
);
694 /* FIXME: Set the correct value */
695 if (ExtendedFound
== FALSE
);
697 LayoutBuffer
->Signature
= 0xdeadbeef;
700 ExtendedFound
= FALSE
;
701 for (i
= 0; i
< PARTITION_TBL_SIZE
; i
++)
703 /* handle normal partition */
704 DPRINT("Partition %u: Normal Partition\n", i
);
705 Count
= LayoutBuffer
->PartitionCount
;
706 DPRINT("Logical Partition %u\n", Count
);
708 if (PartitionTable
->Partition
[i
].StartingBlock
)
710 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
=
711 (ULONGLONG
)Offset
.QuadPart
+
712 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
716 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
= 0;
718 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
=
719 (ULONGLONG
)PartitionTable
->Partition
[i
].SectorCount
* (ULONGLONG
)SectorSize
;
720 LayoutBuffer
->PartitionEntry
[Count
].HiddenSectors
= 0;
722 if (IsUsablePartition(PartitionTable
->Partition
[i
].PartitionType
))
724 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= Number
;
729 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
= 0;
732 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
=
733 PartitionTable
->Partition
[i
].PartitionType
;
734 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
=
735 (PartitionTable
->Partition
[i
].BootFlags
& 0x80)?TRUE
:FALSE
;
736 LayoutBuffer
->PartitionEntry
[Count
].RecognizedPartition
=
737 IsRecognizedPartition (PartitionTable
->Partition
[i
].PartitionType
);
738 LayoutBuffer
->PartitionEntry
[Count
].RewritePartition
= FALSE
;
740 DPRINT(" Offset: 0x%I64x", Offset
.QuadPart
);
742 if (IsExtendedPartition(PartitionTable
->Partition
[i
].PartitionType
))
744 Offset
.QuadPart
= (ULONGLONG
)Offset
.QuadPart
+
745 ((ULONGLONG
)PartitionTable
->Partition
[i
].StartingBlock
* (ULONGLONG
)SectorSize
);
746 ExtendedFound
= TRUE
;
749 DPRINT(" Offset: 0x%I64x\n", Offset
.QuadPart
);
751 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
753 LayoutBuffer
->PartitionEntry
[Count
].PartitionNumber
,
754 LayoutBuffer
->PartitionEntry
[Count
].BootIndicator
,
755 LayoutBuffer
->PartitionEntry
[Count
].PartitionType
,
756 LayoutBuffer
->PartitionEntry
[Count
].StartingOffset
.QuadPart
,
757 LayoutBuffer
->PartitionEntry
[Count
].PartitionLength
.QuadPart
);
759 LayoutBuffer
->PartitionCount
++;
762 while (ExtendedFound
== TRUE
);
764 *PartitionBuffer
= LayoutBuffer
;
765 ExFreePool (SectorBuffer
);
767 return STATUS_SUCCESS
;