/// <summary>
        /// Gets all of the disk ranges containing partition table data.
        /// </summary>
        /// <returns>Set of stream extents, indicated as byte offset from the start of the disk.</returns>
        public IEnumerable<StreamExtent> GetMetadataDiskExtents()
        {
            List<StreamExtent> extents = new List<StreamExtent>();

            uint partPos = _firstSector;
            while (partPos != 0)
            {
                extents.Add(new StreamExtent(((long)partPos) * Utilities.SectorSize, Utilities.SectorSize));

                _disk.Position = ((long)partPos) * Utilities.SectorSize;
                byte[] sector = Utilities.ReadFully(_disk, Utilities.SectorSize);
                if (sector[510] != 0x55 || sector[511] != 0xAA)
                {
                    throw new IOException("Invalid extended partition sector");
                }

                uint nextPartPos = 0;
                for (int offset = 0x1BE; offset <= 0x1EE; offset += 0x10)
                {
                    BiosPartitionRecord thisPart = new BiosPartitionRecord(sector, offset, partPos, -1);

                    if (thisPart.StartCylinder != 0 || thisPart.StartHead != 0 || thisPart.StartSector != 0)
                    {
                        if (thisPart.PartitionType == 0x05 || thisPart.PartitionType == 0x0F)
                        {
                            nextPartPos = _firstSector + thisPart.LBAStart;
                        }
                    }
                }

                partPos = nextPartPos;
            }

            return extents;
        }
Example #2
0
        public BiosPartitionRecord[] GetPartitions()
        {
            List <BiosPartitionRecord> result = new List <BiosPartitionRecord>();

            uint partPos = _firstSector;

            while (partPos != 0)
            {
                _disk.Position = ((long)partPos) * Utilities.SectorSize;
                byte[] sector = Utilities.ReadFully(_disk, Utilities.SectorSize);
                if (sector[510] != 0x55 || sector[511] != 0xAA)
                {
                    throw new IOException("Invalid extended partition sector");
                }

                uint nextPartPos = 0;
                for (int offset = 0x1BE; offset <= 0x1EE; offset += 0x10)
                {
                    BiosPartitionRecord thisPart = new BiosPartitionRecord(sector, offset, partPos, -1);

                    if (thisPart.StartCylinder != 0 || thisPart.StartHead != 0 || thisPart.StartSector != 0)
                    {
                        if (thisPart.PartitionType != 0x05 && thisPart.PartitionType != 0x0F)
                        {
                            result.Add(thisPart);
                        }
                        else
                        {
                            nextPartPos = _firstSector + thisPart.LBAStart;
                        }
                    }
                }

                partPos = nextPartPos;
            }

            return(result.ToArray());
        }
        public BiosPartitionRecord[] GetPartitions()
        {
            List<BiosPartitionRecord> result = new List<BiosPartitionRecord>();

            uint partPos = _firstSector;
            while (partPos != 0)
            {
                _disk.Position = (long)partPos * Utilities.SectorSize;
                byte[] sector = Utilities.ReadFully(_disk, Utilities.SectorSize);
                if (sector[510] != 0x55 || sector[511] != 0xAA)
                {
                    throw new IOException("Invalid extended partition sector");
                }

                uint nextPartPos = 0;
                for (int offset = 0x1BE; offset <= 0x1EE; offset += 0x10)
                {
                    BiosPartitionRecord thisPart = new BiosPartitionRecord(sector, offset, partPos, -1);

                    if (thisPart.StartCylinder != 0 || thisPart.StartHead != 0 || thisPart.StartSector != 0)
                    {
                        if (thisPart.PartitionType != 0x05 && thisPart.PartitionType != 0x0F)
                        {
                            result.Add(thisPart);
                        }
                        else
                        {
                            nextPartPos = _firstSector + thisPart.LBAStart;
                        }
                    }
                }

                partPos = nextPartPos;
            }

            return result.ToArray();
        }
