3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 DBG_DEFAULT_CHANNEL(DISK
);
26 BOOLEAN
DiskGetActivePartitionEntry(UCHAR DriveNumber
,
27 PPARTITION_TABLE_ENTRY PartitionTableEntry
,
28 ULONG
*ActivePartition
)
30 ULONG BootablePartitionCount
= 0;
31 MASTER_BOOT_RECORD MasterBootRecord
;
35 // Read master boot record
36 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
41 // Count the bootable partitions
42 if (MasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
44 BootablePartitionCount
++;
47 if (MasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
49 BootablePartitionCount
++;
52 if (MasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
54 BootablePartitionCount
++;
57 if (MasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
59 BootablePartitionCount
++;
63 // Make sure there was only one bootable partition
64 if (BootablePartitionCount
== 0)
66 ERR("No bootable (active) partitions found.\n");
69 else if (BootablePartitionCount
!= 1)
71 ERR("Too many bootable (active) partitions found.\n");
75 // Copy the partition table entry
76 RtlCopyMemory(PartitionTableEntry
,
77 &MasterBootRecord
.PartitionTable
[*ActivePartition
- 1],
78 sizeof(PARTITION_TABLE_ENTRY
));
83 BOOLEAN
DiskGetPartitionEntry(UCHAR DriveNumber
, ULONG PartitionNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
85 MASTER_BOOT_RECORD MasterBootRecord
;
86 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry
;
87 ULONG ExtendedPartitionNumber
;
88 ULONG ExtendedPartitionOffset
;
91 // Read master boot record
92 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
97 // If they are asking for a primary
98 // partition then things are easy
99 if (PartitionNumber
< 5)
101 // PartitionNumber is one-based and we need it zero-based
104 // Copy the partition table entry
105 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[PartitionNumber
], sizeof(PARTITION_TABLE_ENTRY
));
111 // They want an extended partition entry so we will need
112 // to loop through all the extended partitions on the disk
113 // and return the one they want.
115 ExtendedPartitionNumber
= PartitionNumber
- 5;
117 // Set the initial relative starting sector to 0
118 // This is because extended partition starting
119 // sectors a numbered relative to their parent
120 ExtendedPartitionOffset
= 0;
122 for (Index
=0; Index
<=ExtendedPartitionNumber
; Index
++)
124 // Get the extended partition table entry
125 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord
, &ExtendedPartitionTableEntry
))
130 // Adjust the relative starting sector of the partition
131 ExtendedPartitionTableEntry
.SectorCountBeforePartition
+= ExtendedPartitionOffset
;
132 if (ExtendedPartitionOffset
== 0)
134 // Set the start of the parrent extended partition
135 ExtendedPartitionOffset
= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
137 // Read the partition boot record
138 if (!DiskReadBootRecord(DriveNumber
, ExtendedPartitionTableEntry
.SectorCountBeforePartition
, &MasterBootRecord
))
143 // Get the first real partition table entry
144 if (!DiskGetFirstPartitionEntry(&MasterBootRecord
, PartitionTableEntry
))
149 // Now correct the start sector of the partition
150 PartitionTableEntry
->SectorCountBeforePartition
+= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
153 // When we get here we should have the correct entry
154 // already stored in PartitionTableEntry
155 // so just return TRUE
161 BOOLEAN
DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
165 for (Index
=0; Index
<4; Index
++)
167 // Check the system indicator
168 // If it's not an extended or unused partition
170 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_ENTRY_UNUSED
) &&
171 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_EXTENDED
) &&
172 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_XINT13_EXTENDED
))
174 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
182 BOOLEAN
DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
186 for (Index
=0; Index
<4; Index
++)
188 // Check the system indicator
189 // If it an extended partition then we're done
190 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_EXTENDED
) ||
191 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_XINT13_EXTENDED
))
193 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
201 BOOLEAN
DiskReadBootRecord(UCHAR DriveNumber
, ULONGLONG LogicalSectorNumber
, PMASTER_BOOT_RECORD BootRecord
)
205 // Read master boot record
206 if (!MachDiskReadLogicalSectors(DriveNumber
, LogicalSectorNumber
, 1, DiskReadBuffer
))
210 RtlCopyMemory(BootRecord
, DiskReadBuffer
, sizeof(MASTER_BOOT_RECORD
));
212 TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber
);
213 TRACE("Boot record logical start sector = %d\n", LogicalSectorNumber
);
214 TRACE("sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
));
216 for (Index
=0; Index
<4; Index
++)
218 TRACE("-------------------------------------------\n");
219 TRACE("Partition %d\n", (Index
+ 1));
220 TRACE("BootIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].BootIndicator
);
221 TRACE("StartHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartHead
);
222 TRACE("StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].StartSector
);
223 TRACE("StartCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartCylinder
);
224 TRACE("SystemIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].SystemIndicator
);
225 TRACE("EndHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndHead
);
226 TRACE("EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].EndSector
);
227 TRACE("EndCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndCylinder
);
228 TRACE("SectorCountBeforePartition: 0x%x\n", BootRecord
->PartitionTable
[Index
].SectorCountBeforePartition
);
229 TRACE("PartitionSectorCount: 0x%x\n", BootRecord
->PartitionTable
[Index
].PartitionSectorCount
);
232 // Check the partition table magic value
233 if (BootRecord
->MasterBootRecordMagic
!= 0xaa55)
244 IN PDEVICE_OBJECT DeviceObject
,
245 IN ULONGLONG LogicalSectorNumber
,
247 OUT PMASTER_BOOT_RECORD BootRecord
)
249 ULONG FileId
= (ULONG
)DeviceObject
;
250 LARGE_INTEGER Position
;
254 Position
.QuadPart
= LogicalSectorNumber
* SectorSize
;
255 Status
= ArcSeek(FileId
, &Position
, SeekAbsolute
);
256 if (Status
!= ESUCCESS
)
257 return STATUS_IO_DEVICE_ERROR
;
259 Status
= ArcRead(FileId
, BootRecord
, SectorSize
, &BytesRead
);
260 if (Status
!= ESUCCESS
|| BytesRead
!= SectorSize
)
261 return STATUS_IO_DEVICE_ERROR
;
263 return STATUS_SUCCESS
;
268 IopCopyPartitionRecord(
269 IN BOOLEAN ReturnRecognizedPartitions
,
271 IN PPARTITION_TABLE_ENTRY PartitionTableEntry
,
272 OUT PARTITION_INFORMATION
*PartitionEntry
)
274 BOOLEAN IsRecognized
;
276 IsRecognized
= TRUE
; /* FIXME */
277 if (!IsRecognized
&& ReturnRecognizedPartitions
)
280 PartitionEntry
->StartingOffset
.QuadPart
= (ULONGLONG
)PartitionTableEntry
->SectorCountBeforePartition
* SectorSize
;
281 PartitionEntry
->PartitionLength
.QuadPart
= (ULONGLONG
)PartitionTableEntry
->PartitionSectorCount
* SectorSize
;
282 PartitionEntry
->HiddenSectors
= 0;
283 PartitionEntry
->PartitionNumber
= 0; /* Will be filled later */
284 PartitionEntry
->PartitionType
= PartitionTableEntry
->SystemIndicator
;
285 PartitionEntry
->BootIndicator
= (PartitionTableEntry
->BootIndicator
& 0x80) ? TRUE
: FALSE
;
286 PartitionEntry
->RecognizedPartition
= IsRecognized
;
287 PartitionEntry
->RewritePartition
= FALSE
;
294 IoReadPartitionTable(
295 IN PDEVICE_OBJECT DeviceObject
,
297 IN BOOLEAN ReturnRecognizedPartitions
,
298 OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
300 PMASTER_BOOT_RECORD MasterBootRecord
;
301 PDRIVE_LAYOUT_INFORMATION Partitions
;
302 ULONG NbPartitions
, i
, Size
;
305 *PartitionBuffer
= NULL
;
307 if (SectorSize
< sizeof(MASTER_BOOT_RECORD
))
308 return STATUS_NOT_SUPPORTED
;
310 MasterBootRecord
= ExAllocatePool(NonPagedPool
, SectorSize
);
311 if (!MasterBootRecord
)
312 return STATUS_NO_MEMORY
;
315 ret
= IopReadBootRecord(DeviceObject
, 0, SectorSize
, MasterBootRecord
);
316 if (!NT_SUCCESS(ret
))
318 ExFreePool(MasterBootRecord
);
322 /* Check validity of boot record */
323 if (MasterBootRecord
->MasterBootRecordMagic
!= 0xaa55)
325 ExFreePool(MasterBootRecord
);
326 return STATUS_NOT_SUPPORTED
;
329 /* Count number of partitions */
331 for (i
= 0; i
< 4; i
++)
335 if (MasterBootRecord
->PartitionTable
[i
].SystemIndicator
== PARTITION_EXTENDED
||
336 MasterBootRecord
->PartitionTable
[i
].SystemIndicator
== PARTITION_XINT13_EXTENDED
)
338 /* FIXME: unhandled case; count number of partitions */
343 if (NbPartitions
== 0)
345 ExFreePool(MasterBootRecord
);
346 return STATUS_NOT_SUPPORTED
;
349 /* Allocation space to store partitions */
350 Size
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION
, PartitionEntry
) +
351 NbPartitions
* sizeof(PARTITION_INFORMATION
);
352 Partitions
= ExAllocatePool(NonPagedPool
, Size
);
355 ExFreePool(MasterBootRecord
);
356 return STATUS_NO_MEMORY
;
359 /* Count number of partitions */
361 for (i
= 0; i
< 4; i
++)
363 if (IopCopyPartitionRecord(ReturnRecognizedPartitions
,
365 &MasterBootRecord
->PartitionTable
[i
],
366 &Partitions
->PartitionEntry
[NbPartitions
]))
368 Partitions
->PartitionEntry
[NbPartitions
].PartitionNumber
= NbPartitions
+ 1;
372 if (MasterBootRecord
->PartitionTable
[i
].SystemIndicator
== PARTITION_EXTENDED
||
373 MasterBootRecord
->PartitionTable
[i
].SystemIndicator
== PARTITION_XINT13_EXTENDED
)
375 /* FIXME: unhandled case; copy partitions */
380 Partitions
->PartitionCount
= NbPartitions
;
381 Partitions
->Signature
= MasterBootRecord
->Signature
;
382 ExFreePool(MasterBootRecord
);
384 *PartitionBuffer
= Partitions
;
385 return STATUS_SUCCESS
;