ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

partition.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.