3 * Copyright (C) 1998-2002 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
DiskIsDriveRemovable(ULONG DriveNumber
)
31 // Hard disks use drive numbers >= 0x80
32 // So if the drive number indicates a hard disk
34 if (DriveNumber
>= 0x80)
39 // Drive is a floppy diskette so return TRUE
44 BOOL
DiskIsDriveCdRom(ULONG DriveNumber
)
49 // Hard disks use drive numbers >= 0x80
50 // So if the drive number indicates a hard disk
52 if ((DriveNumber
>= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber
)))
54 Sector
= AllocateMemory(2048);
56 if (!BiosInt13ReadExtended(DriveNumber
, 16, 1, Sector
))
58 DiskError("Disk read error.");
63 Result
= (Sector
[0] == 1 &&
75 // Drive is not CdRom so return FALSE
80 BOOL
DiskGetActivePartitionEntry(ULONG DriveNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
82 ULONG BootablePartitionCount
= 0;
83 MASTER_BOOT_RECORD MasterBootRecord
;
85 // Read master boot record
86 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
91 // Count the bootable partitions
92 if (MasterBootRecord
.PartitionTable
[0].BootIndicator
== 0x80)
94 BootablePartitionCount
++;
97 if (MasterBootRecord
.PartitionTable
[1].BootIndicator
== 0x80)
99 BootablePartitionCount
++;
102 if (MasterBootRecord
.PartitionTable
[2].BootIndicator
== 0x80)
104 BootablePartitionCount
++;
107 if (MasterBootRecord
.PartitionTable
[3].BootIndicator
== 0x80)
109 BootablePartitionCount
++;
113 // Make sure there was only one bootable partition
114 if (BootablePartitionCount
!= 1)
116 DiskError("Too many bootable partitions or none found.");
120 // Copy the partition table entry
121 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[BootPartition
], sizeof(PARTITION_TABLE_ENTRY
));
126 BOOL
DiskGetPartitionEntry(ULONG DriveNumber
, ULONG PartitionNumber
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
128 MASTER_BOOT_RECORD MasterBootRecord
;
129 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry
;
130 ULONG ExtendedPartitionNumber
;
133 // Read master boot record
134 if (!DiskReadBootRecord(DriveNumber
, 0, &MasterBootRecord
))
139 // If they are asking for a primary
140 // partition then things are easy
141 if (PartitionNumber
< 5)
143 // PartitionNumber is one-based and we need it zero-based
146 // Copy the partition table entry
147 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
.PartitionTable
[PartitionNumber
], sizeof(PARTITION_TABLE_ENTRY
));
153 // They want an extended partition entry so we will need
154 // to loop through all the extended partitions on the disk
155 // and return the one they want.
157 ExtendedPartitionNumber
= PartitionNumber
- 5;
159 for (Index
=0; Index
<=ExtendedPartitionNumber
; Index
++)
161 // Get the extended partition table entry
162 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord
, &ExtendedPartitionTableEntry
))
167 // Read the partition boot record
168 if (!DiskReadBootRecord(DriveNumber
, ExtendedPartitionTableEntry
.SectorCountBeforePartition
, &MasterBootRecord
))
173 // Get the first real partition table entry
174 if (!DiskGetFirstPartitionEntry(&MasterBootRecord
, PartitionTableEntry
))
180 // When we get here we should have the correct entry
181 // already stored in PartitionTableEntry
182 // so just return TRUE
188 BOOL
DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
192 for (Index
=0; Index
<4; Index
++)
194 // Check the system indicator
195 // If it's not an extended or unused partition
197 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_ENTRY_UNUSED
) &&
198 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_EXTENDED
) &&
199 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
!= PARTITION_XINT13_EXTENDED
))
201 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
209 BOOL
DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord
, PPARTITION_TABLE_ENTRY PartitionTableEntry
)
213 for (Index
=0; Index
<4; Index
++)
215 // Check the system indicator
216 // If it an extended partition then we're done
217 if ((MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_EXTENDED
) ||
218 (MasterBootRecord
->PartitionTable
[Index
].SystemIndicator
== PARTITION_XINT13_EXTENDED
))
220 RtlCopyMemory(PartitionTableEntry
, &MasterBootRecord
->PartitionTable
[Index
], sizeof(PARTITION_TABLE_ENTRY
));
228 BOOL
DiskReadBootRecord(ULONG DriveNumber
, ULONG LogicalSectorNumber
, PMASTER_BOOT_RECORD BootRecord
)
232 // Read master boot record
233 if (!DiskReadLogicalSectors(DriveNumber
, LogicalSectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
237 RtlCopyMemory(BootRecord
, (PVOID
)DISKREADBUFFER
, sizeof(MASTER_BOOT_RECORD
));
242 DbgPrint((DPRINT_DISK
, "Dumping partition table for drive 0x%x:\n", DriveNumber
));
243 DbgPrint((DPRINT_DISK
, "Boot record logical start sector = %d\n", LogicalSectorNumber
));
244 DbgPrint((DPRINT_DISK
, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD
)));
246 for (Index
=0; Index
<4; Index
++)
248 DbgPrint((DPRINT_DISK
, "-------------------------------------------\n"));
249 DbgPrint((DPRINT_DISK
, "Partition %d\n", (Index
+ 1)));
250 DbgPrint((DPRINT_DISK
, "BootIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].BootIndicator
));
251 DbgPrint((DPRINT_DISK
, "StartHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartHead
));
252 DbgPrint((DPRINT_DISK
, "StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].StartSector
));
253 DbgPrint((DPRINT_DISK
, "StartCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].StartCylinder
));
254 DbgPrint((DPRINT_DISK
, "SystemIndicator: 0x%x\n", BootRecord
->PartitionTable
[Index
].SystemIndicator
));
255 DbgPrint((DPRINT_DISK
, "EndHead: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndHead
));
256 DbgPrint((DPRINT_DISK
, "EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord
->PartitionTable
[Index
].EndSector
));
257 DbgPrint((DPRINT_DISK
, "EndCylinder: 0x%x\n", BootRecord
->PartitionTable
[Index
].EndCylinder
));
258 DbgPrint((DPRINT_DISK
, "SectorCountBeforePartition: 0x%x\n", BootRecord
->PartitionTable
[Index
].SectorCountBeforePartition
));
259 DbgPrint((DPRINT_DISK
, "PartitionSectorCount: 0x%x\n", BootRecord
->PartitionTable
[Index
].PartitionSectorCount
));
262 #endif // defined DEBUG
264 // Check the partition table magic value
265 if (BootRecord
->MasterBootRecordMagic
!= 0xaa55)
267 DiskError("Invalid partition table magic (0xaa55)");