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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 BOOL
DiskGetActivePartitionEntry(U32 DriveNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
31 U32 BootablePartitionCount
= 0;
32 MASTER_BOOT_RECORD MasterBootRecord
;
34 // Read master boot record
35 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
40 // Count the bootable partitions
41 if (MasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
43 BootablePartitionCount
++;
46 if (MasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
48 BootablePartitionCount
++;
51 if (MasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
53 BootablePartitionCount
++;
56 if (MasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
58 BootablePartitionCount
++;
62 // Make sure there was only one bootable partition
63 if (BootablePartitionCount
== 0)
65 DiskError("No bootable (active) partitions found.", 0);
68 else if (BootablePartitionCount
!= 1)
70 DiskError("Too many bootable (active) partitions found.", 0);
74 // Copy the partition table entry
75 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[BootPartition
], sizeof(PARTITION_TABLE_ENTRY
));
80 BOOL
DiskGetPartitionEntry(U32 DriveNumber
, U32 PartitionNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
82 MASTER_BOOT_RECORD MasterBootRecord
;
83 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry
;
84 U32 ExtendedPartitionNumber
;
85 U32 ExtendedPartitionOffset
;
88 // Read master boot record
89 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
94 // If they are asking for a primary
95 // partition then things are easy
96 if (PartitionNumber
< 5)
98 // PartitionNumber is one-based and we need it zero-based
101 // Copy the partition table entry
102 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[PartitionNumber
], sizeof(PARTITION_TABLE_ENTRY
));
108 // They want an extended partition entry so we will need
109 // to loop through all the extended partitions on the disk
110 // and return the one they want.
112 ExtendedPartitionNumber
= PartitionNumber
- 5;
114 // Set the initial relative starting sector to 0
115 // This is because extended partition starting
116 // sectors a numbered relative to their parent
117 ExtendedPartitionOffset
= 0;
119 for (Index
=0; Index
<=ExtendedPartitionNumber
; Index
++)
121 // Get the extended partition table entry
122 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord
, &ExtendedPartitionTableEntry
))
127 // Adjust the relative starting sector of the partition
128 ExtendedPartitionTableEntry
.SectorCountBeforePartition
+= ExtendedPartitionOffset
;
129 if (ExtendedPartitionOffset
== 0)
131 // Set the start of the parrent extended partition
132 ExtendedPartitionOffset
= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
134 // Read the partition boot record
135 if (!DiskReadBootRecord(DriveNumber
, ExtendedPartitionTableEntry
.SectorCountBeforePartition
, &MasterBootRecord
))
140 // Get the first real partition table entry
141 if (!DiskGetFirstPartitionEntry(&MasterBootRecord
, PartitionTableEntry
))
146 // Now correct the start sector of the partition
147 PartitionTableEntry
->SectorCountBeforePartition
+= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
150 // When we get here we should have the correct entry
151 // already stored in PartitionTableEntry
152 // so just return TRUE
158 BOOL
DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
162 for (Index
=0; Index
<4; Index
++)
164 // Check the system indicator
165 // If it's not an extended or unused partition
167 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_ENTRY_UNUSED
) &&
168 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_EXTENDED
) &&
169 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_XINT13_EXTENDED
))
171 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
179 BOOL
DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
183 for (Index
=0; Index
<4; Index
++)
185 // Check the system indicator
186 // If it an extended partition then we're done
187 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_EXTENDED
) ||
188 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_XINT13_EXTENDED
))
190 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
198 BOOL
DiskReadBootRecord(U32 DriveNumber
, U64 LogicalSectorNumber
, PMASTER_BOOT_RECORD BootRecord
)
205 // Read master boot record
206 if (!MachDiskReadLogicalSectors(DriveNumber
, LogicalSectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
210 RtlCopyMemory(BootRecord
, (PVOID
)DISKREADBUFFER
, sizeof(MASTER_BOOT_RECORD
));
215 DbgPrint((DPRINT_DISK
, "Dumping partition table for drive 0x%x:\n", DriveNumber
));
216 DbgPrint((DPRINT_DISK
, "Boot record logical start sector = %d\n", LogicalSectorNumber
));
217 DbgPrint((DPRINT_DISK
, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
)));
219 for (Index
=0; Index
<4; Index
++)
221 DbgPrint((DPRINT_DISK
, "-------------------------------------------\n"));
222 DbgPrint((DPRINT_DISK
, "Partition %d\n", (Index
+ 1)));
223 DbgPrint((DPRINT_DISK
, "BootIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].BootIndicator
));
224 DbgPrint((DPRINT_DISK
, "StartHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartHead
));
225 DbgPrint((DPRINT_DISK
, "StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].StartSector
));
226 DbgPrint((DPRINT_DISK
, "StartCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartCylinder
));
227 DbgPrint((DPRINT_DISK
, "SystemIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].SystemIndicator
));
228 DbgPrint((DPRINT_DISK
, "EndHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndHead
));
229 DbgPrint((DPRINT_DISK
, "EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].EndSector
));
230 DbgPrint((DPRINT_DISK
, "EndCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndCylinder
));
231 DbgPrint((DPRINT_DISK
, "SectorCountBeforePartition: 0x%x\n", BootRecord
->PartitionTable
[Index
].SectorCountBeforePartition
));
232 DbgPrint((DPRINT_DISK
, "PartitionSectorCount: 0x%x\n", BootRecord
->PartitionTable
[Index
].PartitionSectorCount
));
235 #endif // defined DEBUG
237 // Check the partition table magic value
238 if (BootRecord
->MasterBootRecordMagic
!= 0xaa55)
240 sprintf(ErrMsg
, "Invalid partition table magic 0x%x found on drive 0x%x",
241 BootRecord
->MasterBootRecordMagic
, DriveNumber
);
242 DiskError(ErrMsg
, 0);