/// <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; }
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(); }
/// <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"); }
internal SparseStream Open(BiosPartitionRecord record) { return new SubStream(_diskData, Ownership.None, ((long)record.LBAStartAbsolute) * _diskGeometry.BytesPerSector, ((long)record.LBALength) * _diskGeometry.BytesPerSector); }