Example #4
0
        /// <summary>
        /// Gets all of the disk ranges containing partition table data.
        /// </summary>
        /// <returns>Set of stream extents, indicated as byte offset from the start of the disk.</returns>
        public IEnumerable <StreamExtent> GetMetadataDiskExtents()
        {
            List <StreamExtent> extents = new List <StreamExtent>();

            uint partPos = _firstSector;

            while (partPos != 0)
            {
                extents.Add(new StreamExtent(((long)partPos) * Utilities.SectorSize, Utilities.SectorSize));

                _disk.Position = ((long)partPos) * Utilities.SectorSize;
                byte[] sector = Utilities.ReadFully(_disk, Utilities.SectorSize);
                if (sector[510] != 0x55 || sector[511] != 0xAA)
                {
                    throw new IOException("Invalid extended partition sector");
                }

                uint nextPartPos = 0;
                for (int offset = 0x1BE; offset <= 0x1EE; offset += 0x10)
                {
                    BiosPartitionRecord thisPart = new BiosPartitionRecord(sector, offset, partPos, -1);

                    if (thisPart.StartCylinder != 0 || thisPart.StartHead != 0 || thisPart.StartSector != 0)
                    {
                        if (thisPart.PartitionType == 0x05 || thisPart.PartitionType == 0x0F)
                        {
                            nextPartPos = _firstSector + thisPart.LBAStart;
                        }
                    }
                }

                partPos = nextPartPos;
            }

            return(extents);
        }
 internal BiosPartitionInfo(BiosPartitionTable table, BiosPartitionRecord record)
 {
     _table = table;
     _record = record;
 }
 private BiosPartitionRecord[] GetExtendedRecords(BiosPartitionRecord r)
 {
     return new BiosExtendedPartitionTable(_diskData, r.LBAStart).GetPartitions();
 }
 private void WriteRecord(int i, BiosPartitionRecord newRecord)
 {
     _diskData.Position = 0;
     byte[] bootSector = Utilities.ReadFully(_diskData, Utilities.SectorSize);
     newRecord.WriteTo(bootSector, 0x01BE + (i * 16));
     _diskData.Position = 0;
     _diskData.Write(bootSector, 0, bootSector.Length);
 }
 private static bool IsExtendedPartition(BiosPartitionRecord r)
 {
     return r.PartitionType == BiosPartitionTypes.Extended || r.PartitionType == BiosPartitionTypes.ExtendedLba;
 }
        private static BiosPartitionRecord[] ReadPrimaryRecords(byte[] bootSector)
        {
            BiosPartitionRecord[] records = new BiosPartitionRecord[4];
            for (int i = 0; i < 4; ++i)
            {
                records[i] = new BiosPartitionRecord(bootSector, 0x01BE + (i * 0x10), 0, i);
            }

            return records;
        }
 internal SparseStream Open(BiosPartitionRecord record)
 {
     return new SubStream(_diskData, Ownership.None, ((long)record.LBAStartAbsolute) * Utilities.SectorSize, ((long)record.LBALength) * Utilities.SectorSize);
 }
        /// <summary>
        /// Creates a new Primary Partition, specified by Logical Block Addresses.
        /// </summary>
        /// <param name="first">The LBA address of the first sector (inclusive)</param>
        /// <param name="last">The LBA address of the last sector (inclusive)</param>
        /// <param name="type">The BIOS (MBR) type of the new partition</param>
        /// <param name="markActive">Whether to mark the partition active (bootable)</param>
        /// <returns>The index of the new partition</returns>
        public int CreatePrimaryBySector(long first, long last, byte type, bool markActive)
        {
            if (first >= last)
            {
                throw new ArgumentException("The first sector in a partition must be before the last");
            }

            if ((last + 1) * _diskGeometry.BytesPerSector > _diskData.Length)
            {
                throw new ArgumentOutOfRangeException("last", last, "The last sector extends beyond the end of the disk");
            }

            BiosPartitionRecord[] existing = GetPrimaryRecords();

            BiosPartitionRecord newRecord = new BiosPartitionRecord();
            ChsAddress startAddr = _diskGeometry.ToChsAddress(first);
            ChsAddress endAddr = _diskGeometry.ToChsAddress(last);

            // Because C/H/S addresses can max out at lower values than the LBA values,
            // the special tuple (1023, 254, 63) is used.
            if (startAddr.Cylinder > 1023)
            {
                startAddr = new ChsAddress(1023, 254, 63);
            }

            if (endAddr.Cylinder > 1023)
            {
                endAddr = new ChsAddress(1023, 254, 63);
            }

            newRecord.StartCylinder = (ushort)startAddr.Cylinder;
            newRecord.StartHead = (byte)startAddr.Head;
            newRecord.StartSector = (byte)startAddr.Sector;
            newRecord.EndCylinder = (ushort)endAddr.Cylinder;
            newRecord.EndHead = (byte)endAddr.Head;
            newRecord.EndSector = (byte)endAddr.Sector;
            newRecord.LBAStart = (uint)first;
            newRecord.LBALength = (uint)(last - first + 1);
            newRecord.PartitionType = type;
            newRecord.Status = (byte)(markActive ? 0x80 : 0x00);

            // First check for overlap with existing partition...
            foreach (var r in existing)
            {
                if (Utilities.RangesOverlap((uint)first, (uint)last + 1, r.LBAStartAbsolute, r.LBAStartAbsolute + r.LBALength))
                {
                    throw new IOException("New partition overlaps with existing partition");
                }
            }

            // Now look for empty partition
            for (int i = 0; i < 4; ++i)
            {
                if (!existing[i].IsValid)
                {
                    WriteRecord(i, newRecord);
                    return i;
                }
            }

            throw new IOException("No primary partition slots available");
        }
Example #12
0
 internal SparseStream Open(BiosPartitionRecord record)
 {
     return new SubStream(_diskData, Ownership.None, ((long)record.LBAStartAbsolute) * _diskGeometry.BytesPerSector, ((long)record.LBALength) * _diskGeometry.BytesPerSector);
 }