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.
23 BOOLEAN
DiskGetActivePartitionEntry(ULONG DriveNumber
,
24 PPARTITION_TABLE_ENTRY PartitionTableEntry
,
25 ULONG
*ActivePartition
)
27 ULONG BootablePartitionCount
= 0;
28 MASTER_BOOT_RECORD MasterBootRecord
;
31 // Read master boot record
32 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
37 // Count the bootable partitions
38 if (MasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
40 BootablePartitionCount
++;
43 if (MasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
45 BootablePartitionCount
++;
48 if (MasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
50 BootablePartitionCount
++;
53 if (MasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
55 BootablePartitionCount
++;
59 // Make sure there was only one bootable partition
60 if (BootablePartitionCount
== 0)
62 DPRINTM(DPRINT_DISK
, "No bootable (active) partitions found.\n");
65 else if (BootablePartitionCount
!= 1)
67 DPRINTM(DPRINT_DISK
, "Too many bootable (active) partitions found.\n");
71 // Copy the partition table entry
72 RtlCopyMemory(PartitionTableEntry
,
73 &MasterBootRecord
.PartitionTable
[*ActivePartition
- 1],
74 sizeof(PARTITION_TABLE_ENTRY
));
79 BOOLEAN
DiskGetPartitionEntry(ULONG DriveNumber
, ULONG PartitionNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
81 MASTER_BOOT_RECORD MasterBootRecord
;
82 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry
;
83 ULONG ExtendedPartitionNumber
;
84 ULONG ExtendedPartitionOffset
;
87 // Read master boot record
88 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
93 // If they are asking for a primary
94 // partition then things are easy
95 if (PartitionNumber
< 5)
97 // PartitionNumber is one-based and we need it zero-based
100 // Copy the partition table entry
101 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[PartitionNumber
], sizeof(PARTITION_TABLE_ENTRY
));
107 // They want an extended partition entry so we will need
108 // to loop through all the extended partitions on the disk
109 // and return the one they want.
111 ExtendedPartitionNumber
= PartitionNumber
- 5;
113 // Set the initial relative starting sector to 0
114 // This is because extended partition starting
115 // sectors a numbered relative to their parent
116 ExtendedPartitionOffset
= 0;
118 for (Index
=0; Index
<=ExtendedPartitionNumber
; Index
++)
120 // Get the extended partition table entry
121 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord
, &ExtendedPartitionTableEntry
))
126 // Adjust the relative starting sector of the partition
127 ExtendedPartitionTableEntry
.SectorCountBeforePartition
+= ExtendedPartitionOffset
;
128 if (ExtendedPartitionOffset
== 0)
130 // Set the start of the parrent extended partition
131 ExtendedPartitionOffset
= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
133 // Read the partition boot record
134 if (!DiskReadBootRecord(DriveNumber
, ExtendedPartitionTableEntry
.SectorCountBeforePartition
, &MasterBootRecord
))
139 // Get the first real partition table entry
140 if (!DiskGetFirstPartitionEntry(&MasterBootRecord
, PartitionTableEntry
))
145 // Now correct the start sector of the partition
146 PartitionTableEntry
->SectorCountBeforePartition
+= ExtendedPartitionTableEntry
.SectorCountBeforePartition
;
149 // When we get here we should have the correct entry
150 // already stored in PartitionTableEntry
151 // so just return TRUE
157 BOOLEAN
DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
161 for (Index
=0; Index
<4; Index
++)
163 // Check the system indicator
164 // If it's not an extended or unused partition
166 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_ENTRY_UNUSED
) &&
167 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_EXTENDED
) &&
168 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_XINT13_EXTENDED
))
170 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
178 BOOLEAN
DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
182 for (Index
=0; Index
<4; Index
++)
184 // Check the system indicator
185 // If it an extended partition then we're done
186 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_EXTENDED
) ||
187 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_XINT13_EXTENDED
))
189 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
197 BOOLEAN
DiskReadBootRecord(ULONG DriveNumber
, ULONGLONG LogicalSectorNumber
, PMASTER_BOOT_RECORD BootRecord
)
202 // Read master boot record
203 if (!MachDiskReadLogicalSectors(DriveNumber
, LogicalSectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
207 RtlCopyMemory(BootRecord
, (PVOID
)DISKREADBUFFER
, sizeof(MASTER_BOOT_RECORD
));
210 DPRINTM(DPRINT_DISK
, "Dumping partition table for drive 0x%x:\n", DriveNumber
);
211 DPRINTM(DPRINT_DISK
, "Boot record logical start sector = %d\n", LogicalSectorNumber
);
212 DPRINTM(DPRINT_DISK
, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
));
214 for (Index
=0; Index
<4; Index
++)
216 DPRINTM(DPRINT_DISK
, "-------------------------------------------\n");
217 DPRINTM(DPRINT_DISK
, "Partition %d\n", (Index
+ 1));
218 DPRINTM(DPRINT_DISK
, "BootIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].BootIndicator
);
219 DPRINTM(DPRINT_DISK
, "StartHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartHead
);
220 DPRINTM(DPRINT_DISK
, "StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].StartSector
);
221 DPRINTM(DPRINT_DISK
, "StartCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartCylinder
);
222 DPRINTM(DPRINT_DISK
, "SystemIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].SystemIndicator
);
223 DPRINTM(DPRINT_DISK
, "EndHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndHead
);
224 DPRINTM(DPRINT_DISK
, "EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].EndSector
);
225 DPRINTM(DPRINT_DISK
, "EndCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndCylinder
);
226 DPRINTM(DPRINT_DISK
, "SectorCountBeforePartition: 0x%x\n", BootRecord
->PartitionTable
[Index
].SectorCountBeforePartition
);
227 DPRINTM(DPRINT_DISK
, "PartitionSectorCount: 0x%x\n", BootRecord
->PartitionTable
[Index
].PartitionSectorCount
);
230 // Check the partition table magic value
231 if (BootRecord
->MasterBootRecordMagic
!= 0xaa55)
233 sprintf(ErrMsg
, "Invalid partition table magic 0x%x found on drive 0x%lx",
234 BootRecord
->MasterBootRecordMagic
, DriveNumber
);
235 DiskError(ErrMsg
, 0);