Fix the export of HalExamineMBR. It mustn't be aliased since we need to have it named...
[reactos.git] / reactos / ntoskrnl / io / disk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/disk.c
5 * PURPOSE: I/O Support for Hal Disk (Partition Table/MBR) Routines.
6 *
7 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* LOCAL MACROS and TYPES ***************************************************/
18
19 #define AUTO_DRIVE ((ULONG)-1)
20
21 #define PARTITION_MAGIC 0xaa55
22
23 #define PARTITION_TBL_SIZE 4
24
25 #include <pshpack1.h>
26
27 typedef struct _PARTITION
28 {
29 unsigned char BootFlags; /* bootable? 0=no, 128=yes */
30 unsigned char StartingHead; /* beginning head number */
31 unsigned char StartingSector; /* beginning sector number */
32 unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
33 unsigned char PartitionType; /* Operating System type indicator code */
34 unsigned char EndingHead; /* ending head number */
35 unsigned char EndingSector; /* ending sector number */
36 unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
37 unsigned int StartingBlock; /* first sector relative to start of disk */
38 unsigned int SectorCount; /* number of sectors in partition */
39 } PARTITION, *PPARTITION;
40
41
42 typedef struct _PARTITION_SECTOR
43 {
44 UCHAR BootCode[440]; /* 0x000 */
45 ULONG Signature; /* 0x1B8 */
46 UCHAR Reserved[2]; /* 0x1BC */
47 PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */
48 USHORT Magic; /* 0x1FE */
49 } PARTITION_SECTOR, *PPARTITION_SECTOR;
50
51 #include <poppack.h>
52
53
54 typedef enum _DISK_MANAGER
55 {
56 NoDiskManager,
57 OntrackDiskManager,
58 EZ_Drive
59 } DISK_MANAGER;
60
61 HAL_DISPATCH EXPORTED HalDispatchTable =
62 {
63 HAL_DISPATCH_VERSION,
64 (pHalQuerySystemInformation) NULL, // HalQuerySystemInformation
65 (pHalSetSystemInformation) NULL, // HalSetSystemInformation
66 (pHalQueryBusSlots) NULL, // HalQueryBusSlots
67 0,
68 (pHalExamineMBR) HalExamineMBR,
69 (pHalIoAssignDriveLetters) xHalIoAssignDriveLetters,
70 (pHalIoReadPartitionTable) xHalIoReadPartitionTable,
71 (pHalIoSetPartitionInformation) xHalIoSetPartitionInformation,
72 (pHalIoWritePartitionTable) xHalIoWritePartitionTable,
73 (pHalHandlerForBus) NULL, // HalReferenceHandlerForBus
74 (pHalReferenceBusHandler) NULL, // HalReferenceBusHandler
75 (pHalReferenceBusHandler) NULL, // HalDereferenceBusHandler
76 (pHalInitPnpDriver) NULL, //HalInitPnpDriver;
77 (pHalInitPowerManagement) NULL, //HalInitPowerManagement;
78 (pHalGetDmaAdapter) NULL, //HalGetDmaAdapter;
79 (pHalGetInterruptTranslator) NULL, //HalGetInterruptTranslator;
80 (pHalStartMirroring) NULL, //HalStartMirroring;
81 (pHalEndMirroring) NULL, //HalEndMirroring;
82 (pHalMirrorPhysicalMemory) NULL, //HalMirrorPhysicalMemory;
83 (pHalEndOfBoot) NULL, //HalEndOfBoot;
84 (pHalMirrorVerify) NULL //HalMirrorVerify;
85 };
86
87
88 HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable =
89 {
90 HAL_PRIVATE_DISPATCH_VERSION
91 };
92
93 /* FUNCTIONS *****************************************************************/
94
95 NTSTATUS
96 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
97 OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
98 {
99 IO_STATUS_BLOCK StatusBlock;
100 DISK_GEOMETRY DiskGeometry;
101 PDEVICE_OBJECT DeviceObject = NULL;
102 PFILE_OBJECT FileObject;
103 KEVENT Event;
104 PIRP Irp;
105 NTSTATUS Status;
106
107 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
108 DeviceName,
109 LayoutInfo);
110
111 /* Get the drives sector size */
112 Status = IoGetDeviceObjectPointer(DeviceName,
113 FILE_READ_DATA,
114 &FileObject,
115 &DeviceObject);
116 if (!NT_SUCCESS(Status))
117 {
118 DPRINT("Status %x\n",Status);
119 return(Status);
120 }
121
122 KeInitializeEvent(&Event,
123 NotificationEvent,
124 FALSE);
125
126 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
127 DeviceObject,
128 NULL,
129 0,
130 &DiskGeometry,
131 sizeof(DISK_GEOMETRY),
132 FALSE,
133 &Event,
134 &StatusBlock);
135 if (Irp == NULL)
136 {
137 ObDereferenceObject(FileObject);
138 return(STATUS_INSUFFICIENT_RESOURCES);
139 }
140
141 Status = IoCallDriver(DeviceObject,
142 Irp);
143 if (Status == STATUS_PENDING)
144 {
145 KeWaitForSingleObject(&Event,
146 Executive,
147 KernelMode,
148 FALSE,
149 NULL);
150 Status = StatusBlock.Status;
151 }
152 if (!NT_SUCCESS(Status))
153 {
154 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
155 {
156 DiskGeometry.BytesPerSector = 512;
157 }
158 else
159 {
160 ObDereferenceObject(FileObject);
161 return(Status);
162 }
163 }
164
165 DPRINT("DiskGeometry.BytesPerSector: %d\n",
166 DiskGeometry.BytesPerSector);
167
168 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
169 {
170 PDRIVE_LAYOUT_INFORMATION Buffer;
171
172 /* Allocate a partition list for a single entry. */
173 Buffer = ExAllocatePool(NonPagedPool,
174 sizeof(DRIVE_LAYOUT_INFORMATION));
175 if (Buffer != NULL)
176 {
177 RtlZeroMemory(Buffer,
178 sizeof(DRIVE_LAYOUT_INFORMATION));
179 Buffer->PartitionCount = 1;
180 *LayoutInfo = Buffer;
181
182 Status = STATUS_SUCCESS;
183 }
184 else
185 {
186 Status = STATUS_UNSUCCESSFUL;
187 }
188 }
189 else
190 {
191 /* Read the partition table */
192 Status = IoReadPartitionTable(DeviceObject,
193 DiskGeometry.BytesPerSector,
194 FALSE,
195 LayoutInfo);
196 }
197
198 ObDereferenceObject(FileObject);
199
200 return(Status);
201 }
202
203
204 static NTSTATUS
205 xHalpReadSector (IN PDEVICE_OBJECT DeviceObject,
206 IN ULONG SectorSize,
207 IN PLARGE_INTEGER SectorOffset,
208 IN PVOID Sector)
209 {
210 IO_STATUS_BLOCK StatusBlock;
211 KEVENT Event;
212 PIRP Irp;
213 NTSTATUS Status;
214
215 DPRINT("xHalpReadSector() called\n");
216
217 ASSERT(DeviceObject);
218 ASSERT(Sector);
219
220 KeInitializeEvent(&Event,
221 NotificationEvent,
222 FALSE);
223
224 /* Read the sector */
225 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
226 DeviceObject,
227 Sector,
228 SectorSize,
229 SectorOffset,
230 &Event,
231 &StatusBlock);
232
233 Status = IoCallDriver(DeviceObject,
234 Irp);
235 if (Status == STATUS_PENDING)
236 {
237 KeWaitForSingleObject(&Event,
238 Executive,
239 KernelMode,
240 FALSE,
241 NULL);
242 Status = StatusBlock.Status;
243 }
244
245 if (!NT_SUCCESS(Status))
246 {
247 DPRINT("Reading sector failed (Status 0x%08lx)\n",
248 Status);
249 return Status;
250 }
251
252 return Status;
253 }
254
255
256 static NTSTATUS
257 xHalpWriteSector (IN PDEVICE_OBJECT DeviceObject,
258 IN ULONG SectorSize,
259 IN PLARGE_INTEGER SectorOffset,
260 IN PVOID Sector)
261 {
262 IO_STATUS_BLOCK StatusBlock;
263 KEVENT Event;
264 PIRP Irp;
265 NTSTATUS Status;
266
267 DPRINT("xHalpWriteSector() called\n");
268
269 KeInitializeEvent(&Event,
270 NotificationEvent,
271 FALSE);
272
273 /* Write the sector */
274 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
275 DeviceObject,
276 Sector,
277 SectorSize,
278 SectorOffset,
279 &Event,
280 &StatusBlock);
281
282 Status = IoCallDriver(DeviceObject,
283 Irp);
284 if (Status == STATUS_PENDING)
285 {
286 KeWaitForSingleObject(&Event,
287 Executive,
288 KernelMode,
289 FALSE,
290 NULL);
291 Status = StatusBlock.Status;
292 }
293
294 if (!NT_SUCCESS(Status))
295 {
296 DPRINT("Writing sector failed (Status 0x%08lx)\n",
297 Status);
298 }
299
300 return Status;
301 }
302
303
304 VOID FASTCALL
305 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
306 IN ULONG SectorSize,
307 IN ULONG MBRTypeIdentifier,
308 OUT PVOID *Buffer)
309 {
310 LARGE_INTEGER SectorOffset;
311 PPARTITION_SECTOR Sector;
312 NTSTATUS Status;
313
314 DPRINT("HalExamineMBR()\n");
315
316 *Buffer = NULL;
317
318 if (SectorSize < 512)
319 SectorSize = 512;
320 if (SectorSize > 4096)
321 SectorSize = 4096;
322
323 Sector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
324 SectorSize);
325 if (Sector == NULL)
326 {
327 DPRINT ("Partition sector allocation failed\n");
328 return;
329 }
330
331 #if defined(__GNUC__)
332 SectorOffset.QuadPart = 0LL;
333 #else
334 SectorOffset.QuadPart = 0;
335 #endif
336 Status = xHalpReadSector (DeviceObject,
337 SectorSize,
338 &SectorOffset,
339 (PVOID)Sector);
340 if (!NT_SUCCESS(Status))
341 {
342 DPRINT("xHalpReadSector() failed (Status %lx)\n", Status);
343 ExFreePool(Sector);
344 return;
345 }
346
347 if (Sector->Magic != PARTITION_MAGIC)
348 {
349 DPRINT("Invalid MBR magic value\n");
350 ExFreePool(Sector);
351 return;
352 }
353
354 if (Sector->Partition[0].PartitionType != MBRTypeIdentifier)
355 {
356 DPRINT("Invalid MBRTypeIdentifier\n");
357 ExFreePool(Sector);
358 return;
359 }
360
361 if (Sector->Partition[0].PartitionType == 0x54)
362 {
363 /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
364 DPRINT("Found 'Ontrack Disk Manager'!\n");
365 *((PULONG)Sector) = 63;
366 }
367
368 *Buffer = (PVOID)Sector;
369 }
370
371
372 static VOID
373 HalpAssignDrive(IN PUNICODE_STRING PartitionName,
374 IN ULONG DriveNumber,
375 IN UCHAR DriveType)
376 {
377 WCHAR DriveNameBuffer[8];
378 UNICODE_STRING DriveName;
379 ULONG i;
380
381 DPRINT("HalpAssignDrive()\n");
382
383 if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 24))
384 {
385 /* Force assignment */
386 if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
387 {
388 DbgPrint("Drive letter already used!\n");
389 return;
390 }
391 }
392 else
393 {
394 /* Automatic assignment */
395 DriveNumber = AUTO_DRIVE;
396
397 for (i = 2; i < 24; i++)
398 {
399 if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
400 {
401 DriveNumber = i;
402 break;
403 }
404 }
405
406 if (DriveNumber == AUTO_DRIVE)
407 {
408 DbgPrint("No drive letter available!\n");
409 return;
410 }
411 }
412
413 DPRINT("DriveNumber %d\n", DriveNumber);
414
415 /* Update the System Device Map */
416 ObSystemDeviceMap->DriveMap |= (1 << DriveNumber);
417 ObSystemDeviceMap->DriveType[DriveNumber] = DriveType;
418
419 /* Build drive name */
420 swprintf(DriveNameBuffer,
421 L"\\??\\%C:",
422 'A' + DriveNumber);
423 RtlInitUnicodeString(&DriveName,
424 DriveNameBuffer);
425
426 DPRINT(" %wZ ==> %wZ\n",
427 &DriveName,
428 PartitionName);
429
430 /* Create symbolic link */
431 IoCreateSymbolicLink(&DriveName,
432 PartitionName);
433 }
434
435
436 VOID FASTCALL
437 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
438 IN PSTRING NtDeviceName,
439 OUT PUCHAR NtSystemPath,
440 OUT PSTRING NtSystemPathString)
441 {
442 PDRIVE_LAYOUT_INFORMATION *LayoutArray;
443 PCONFIGURATION_INFORMATION ConfigInfo;
444 OBJECT_ATTRIBUTES ObjectAttributes;
445 IO_STATUS_BLOCK StatusBlock;
446 UNICODE_STRING UnicodeString1;
447 UNICODE_STRING UnicodeString2;
448 HANDLE FileHandle;
449 PWSTR Buffer1;
450 PWSTR Buffer2;
451 ULONG i;
452 NTSTATUS Status;
453 ULONG j;
454
455 DPRINT("xHalIoAssignDriveLetters()\n");
456
457 ConfigInfo = IoGetConfigurationInformation();
458
459 Buffer1 = (PWSTR)ExAllocatePool(PagedPool,
460 64 * sizeof(WCHAR));
461 Buffer2 = (PWSTR)ExAllocatePool(PagedPool,
462 32 * sizeof(WCHAR));
463
464 /* Create PhysicalDrive links */
465 DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount);
466 for (i = 0; i < ConfigInfo->DiskCount; i++)
467 {
468 swprintf(Buffer1,
469 L"\\Device\\Harddisk%d\\Partition0",
470 i);
471 RtlInitUnicodeString(&UnicodeString1,
472 Buffer1);
473
474 InitializeObjectAttributes(&ObjectAttributes,
475 &UnicodeString1,
476 0,
477 NULL,
478 NULL);
479
480 Status = ZwOpenFile(&FileHandle,
481 0x10001,
482 &ObjectAttributes,
483 &StatusBlock,
484 1,
485 FILE_SYNCHRONOUS_IO_NONALERT);
486 if (NT_SUCCESS(Status))
487 {
488 ZwClose(FileHandle);
489
490 swprintf(Buffer2,
491 L"\\??\\PhysicalDrive%d",
492 i);
493 RtlInitUnicodeString(&UnicodeString2,
494 Buffer2);
495
496 DPRINT("Creating link: %S ==> %S\n",
497 Buffer2,
498 Buffer1);
499
500 IoCreateSymbolicLink(&UnicodeString2,
501 &UnicodeString1);
502 }
503 }
504
505 /* Initialize layout array */
506 LayoutArray = ExAllocatePool(NonPagedPool,
507 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
508 RtlZeroMemory(LayoutArray,
509 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
510 for (i = 0; i < ConfigInfo->DiskCount; i++)
511 {
512 swprintf(Buffer1,
513 L"\\Device\\Harddisk%d\\Partition0",
514 i);
515 RtlInitUnicodeString(&UnicodeString1,
516 Buffer1);
517
518 Status = xHalQueryDriveLayout(&UnicodeString1,
519 &LayoutArray[i]);
520 if (!NT_SUCCESS(Status))
521 {
522 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
523 Status);
524 LayoutArray[i] = NULL;
525 continue;
526 }
527 }
528
529 #ifndef NDEBUG
530 /* Dump layout array */
531 for (i = 0; i < ConfigInfo->DiskCount; i++)
532 {
533 DPRINT("Harddisk %d:\n",
534 i);
535
536 if (LayoutArray[i] == NULL)
537 continue;
538
539 DPRINT("Logical partitions: %d\n",
540 LayoutArray[i]->PartitionCount);
541
542 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
543 {
544 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
545 j,
546 LayoutArray[i]->PartitionEntry[j].PartitionNumber,
547 LayoutArray[i]->PartitionEntry[j].BootIndicator,
548 LayoutArray[i]->PartitionEntry[j].PartitionType,
549 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
550 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
551 }
552 }
553 #endif
554
555 /* Assign pre-assigned (registry) partitions */
556
557
558 /* Assign bootable partition on first harddisk */
559 DPRINT("Assigning bootable primary partition on first harddisk:\n");
560 if (ConfigInfo->DiskCount > 0)
561 {
562 if (LayoutArray[0])
563 {
564 /* Search for bootable partition */
565 for (j = 0; j < LayoutArray[0]->PartitionCount; j++)
566 {
567 if ((LayoutArray[0]->PartitionEntry[j].BootIndicator == TRUE) &&
568 IsRecognizedPartition(LayoutArray[0]->PartitionEntry[j].PartitionType))
569 {
570 swprintf(Buffer2,
571 L"\\Device\\Harddisk0\\Partition%d",
572 LayoutArray[0]->PartitionEntry[j].PartitionNumber);
573 RtlInitUnicodeString(&UnicodeString2,
574 Buffer2);
575
576 /* Assign drive */
577 DPRINT(" %wZ\n", &UnicodeString2);
578 HalpAssignDrive(&UnicodeString2,
579 AUTO_DRIVE,
580 DOSDEVICE_DRIVE_FIXED);
581 }
582 }
583 }
584 }
585
586 /* Assign remaining primary partitions */
587 DPRINT("Assigning remaining primary partitions:\n");
588 for (i = 0; i < ConfigInfo->DiskCount; i++)
589 {
590 if (LayoutArray[i])
591 {
592 /* Search for primary partitions */
593 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[i]->PartitionCount); j++)
594 {
595 if ((i == 0) && (LayoutArray[i]->PartitionEntry[j].BootIndicator == TRUE))
596 continue;
597
598 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType))
599 {
600 swprintf(Buffer2,
601 L"\\Device\\Harddisk%d\\Partition%d",
602 i,
603 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
604 RtlInitUnicodeString(&UnicodeString2,
605 Buffer2);
606
607 /* Assign drive */
608 DPRINT(" %wZ\n",
609 &UnicodeString2);
610 HalpAssignDrive(&UnicodeString2,
611 AUTO_DRIVE,
612 DOSDEVICE_DRIVE_FIXED);
613 }
614 }
615 }
616 }
617
618 /* Assign extended (logical) partitions */
619 DPRINT("Assigning extended (logical) partitions:\n");
620 for (i = 0; i < ConfigInfo->DiskCount; i++)
621 {
622 if (LayoutArray[i])
623 {
624 /* Search for extended partitions */
625 for (j = PARTITION_TBL_SIZE; j < LayoutArray[i]->PartitionCount; j++)
626 {
627 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
628 (LayoutArray[i]->PartitionEntry[j].PartitionNumber != 0))
629 {
630 swprintf(Buffer2,
631 L"\\Device\\Harddisk%d\\Partition%d",
632 i,
633 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
634 RtlInitUnicodeString(&UnicodeString2,
635 Buffer2);
636
637 /* Assign drive */
638 DPRINT(" %wZ\n",
639 &UnicodeString2);
640 HalpAssignDrive(&UnicodeString2,
641 AUTO_DRIVE,
642 DOSDEVICE_DRIVE_FIXED);
643 }
644 }
645 }
646 }
647
648 /* Assign removable disk drives */
649 DPRINT("Assigning removable disk drives:\n");
650 for (i = 0; i < ConfigInfo->DiskCount; i++)
651 {
652 if (LayoutArray[i])
653 {
654 /* Search for virtual partitions */
655 if (LayoutArray[i]->PartitionCount == 1 &&
656 LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
657 {
658 swprintf(Buffer2,
659 L"\\Device\\Harddisk%d\\Partition1",
660 i);
661 RtlInitUnicodeString(&UnicodeString2,
662 Buffer2);
663
664 /* Assign drive */
665 DPRINT(" %wZ\n",
666 &UnicodeString2);
667 HalpAssignDrive(&UnicodeString2,
668 AUTO_DRIVE,
669 DOSDEVICE_DRIVE_REMOVABLE);
670 }
671 }
672 }
673
674 /* Free layout array */
675 for (i = 0; i < ConfigInfo->DiskCount; i++)
676 {
677 if (LayoutArray[i] != NULL)
678 ExFreePool(LayoutArray[i]);
679 }
680 ExFreePool(LayoutArray);
681
682 /* Assign floppy drives */
683 DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount);
684 for (i = 0; i < ConfigInfo->FloppyCount; i++)
685 {
686 swprintf(Buffer1,
687 L"\\Device\\Floppy%d",
688 i);
689 RtlInitUnicodeString(&UnicodeString1,
690 Buffer1);
691
692 /* Assign drive letters A: or B: or first free drive letter */
693 DPRINT(" %wZ\n",
694 &UnicodeString1);
695 HalpAssignDrive(&UnicodeString1,
696 (i < 2) ? i : AUTO_DRIVE,
697 DOSDEVICE_DRIVE_REMOVABLE);
698 }
699
700 /* Assign cdrom drives */
701 DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount);
702 for (i = 0; i < ConfigInfo->CdRomCount; i++)
703 {
704 swprintf(Buffer1,
705 L"\\Device\\CdRom%d",
706 i);
707 RtlInitUnicodeString(&UnicodeString1,
708 Buffer1);
709
710 /* Assign first free drive letter */
711 DPRINT(" %wZ\n", &UnicodeString1);
712 HalpAssignDrive(&UnicodeString1,
713 AUTO_DRIVE,
714 DOSDEVICE_DRIVE_CDROM);
715 }
716
717 /* Anything else to do? */
718
719 ExFreePool(Buffer2);
720 ExFreePool(Buffer1);
721 }
722
723
724 NTSTATUS FASTCALL
725 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
726 ULONG SectorSize,
727 BOOLEAN ReturnRecognizedPartitions,
728 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
729 {
730 LARGE_INTEGER RealPartitionOffset;
731 ULONGLONG PartitionOffset;
732 #if defined(__GNUC__)
733 ULONGLONG nextPartitionOffset = 0LL;
734 #else
735 ULONGLONG nextPartitionOffset = 0;
736 #endif
737 ULONGLONG containerOffset;
738 NTSTATUS Status;
739 PPARTITION_SECTOR PartitionSector;
740 PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
741 ULONG i;
742 ULONG Count = 0;
743 ULONG Number = 1;
744 BOOLEAN ExtendedFound = FALSE;
745 PVOID MbrBuffer;
746 DISK_MANAGER DiskManager = NoDiskManager;
747
748 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
749 DeviceObject,
750 SectorSize,
751 ReturnRecognizedPartitions,
752 PartitionBuffer);
753
754 *PartitionBuffer = NULL;
755
756 /* Check sector size */
757 if (SectorSize < 512)
758 SectorSize = 512;
759 if (SectorSize > 4096)
760 SectorSize = 4096;
761
762 /* Check for 'Ontrack Disk Manager' */
763 HalExamineMBR(DeviceObject,
764 SectorSize,
765 0x54,
766 &MbrBuffer);
767 if (MbrBuffer != NULL)
768 {
769 DPRINT("Found 'Ontrack Disk Manager'\n");
770 DiskManager = OntrackDiskManager;
771 ExFreePool(MbrBuffer);
772 }
773
774 /* Check for 'EZ-Drive' */
775 HalExamineMBR(DeviceObject,
776 SectorSize,
777 0x55,
778 &MbrBuffer);
779 if (MbrBuffer != NULL)
780 {
781 DPRINT("Found 'EZ-Drive'\n");
782 DiskManager = EZ_Drive;
783 ExFreePool(MbrBuffer);
784 }
785
786 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
787 SectorSize);
788 if (PartitionSector == NULL)
789 {
790 return(STATUS_INSUFFICIENT_RESOURCES);
791 }
792
793 LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool,
794 0x1000);
795 if (LayoutBuffer == NULL)
796 {
797 ExFreePool(PartitionSector);
798 return(STATUS_INSUFFICIENT_RESOURCES);
799 }
800
801 RtlZeroMemory(LayoutBuffer,
802 0x1000);
803
804 #if defined(__GNUC__)
805 PartitionOffset = 0ULL;
806 containerOffset = 0ULL;
807 #else
808 PartitionOffset = 0;
809 containerOffset = 0;
810 #endif
811
812 do
813 {
814 DPRINT("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
815
816 /* Handle disk managers */
817 if (DiskManager == OntrackDiskManager)
818 {
819 /* Shift offset by 63 sectors */
820 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
821 }
822 #if defined(__GNUC__)
823 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
824 #else
825 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
826 #endif
827 {
828 /* Use sector 1 instead of sector 0 */
829 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
830 }
831 else
832 {
833 RealPartitionOffset.QuadPart = PartitionOffset;
834 }
835
836 DPRINT ("RealPartitionOffset: %I64u\n",
837 RealPartitionOffset.QuadPart / SectorSize);
838
839 Status = xHalpReadSector (DeviceObject,
840 SectorSize,
841 &RealPartitionOffset,
842 PartitionSector);
843 if (!NT_SUCCESS(Status))
844 {
845 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
846 Status);
847 ExFreePool (PartitionSector);
848 ExFreePool (LayoutBuffer);
849 return Status;
850 }
851
852 /* Check the boot sector id */
853 DPRINT("Magic %x\n", PartitionSector->Magic);
854 if (PartitionSector->Magic != PARTITION_MAGIC)
855 {
856 DPRINT ("Invalid partition sector magic\n");
857 ExFreePool (PartitionSector);
858 *PartitionBuffer = LayoutBuffer;
859 return STATUS_SUCCESS;
860 }
861
862 #ifndef NDEBUG
863 for (i = 0; i < PARTITION_TBL_SIZE; i++)
864 {
865 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
866 i,
867 PartitionSector->Partition[i].BootFlags,
868 PartitionSector->Partition[i].PartitionType,
869 PartitionSector->Partition[i].StartingHead,
870 PartitionSector->Partition[i].StartingSector & 0x3f,
871 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
872 PartitionSector->Partition[i].StartingCylinder,
873 PartitionSector->Partition[i].EndingHead,
874 PartitionSector->Partition[i].EndingSector & 0x3f,
875 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
876 PartitionSector->Partition[i].EndingCylinder,
877 PartitionSector->Partition[i].StartingBlock,
878 PartitionSector->Partition[i].SectorCount);
879 }
880 #endif
881
882 #if defined(__GNUC__)
883 if (PartitionOffset == 0ULL)
884 #else
885 if (PartitionOffset == 0)
886 #endif
887 {
888 LayoutBuffer->Signature = PartitionSector->Signature;
889 DPRINT("Disk signature: %lx\n", LayoutBuffer->Signature);
890 }
891
892 ExtendedFound = FALSE;
893
894 for (i = 0; i < PARTITION_TBL_SIZE; i++)
895 {
896 if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
897 {
898 ExtendedFound = TRUE;
899 if ((ULONGLONG) containerOffset == (ULONGLONG) 0)
900 {
901 containerOffset = PartitionOffset;
902 }
903 nextPartitionOffset = (ULONGLONG) containerOffset +
904 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
905 (ULONGLONG) SectorSize;
906 }
907
908 if ((ReturnRecognizedPartitions == FALSE) ||
909 ((ReturnRecognizedPartitions == TRUE) &&
910 IsRecognizedPartition(PartitionSector->Partition[i].PartitionType)))
911 {
912 /* handle normal partition */
913 DPRINT("Partition %u: Normal Partition\n", i);
914 Count = LayoutBuffer->PartitionCount;
915 DPRINT("Logical Partition %u\n", Count);
916
917 if (PartitionSector->Partition[i].StartingBlock == 0)
918 {
919 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
920 }
921 else if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
922 {
923 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
924 (ULONGLONG) containerOffset +
925 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
926 (ULONGLONG) SectorSize;
927 }
928 else
929 {
930 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
931 (ULONGLONG)PartitionOffset +
932 ((ULONGLONG)PartitionSector->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
933 }
934 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
935 (ULONGLONG)PartitionSector->Partition[i].SectorCount * (ULONGLONG)SectorSize;
936 LayoutBuffer->PartitionEntry[Count].HiddenSectors =
937 PartitionSector->Partition[i].StartingBlock;
938
939 if (IsRecognizedPartition(PartitionSector->Partition[i].PartitionType))
940 {
941 LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number;
942 Number++;
943 }
944 else
945 {
946 LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0;
947 }
948
949 LayoutBuffer->PartitionEntry[Count].PartitionType =
950 PartitionSector->Partition[i].PartitionType;
951 LayoutBuffer->PartitionEntry[Count].BootIndicator =
952 (PartitionSector->Partition[i].BootFlags & 0x80)?TRUE:FALSE;
953 LayoutBuffer->PartitionEntry[Count].RecognizedPartition =
954 IsRecognizedPartition (PartitionSector->Partition[i].PartitionType);
955 LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE;
956
957 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
958 Count,
959 LayoutBuffer->PartitionEntry[Count].PartitionNumber,
960 LayoutBuffer->PartitionEntry[Count].BootIndicator,
961 LayoutBuffer->PartitionEntry[Count].PartitionType,
962 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart,
963 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart,
964 LayoutBuffer->PartitionEntry[Count].RecognizedPartition);
965
966 LayoutBuffer->PartitionCount++;
967 }
968 }
969
970 PartitionOffset = nextPartitionOffset;
971 }
972 while (ExtendedFound == TRUE);
973
974 *PartitionBuffer = LayoutBuffer;
975 ExFreePool(PartitionSector);
976
977 return(STATUS_SUCCESS);
978 }
979
980
981 NTSTATUS FASTCALL
982 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
983 IN ULONG SectorSize,
984 IN ULONG PartitionNumber,
985 IN ULONG PartitionType)
986 {
987 PPARTITION_SECTOR PartitionSector;
988 LARGE_INTEGER RealPartitionOffset;
989 ULONGLONG PartitionOffset;
990 #if defined(__GNUC__)
991 ULONGLONG nextPartitionOffset = 0LL;
992 #else
993 ULONGLONG nextPartitionOffset = 0;
994 #endif
995 ULONGLONG containerOffset;
996 NTSTATUS Status;
997 ULONG i;
998 ULONG Number = 1;
999 BOOLEAN ExtendedFound = FALSE;
1000 DISK_MANAGER DiskManager = NoDiskManager;
1001
1002 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
1003 DeviceObject,
1004 SectorSize,
1005 PartitionNumber,
1006 PartitionType);
1007
1008 /* Check sector size */
1009 if (SectorSize < 512)
1010 SectorSize = 512;
1011 if (SectorSize > 4096)
1012 SectorSize = 4096;
1013
1014 /* Check for 'Ontrack Disk Manager' */
1015 HalExamineMBR (DeviceObject,
1016 SectorSize,
1017 0x54,
1018 (PVOID*)(PVOID)&PartitionSector);
1019 if (PartitionSector != NULL)
1020 {
1021 DPRINT ("Found 'Ontrack Disk Manager'\n");
1022 DiskManager = OntrackDiskManager;
1023 ExFreePool (PartitionSector);
1024 }
1025
1026 /* Check for 'EZ-Drive' */
1027 HalExamineMBR (DeviceObject,
1028 SectorSize,
1029 0x55,
1030 (PVOID*)(PVOID)&PartitionSector);
1031 if (PartitionSector != NULL)
1032 {
1033 DPRINT ("Found 'EZ-Drive'\n");
1034 DiskManager = EZ_Drive;
1035 ExFreePool (PartitionSector);
1036 }
1037
1038 /* Allocate partition sector */
1039 PartitionSector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
1040 SectorSize);
1041 if (PartitionSector == NULL)
1042 {
1043 return STATUS_INSUFFICIENT_RESOURCES;
1044 }
1045
1046 #if defined(__GNUC__)
1047 PartitionOffset = 0ULL;
1048 containerOffset = 0ULL;
1049 #else
1050 PartitionOffset = 0;
1051 containerOffset = 0;
1052 #endif
1053
1054 do
1055 {
1056 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
1057
1058 /* Handle disk managers */
1059 if (DiskManager == OntrackDiskManager)
1060 {
1061 /* Shift offset by 63 sectors */
1062 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1063 }
1064 #if defined(__GNUC__)
1065 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1066 #else
1067 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1068 #endif
1069 {
1070 /* Use sector 1 instead of sector 0 */
1071 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1072 }
1073 else
1074 {
1075 RealPartitionOffset.QuadPart = PartitionOffset;
1076 }
1077
1078 DPRINT ("RealPartitionOffset: %I64u\n",
1079 RealPartitionOffset.QuadPart / SectorSize);
1080
1081 Status = xHalpReadSector (DeviceObject,
1082 SectorSize,
1083 &RealPartitionOffset,
1084 PartitionSector);
1085 if (!NT_SUCCESS (Status))
1086 {
1087 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1088 Status);
1089 ExFreePool (PartitionSector);
1090 return Status;
1091 }
1092
1093 /* Check the boot sector id */
1094 DPRINT("Magic %x\n", PartitionSector->Magic);
1095 if (PartitionSector->Magic != PARTITION_MAGIC)
1096 {
1097 DPRINT ("Invalid partition sector magic\n");
1098 ExFreePool (PartitionSector);
1099 return STATUS_UNSUCCESSFUL;
1100 }
1101
1102 #ifndef NDEBUG
1103 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1104 {
1105 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1106 i,
1107 PartitionSector->Partition[i].BootFlags,
1108 PartitionSector->Partition[i].PartitionType,
1109 PartitionSector->Partition[i].StartingHead,
1110 PartitionSector->Partition[i].StartingSector & 0x3f,
1111 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1112 PartitionSector->Partition[i].StartingCylinder,
1113 PartitionSector->Partition[i].EndingHead,
1114 PartitionSector->Partition[i].EndingSector & 0x3f,
1115 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1116 PartitionSector->Partition[i].EndingCylinder,
1117 PartitionSector->Partition[i].StartingBlock,
1118 PartitionSector->Partition[i].SectorCount);
1119 }
1120 #endif
1121
1122 ExtendedFound = FALSE;
1123 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1124 {
1125 if (IsContainerPartition (PartitionSector->Partition[i].PartitionType))
1126 {
1127 ExtendedFound = TRUE;
1128 #if defined(__GNUC__)
1129 if (containerOffset == 0ULL)
1130 #else
1131 if (containerOffset == 0)
1132 #endif
1133 {
1134 containerOffset = PartitionOffset;
1135 }
1136 nextPartitionOffset = containerOffset +
1137 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1138 (ULONGLONG) SectorSize;
1139 }
1140
1141 /* Handle recognized partition */
1142 if (IsRecognizedPartition (PartitionSector->Partition[i].PartitionType))
1143 {
1144 if (Number == PartitionNumber)
1145 {
1146 /* Set partition type */
1147 PartitionSector->Partition[i].PartitionType = PartitionType;
1148
1149 /* Write partition sector */
1150 Status = xHalpWriteSector (DeviceObject,
1151 SectorSize,
1152 &RealPartitionOffset,
1153 PartitionSector);
1154 if (!NT_SUCCESS(Status))
1155 {
1156 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1157 }
1158
1159 ExFreePool (PartitionSector);
1160 return Status;
1161 }
1162 Number++;
1163 }
1164 }
1165
1166 PartitionOffset = nextPartitionOffset;
1167 }
1168 while (ExtendedFound == TRUE);
1169
1170 ExFreePool(PartitionSector);
1171
1172 return STATUS_UNSUCCESSFUL;
1173 }
1174
1175
1176 NTSTATUS FASTCALL
1177 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
1178 IN ULONG SectorSize,
1179 IN ULONG SectorsPerTrack,
1180 IN ULONG NumberOfHeads,
1181 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
1182 {
1183 PPARTITION_SECTOR PartitionSector;
1184 LARGE_INTEGER RealPartitionOffset;
1185 ULONGLONG PartitionOffset;
1186 #if defined(__GNUC__)
1187 ULONGLONG NextPartitionOffset = 0LL;
1188 #else
1189 ULONGLONG NextPartitionOffset = 0;
1190 #endif
1191 ULONGLONG ContainerOffset;
1192 BOOLEAN ContainerEntry;
1193 DISK_MANAGER DiskManager;
1194 ULONG i;
1195 ULONG j;
1196 ULONG StartBlock;
1197 ULONG SectorCount;
1198 ULONG StartCylinder;
1199 ULONG StartSector;
1200 ULONG StartHead;
1201 ULONG EndCylinder;
1202 ULONG EndSector;
1203 ULONG EndHead;
1204 ULONG lba;
1205 ULONG x;
1206 NTSTATUS Status;
1207
1208 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1209 DeviceObject,
1210 SectorSize,
1211 SectorsPerTrack,
1212 NumberOfHeads,
1213 PartitionBuffer);
1214
1215 ASSERT(DeviceObject);
1216 ASSERT(PartitionBuffer);
1217
1218 DiskManager = NoDiskManager;
1219
1220 /* Check sector size */
1221 if (SectorSize < 512)
1222 SectorSize = 512;
1223 if (SectorSize > 4096)
1224 SectorSize = 4096;
1225
1226 /* Check for 'Ontrack Disk Manager' */
1227 HalExamineMBR (DeviceObject,
1228 SectorSize,
1229 0x54,
1230 (PVOID*)(PVOID)&PartitionSector);
1231 if (PartitionSector != NULL)
1232 {
1233 DPRINT ("Found 'Ontrack Disk Manager'\n");
1234 DiskManager = OntrackDiskManager;
1235 ExFreePool (PartitionSector);
1236 }
1237
1238 /* Check for 'EZ-Drive' */
1239 HalExamineMBR (DeviceObject,
1240 SectorSize,
1241 0x55,
1242 (PVOID*)(PVOID)&PartitionSector);
1243 if (PartitionSector != NULL)
1244 {
1245 DPRINT ("Found 'EZ-Drive'\n");
1246 DiskManager = EZ_Drive;
1247 ExFreePool (PartitionSector);
1248 }
1249
1250 /* Allocate partition sector */
1251 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1252 SectorSize);
1253 if (PartitionSector == NULL)
1254 {
1255 return STATUS_INSUFFICIENT_RESOURCES;
1256 }
1257
1258 Status = STATUS_SUCCESS;
1259 #if defined(__GNUC__)
1260 PartitionOffset = 0ULL;
1261 ContainerOffset = 0ULL;
1262 #else
1263 PartitionOffset = 0;
1264 ContainerOffset = 0;
1265 #endif
1266 for (i = 0; i < PartitionBuffer->PartitionCount; i += 4)
1267 {
1268 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset);
1269 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset);
1270
1271 /* Handle disk managers */
1272 if (DiskManager == OntrackDiskManager)
1273 {
1274 /* Shift offset by 63 sectors */
1275 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1276 }
1277 #if defined(__GNUC__)
1278 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1279 #else
1280 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1281 #endif
1282 {
1283 /* Use sector 1 instead of sector 0 */
1284 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1285 }
1286 else
1287 {
1288 RealPartitionOffset.QuadPart = PartitionOffset;
1289 }
1290
1291 /* Write modified partition tables */
1292 if (PartitionBuffer->PartitionEntry[i].RewritePartition == TRUE ||
1293 PartitionBuffer->PartitionEntry[i + 1].RewritePartition == TRUE ||
1294 PartitionBuffer->PartitionEntry[i + 2].RewritePartition == TRUE ||
1295 PartitionBuffer->PartitionEntry[i + 3].RewritePartition == TRUE)
1296 {
1297 /* Read partition sector */
1298 Status = xHalpReadSector (DeviceObject,
1299 SectorSize,
1300 &RealPartitionOffset,
1301 PartitionSector);
1302 if (!NT_SUCCESS(Status))
1303 {
1304 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status);
1305 break;
1306 }
1307
1308 /* Initialize a new partition sector */
1309 if (PartitionSector->Magic != PARTITION_MAGIC)
1310 {
1311 /* Create empty partition sector */
1312 RtlZeroMemory (PartitionSector,
1313 SectorSize);
1314 PartitionSector->Magic = PARTITION_MAGIC;
1315 }
1316
1317 /* Update partition sector entries */
1318 for (j = 0; j < 4; j++)
1319 {
1320 if (PartitionBuffer->PartitionEntry[i + j].RewritePartition == TRUE)
1321 {
1322 /* Set partition boot flag */
1323 if (PartitionBuffer->PartitionEntry[i + j].BootIndicator)
1324 {
1325 PartitionSector->Partition[j].BootFlags |= 0x80;
1326 }
1327 else
1328 {
1329 PartitionSector->Partition[j].BootFlags &= ~0x80;
1330 }
1331
1332 /* Set partition type */
1333 PartitionSector->Partition[j].PartitionType =
1334 PartitionBuffer->PartitionEntry[i + j].PartitionType;
1335
1336 /* Set partition data */
1337 #if defined(__GNUC__)
1338 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0ULL &&
1339 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0ULL)
1340 #else
1341 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0 &&
1342 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0)
1343 #endif
1344 {
1345 PartitionSector->Partition[j].StartingBlock = 0;
1346 PartitionSector->Partition[j].SectorCount = 0;
1347 PartitionSector->Partition[j].StartingCylinder = 0;
1348 PartitionSector->Partition[j].StartingHead = 0;
1349 PartitionSector->Partition[j].StartingSector = 0;
1350 PartitionSector->Partition[j].EndingCylinder = 0;
1351 PartitionSector->Partition[j].EndingHead = 0;
1352 PartitionSector->Partition[j].EndingSector = 0;
1353 }
1354 else
1355 {
1356 /*
1357 * CHS formulas:
1358 * x = LBA DIV SectorsPerTrack
1359 * cylinder = (x DIV NumberOfHeads) % 1024
1360 * head = x MOD NumberOfHeads
1361 * sector = (LBA MOD SectorsPerTrack) + 1
1362 */
1363
1364 /* Compute starting CHS values */
1365 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart) / SectorSize);
1366 x = lba / SectorsPerTrack;
1367 StartCylinder = (x / NumberOfHeads) %1024;
1368 StartHead = x % NumberOfHeads;
1369 StartSector = (lba % SectorsPerTrack) + 1;
1370 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1371 lba, StartCylinder, StartHead, StartSector);
1372
1373 /* Compute ending CHS values */
1374 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart +
1375 (PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart - 1)) / SectorSize);
1376 x = lba / SectorsPerTrack;
1377 EndCylinder = (x / NumberOfHeads) % 1024;
1378 EndHead = x % NumberOfHeads;
1379 EndSector = (lba % SectorsPerTrack) + 1;
1380 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1381 lba, EndCylinder, EndHead, EndSector);
1382
1383 /* Set starting CHS values */
1384 PartitionSector->Partition[j].StartingCylinder = StartCylinder & 0xff;
1385 PartitionSector->Partition[j].StartingHead = StartHead;
1386 PartitionSector->Partition[j].StartingSector =
1387 ((StartCylinder & 0x0300) >> 2) + (StartSector & 0x3f);
1388
1389 /* Set ending CHS values */
1390 PartitionSector->Partition[j].EndingCylinder = EndCylinder & 0xff;
1391 PartitionSector->Partition[j].EndingHead = EndHead;
1392 PartitionSector->Partition[j].EndingSector =
1393 ((EndCylinder & 0x0300) >> 2) + (EndSector & 0x3f);
1394
1395 /* Calculate start sector and sector count */
1396 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1397 {
1398 StartBlock =
1399 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - ContainerOffset) / SectorSize;
1400 }
1401 else
1402 {
1403 StartBlock =
1404 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - NextPartitionOffset) / SectorSize;
1405 }
1406 SectorCount =
1407 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart / SectorSize;
1408 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1409 StartBlock, SectorCount);
1410
1411 /* Set start sector and sector count */
1412 PartitionSector->Partition[j].StartingBlock = StartBlock;
1413 PartitionSector->Partition[j].SectorCount = SectorCount;
1414 }
1415 }
1416 }
1417
1418 /* Write partition sector */
1419 Status = xHalpWriteSector (DeviceObject,
1420 SectorSize,
1421 &RealPartitionOffset,
1422 PartitionSector);
1423 if (!NT_SUCCESS(Status))
1424 {
1425 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1426 break;
1427 }
1428 }
1429
1430 ContainerEntry = FALSE;
1431 for (j = 0; j < 4; j++)
1432 {
1433 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1434 {
1435 ContainerEntry = TRUE;
1436 NextPartitionOffset =
1437 PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart;
1438
1439 #if defined(__GNUC__)
1440 if (ContainerOffset == 0ULL)
1441 #else
1442 if (ContainerOffset == 0)
1443 #endif
1444 {
1445 ContainerOffset = NextPartitionOffset;
1446 }
1447 }
1448 }
1449
1450 if (ContainerEntry == FALSE)
1451 {
1452 DPRINT ("No container entry in partition sector!\n");
1453 break;
1454 }
1455
1456 PartitionOffset = NextPartitionOffset;
1457 }
1458
1459 ExFreePool (PartitionSector);
1460
1461 return Status;
1462 }
1463
1464 /*
1465 * @unimplemented
1466 *
1467 STDCALL
1468 VOID
1469 IoAssignDriveLetters(
1470 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1471 IN PSTRING NtDeviceName,
1472 OUT PUCHAR NtSystemPath,
1473 OUT PSTRING NtSystemPathString
1474 )
1475 {
1476 UNIMPLEMENTED;
1477 */
1478
1479 /*
1480 * @unimplemented
1481 */
1482 NTSTATUS
1483 STDCALL
1484 IoCreateDisk(
1485 IN PDEVICE_OBJECT DeviceObject,
1486 IN struct _CREATE_DISK* Disk
1487 )
1488 {
1489 UNIMPLEMENTED;
1490 return STATUS_NOT_IMPLEMENTED;
1491 }
1492
1493 /*
1494 * @unimplemented
1495 */
1496 NTSTATUS
1497 STDCALL
1498 IoGetBootDiskInformation(
1499 IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
1500 IN ULONG Size
1501 )
1502 {
1503 UNIMPLEMENTED;
1504 return STATUS_NOT_IMPLEMENTED;
1505 }
1506
1507
1508 /*
1509 * @unimplemented
1510 */
1511 NTSTATUS
1512 STDCALL
1513 IoReadDiskSignature(
1514 IN PDEVICE_OBJECT DeviceObject,
1515 IN ULONG BytesPerSector,
1516 OUT PDISK_SIGNATURE Signature
1517 )
1518 {
1519 UNIMPLEMENTED;
1520 return STATUS_NOT_IMPLEMENTED;
1521 }
1522
1523 /*
1524 * @unimplemented
1525 */
1526 NTSTATUS
1527 STDCALL
1528 IoReadPartitionTableEx(
1529 IN PDEVICE_OBJECT DeviceObject,
1530 IN struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout
1531 )
1532 {
1533 UNIMPLEMENTED;
1534 return STATUS_NOT_IMPLEMENTED;
1535 }
1536
1537 /*
1538 * @unimplemented
1539 */
1540 NTSTATUS
1541 STDCALL
1542 IoSetPartitionInformationEx(
1543 IN PDEVICE_OBJECT DeviceObject,
1544 IN ULONG PartitionNumber,
1545 IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
1546 )
1547 {
1548 UNIMPLEMENTED;
1549 return STATUS_NOT_IMPLEMENTED;
1550 }
1551
1552 /*
1553 * @unimplemented
1554 */
1555 NTSTATUS
1556 STDCALL
1557 IoSetSystemPartition(
1558 PUNICODE_STRING VolumeNameString
1559 )
1560 {
1561 UNIMPLEMENTED;
1562 return STATUS_NOT_IMPLEMENTED;
1563 }
1564
1565 /*
1566 * @unimplemented
1567 */
1568 NTSTATUS
1569 STDCALL
1570 IoVerifyPartitionTable(
1571 IN PDEVICE_OBJECT DeviceObject,
1572 IN BOOLEAN FixErrors
1573 )
1574 {
1575 UNIMPLEMENTED;
1576 return STATUS_NOT_IMPLEMENTED;
1577 }
1578
1579 /*
1580 * @unimplemented
1581 */
1582 NTSTATUS
1583 STDCALL
1584 IoVolumeDeviceToDosName(
1585 IN PVOID VolumeDeviceObject,
1586 OUT PUNICODE_STRING DosName
1587 )
1588 {
1589 UNIMPLEMENTED;
1590 return STATUS_NOT_IMPLEMENTED;
1591 }
1592
1593 /*
1594 * @unimplemented
1595 */
1596 NTSTATUS
1597 STDCALL
1598 IoWritePartitionTableEx(
1599 IN PDEVICE_OBJECT DeviceObject,
1600 IN struct _DRIVE_LAYOUT_INFORMATION_EX* DriveLayfout
1601 )
1602 {
1603 UNIMPLEMENTED;
1604 return STATUS_NOT_IMPLEMENTED;
1605 }
1606
1607 /*
1608 * @implemented
1609 */
1610 NTSTATUS FASTCALL
1611 IoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
1612 ULONG SectorSize,
1613 BOOLEAN ReturnRecognizedPartitions,
1614 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
1615 {
1616 return(HalIoReadPartitionTable(DeviceObject,
1617 SectorSize,
1618 ReturnRecognizedPartitions,
1619 PartitionBuffer));
1620 }
1621
1622
1623 NTSTATUS FASTCALL
1624 IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject,
1625 ULONG SectorSize,
1626 ULONG PartitionNumber,
1627 ULONG PartitionType)
1628 {
1629 return(HalIoSetPartitionInformation(DeviceObject,
1630 SectorSize,
1631 PartitionNumber,
1632 PartitionType));
1633 }
1634
1635
1636 NTSTATUS FASTCALL
1637 IoWritePartitionTable(PDEVICE_OBJECT DeviceObject,
1638 ULONG SectorSize,
1639 ULONG SectorsPerTrack,
1640 ULONG NumberOfHeads,
1641 PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
1642 {
1643 return(HalIoWritePartitionTable(DeviceObject,
1644 SectorSize,
1645 SectorsPerTrack,
1646 NumberOfHeads,
1647 PartitionBuffer));
1648 }
1649 /* EOF */