Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpartition.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #ifndef _M_ARM 00021 #include <freeldr.h> 00022 #include <debug.h> 00023 00024 DBG_DEFAULT_CHANNEL(DISK); 00025 00026 BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, 00027 PPARTITION_TABLE_ENTRY PartitionTableEntry, 00028 ULONG *ActivePartition) 00029 { 00030 ULONG BootablePartitionCount = 0; 00031 MASTER_BOOT_RECORD MasterBootRecord; 00032 00033 *ActivePartition = 0; 00034 // Read master boot record 00035 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) 00036 { 00037 return FALSE; 00038 } 00039 00040 // Count the bootable partitions 00041 if (MasterBootRecord.PartitionTable[0].BootIndicator == 0x80) 00042 { 00043 BootablePartitionCount++; 00044 *ActivePartition = 1; 00045 } 00046 if (MasterBootRecord.PartitionTable[1].BootIndicator == 0x80) 00047 { 00048 BootablePartitionCount++; 00049 *ActivePartition = 2; 00050 } 00051 if (MasterBootRecord.PartitionTable[2].BootIndicator == 0x80) 00052 { 00053 BootablePartitionCount++; 00054 *ActivePartition = 3; 00055 } 00056 if (MasterBootRecord.PartitionTable[3].BootIndicator == 0x80) 00057 { 00058 BootablePartitionCount++; 00059 *ActivePartition = 4; 00060 } 00061 00062 // Make sure there was only one bootable partition 00063 if (BootablePartitionCount == 0) 00064 { 00065 ERR("No bootable (active) partitions found.\n"); 00066 return FALSE; 00067 } 00068 else if (BootablePartitionCount != 1) 00069 { 00070 ERR("Too many bootable (active) partitions found.\n"); 00071 return FALSE; 00072 } 00073 00074 // Copy the partition table entry 00075 RtlCopyMemory(PartitionTableEntry, 00076 &MasterBootRecord.PartitionTable[*ActivePartition - 1], 00077 sizeof(PARTITION_TABLE_ENTRY)); 00078 00079 return TRUE; 00080 } 00081 00082 BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) 00083 { 00084 MASTER_BOOT_RECORD MasterBootRecord; 00085 PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry; 00086 ULONG ExtendedPartitionNumber; 00087 ULONG ExtendedPartitionOffset; 00088 ULONG Index; 00089 00090 // Read master boot record 00091 if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) 00092 { 00093 return FALSE; 00094 } 00095 00096 // If they are asking for a primary 00097 // partition then things are easy 00098 if (PartitionNumber < 5) 00099 { 00100 // PartitionNumber is one-based and we need it zero-based 00101 PartitionNumber--; 00102 00103 // Copy the partition table entry 00104 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord.PartitionTable[PartitionNumber], sizeof(PARTITION_TABLE_ENTRY)); 00105 00106 return TRUE; 00107 } 00108 else 00109 { 00110 // They want an extended partition entry so we will need 00111 // to loop through all the extended partitions on the disk 00112 // and return the one they want. 00113 00114 ExtendedPartitionNumber = PartitionNumber - 5; 00115 00116 // Set the initial relative starting sector to 0 00117 // This is because extended partition starting 00118 // sectors a numbered relative to their parent 00119 ExtendedPartitionOffset = 0; 00120 00121 for (Index=0; Index<=ExtendedPartitionNumber; Index++) 00122 { 00123 // Get the extended partition table entry 00124 if (!DiskGetFirstExtendedPartitionEntry(&MasterBootRecord, &ExtendedPartitionTableEntry)) 00125 { 00126 return FALSE; 00127 } 00128 00129 // Adjust the relative starting sector of the partition 00130 ExtendedPartitionTableEntry.SectorCountBeforePartition += ExtendedPartitionOffset; 00131 if (ExtendedPartitionOffset == 0) 00132 { 00133 // Set the start of the parrent extended partition 00134 ExtendedPartitionOffset = ExtendedPartitionTableEntry.SectorCountBeforePartition; 00135 } 00136 // Read the partition boot record 00137 if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord)) 00138 { 00139 return FALSE; 00140 } 00141 00142 // Get the first real partition table entry 00143 if (!DiskGetFirstPartitionEntry(&MasterBootRecord, PartitionTableEntry)) 00144 { 00145 return FALSE; 00146 } 00147 00148 // Now correct the start sector of the partition 00149 PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionTableEntry.SectorCountBeforePartition; 00150 } 00151 00152 // When we get here we should have the correct entry 00153 // already stored in PartitionTableEntry 00154 // so just return TRUE 00155 return TRUE; 00156 } 00157 00158 } 00159 00160 BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) 00161 { 00162 ULONG Index; 00163 00164 for (Index=0; Index<4; Index++) 00165 { 00166 // Check the system indicator 00167 // If it's not an extended or unused partition 00168 // then we're done 00169 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_ENTRY_UNUSED) && 00170 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_EXTENDED) && 00171 (MasterBootRecord->PartitionTable[Index].SystemIndicator != PARTITION_XINT13_EXTENDED)) 00172 { 00173 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); 00174 return TRUE; 00175 } 00176 } 00177 00178 return FALSE; 00179 } 00180 00181 BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) 00182 { 00183 ULONG Index; 00184 00185 for (Index=0; Index<4; Index++) 00186 { 00187 // Check the system indicator 00188 // If it an extended partition then we're done 00189 if ((MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_EXTENDED) || 00190 (MasterBootRecord->PartitionTable[Index].SystemIndicator == PARTITION_XINT13_EXTENDED)) 00191 { 00192 RtlCopyMemory(PartitionTableEntry, &MasterBootRecord->PartitionTable[Index], sizeof(PARTITION_TABLE_ENTRY)); 00193 return TRUE; 00194 } 00195 } 00196 00197 return FALSE; 00198 } 00199 00200 BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) 00201 { 00202 ULONG Index; 00203 00204 // Read master boot record 00205 if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, (PVOID)DISKREADBUFFER)) 00206 { 00207 return FALSE; 00208 } 00209 RtlCopyMemory(BootRecord, (PVOID)DISKREADBUFFER, sizeof(MASTER_BOOT_RECORD)); 00210 00211 00212 TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber); 00213 TRACE("Boot record logical start sector = %d\n", LogicalSectorNumber); 00214 TRACE("sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD)); 00215 00216 for (Index=0; Index<4; Index++) 00217 { 00218 TRACE("-------------------------------------------\n"); 00219 TRACE("Partition %d\n", (Index + 1)); 00220 TRACE("BootIndicator: 0x%x\n", BootRecord->PartitionTable[Index].BootIndicator); 00221 TRACE("StartHead: 0x%x\n", BootRecord->PartitionTable[Index].StartHead); 00222 TRACE("StartSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].StartSector); 00223 TRACE("StartCylinder: 0x%x\n", BootRecord->PartitionTable[Index].StartCylinder); 00224 TRACE("SystemIndicator: 0x%x\n", BootRecord->PartitionTable[Index].SystemIndicator); 00225 TRACE("EndHead: 0x%x\n", BootRecord->PartitionTable[Index].EndHead); 00226 TRACE("EndSector (Plus 2 cylinder bits): 0x%x\n", BootRecord->PartitionTable[Index].EndSector); 00227 TRACE("EndCylinder: 0x%x\n", BootRecord->PartitionTable[Index].EndCylinder); 00228 TRACE("SectorCountBeforePartition: 0x%x\n", BootRecord->PartitionTable[Index].SectorCountBeforePartition); 00229 TRACE("PartitionSectorCount: 0x%x\n", BootRecord->PartitionTable[Index].PartitionSectorCount); 00230 } 00231 00232 // Check the partition table magic value 00233 if (BootRecord->MasterBootRecordMagic != 0xaa55) 00234 { 00235 return FALSE; 00236 } 00237 00238 return TRUE; 00239 } 00240 00241 NTSTATUS 00242 NTAPI 00243 IopReadBootRecord( 00244 IN PDEVICE_OBJECT DeviceObject, 00245 IN ULONGLONG LogicalSectorNumber, 00246 IN ULONG SectorSize, 00247 OUT PMASTER_BOOT_RECORD BootRecord) 00248 { 00249 ULONG FileId = (ULONG)DeviceObject; 00250 LARGE_INTEGER Position; 00251 ULONG BytesRead; 00252 ULONG Status; 00253 00254 Position.QuadPart = LogicalSectorNumber * SectorSize; 00255 Status = ArcSeek(FileId, &Position, SeekAbsolute); 00256 if (Status != ESUCCESS) 00257 return STATUS_IO_DEVICE_ERROR; 00258 00259 Status = ArcRead(FileId, BootRecord, SectorSize, &BytesRead); 00260 if (Status != ESUCCESS || BytesRead != SectorSize) 00261 return STATUS_IO_DEVICE_ERROR; 00262 00263 return STATUS_SUCCESS; 00264 } 00265 00266 BOOLEAN 00267 NTAPI 00268 IopCopyPartitionRecord( 00269 IN BOOLEAN ReturnRecognizedPartitions, 00270 IN ULONG SectorSize, 00271 IN PPARTITION_TABLE_ENTRY PartitionTableEntry, 00272 OUT PARTITION_INFORMATION *PartitionEntry) 00273 { 00274 BOOLEAN IsRecognized; 00275 00276 IsRecognized = TRUE; /* FIXME */ 00277 if (!IsRecognized && ReturnRecognizedPartitions) 00278 return FALSE; 00279 00280 PartitionEntry->StartingOffset.QuadPart = (ULONGLONG)PartitionTableEntry->SectorCountBeforePartition * SectorSize; 00281 PartitionEntry->PartitionLength.QuadPart = (ULONGLONG)PartitionTableEntry->PartitionSectorCount * SectorSize; 00282 PartitionEntry->HiddenSectors = 0; 00283 PartitionEntry->PartitionNumber = 0; /* Will be filled later */ 00284 PartitionEntry->PartitionType = PartitionTableEntry->SystemIndicator; 00285 PartitionEntry->BootIndicator = (PartitionTableEntry->BootIndicator & 0x80) ? TRUE : FALSE; 00286 PartitionEntry->RecognizedPartition = IsRecognized; 00287 PartitionEntry->RewritePartition = FALSE; 00288 00289 return TRUE; 00290 } 00291 00292 NTSTATUS 00293 FASTCALL 00294 IoReadPartitionTable( 00295 IN PDEVICE_OBJECT DeviceObject, 00296 IN ULONG SectorSize, 00297 IN BOOLEAN ReturnRecognizedPartitions, 00298 OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) 00299 { 00300 PMASTER_BOOT_RECORD MasterBootRecord; 00301 PDRIVE_LAYOUT_INFORMATION Partitions; 00302 ULONG NbPartitions, i, Size; 00303 NTSTATUS ret; 00304 00305 *PartitionBuffer = NULL; 00306 00307 if (SectorSize < sizeof(MASTER_BOOT_RECORD)) 00308 return STATUS_NOT_SUPPORTED; 00309 00310 MasterBootRecord = ExAllocatePool(NonPagedPool, SectorSize); 00311 if (!MasterBootRecord) 00312 return STATUS_NO_MEMORY; 00313 00314 /* Read disk MBR */ 00315 ret = IopReadBootRecord(DeviceObject, 0, SectorSize, MasterBootRecord); 00316 if (!NT_SUCCESS(ret)) 00317 { 00318 ExFreePool(MasterBootRecord); 00319 return ret; 00320 } 00321 00322 /* Check validity of boot record */ 00323 if (MasterBootRecord->MasterBootRecordMagic != 0xaa55) 00324 { 00325 ExFreePool(MasterBootRecord); 00326 return STATUS_NOT_SUPPORTED; 00327 } 00328 00329 /* Count number of partitions */ 00330 NbPartitions = 0; 00331 for (i = 0; i < 4; i++) 00332 { 00333 NbPartitions++; 00334 00335 if (MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_EXTENDED || 00336 MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_XINT13_EXTENDED) 00337 { 00338 /* FIXME: unhandled case; count number of partitions */ 00339 UNIMPLEMENTED; 00340 } 00341 } 00342 00343 if (NbPartitions == 0) 00344 { 00345 ExFreePool(MasterBootRecord); 00346 return STATUS_NOT_SUPPORTED; 00347 } 00348 00349 /* Allocation space to store partitions */ 00350 Size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) + 00351 NbPartitions * sizeof(PARTITION_INFORMATION); 00352 Partitions = ExAllocatePool(NonPagedPool, Size); 00353 if (!Partitions) 00354 { 00355 ExFreePool(MasterBootRecord); 00356 return STATUS_NO_MEMORY; 00357 } 00358 00359 /* Count number of partitions */ 00360 NbPartitions = 0; 00361 for (i = 0; i < 4; i++) 00362 { 00363 if (IopCopyPartitionRecord(ReturnRecognizedPartitions, 00364 SectorSize, 00365 &MasterBootRecord->PartitionTable[i], 00366 &Partitions->PartitionEntry[NbPartitions])) 00367 { 00368 Partitions->PartitionEntry[NbPartitions].PartitionNumber = NbPartitions + 1; 00369 NbPartitions++; 00370 } 00371 00372 if (MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_EXTENDED || 00373 MasterBootRecord->PartitionTable[i].SystemIndicator == PARTITION_XINT13_EXTENDED) 00374 { 00375 /* FIXME: unhandled case; copy partitions */ 00376 UNIMPLEMENTED; 00377 } 00378 } 00379 00380 Partitions->PartitionCount = NbPartitions; 00381 Partitions->Signature = MasterBootRecord->Signature; 00382 ExFreePool(MasterBootRecord); 00383 00384 *PartitionBuffer = Partitions; 00385 return STATUS_SUCCESS; 00386 } 00387 00388 #endif Generated on Sat May 26 2012 04:17:55 for ReactOS by
1.7.6.1
|