private bool ReadEntries(GptHeader header) { _diskData.Position = header.PartitionEntriesLba * _diskGeometry.BytesPerSector; _entryBuffer = Utilities.ReadFully(_diskData, (int)(header.PartitionEntrySize * header.PartitionEntryCount)); if (header.EntriesCrc != CalcEntriesCrc()) { return(false); } return(true); }
/// <summary> /// Creates a new partition table on a disk. /// </summary> /// <param name="disk">The stream containing the disk data</param> /// <param name="diskGeometry">The geometry of the disk</param> /// <returns>An object to access the newly created partition table</returns> public static GuidPartitionTable Initialize(Stream disk, Geometry diskGeometry) { // Create the protective MBR partition record. BiosPartitionTable pt = BiosPartitionTable.Initialize(disk, diskGeometry); pt.CreatePrimaryByCylinder(0, diskGeometry.Cylinders - 1, BiosPartitionTypes.GptProtective, false); // Create the GPT headers, and blank-out the entry areas const int EntryCount = 128; const int EntrySize = 128; int entrySectors = ((EntryCount * EntrySize) + diskGeometry.BytesPerSector - 1) / diskGeometry.BytesPerSector; byte[] entriesBuffer = new byte[EntryCount * EntrySize]; // Prepare primary header GptHeader header = new GptHeader(diskGeometry.BytesPerSector); header.HeaderLba = 1; header.AlternateHeaderLba = (disk.Length / diskGeometry.BytesPerSector) - 1; header.FirstUsable = header.HeaderLba + entrySectors + 1; header.LastUsable = header.AlternateHeaderLba - entrySectors - 1; header.DiskGuid = Guid.NewGuid(); header.PartitionEntriesLba = 2; header.PartitionEntryCount = EntryCount; header.PartitionEntrySize = EntrySize; header.EntriesCrc = CalcEntriesCrc(entriesBuffer); // Write the primary header byte[] headerBuffer = new byte[diskGeometry.BytesPerSector]; header.WriteTo(headerBuffer, 0); disk.Position = header.HeaderLba * diskGeometry.BytesPerSector; disk.Write(headerBuffer, 0, headerBuffer.Length); // Calc alternate header header.HeaderLba = header.AlternateHeaderLba; header.AlternateHeaderLba = 1; header.PartitionEntriesLba = header.HeaderLba - entrySectors; // Write the alternate header header.WriteTo(headerBuffer, 0); disk.Position = header.HeaderLba * diskGeometry.BytesPerSector; disk.Write(headerBuffer, 0, headerBuffer.Length); return(new GuidPartitionTable(disk, diskGeometry)); }
public GptHeader(GptHeader toCopy) { Signature = toCopy.Signature; Version = toCopy.Version; HeaderSize = toCopy.HeaderSize; Crc = toCopy.Crc; HeaderLba = toCopy.HeaderLba; AlternateHeaderLba = toCopy.AlternateHeaderLba; FirstUsable = toCopy.FirstUsable; LastUsable = toCopy.LastUsable; DiskGuid = toCopy.DiskGuid; PartitionEntriesLba = toCopy.PartitionEntriesLba; PartitionEntryCount = toCopy.PartitionEntryCount; PartitionEntrySize = toCopy.PartitionEntrySize; EntriesCrc = toCopy.EntriesCrc; Buffer = new byte[toCopy.Buffer.Length]; Array.Copy(toCopy.Buffer, Buffer, Buffer.Length); }
private void Init(Stream disk, Geometry diskGeometry) { BiosPartitionTable bpt; try { bpt = new BiosPartitionTable(disk, diskGeometry); } catch (IOException ioe) { throw new IOException("Invalid GPT disk, protective MBR table not present or invalid", ioe); } if (bpt.Count != 1 || bpt[0].BiosType != BiosPartitionTypes.GptProtective) { throw new IOException("Invalid GPT disk, protective MBR table is not valid"); } _diskData = disk; _diskGeometry = diskGeometry; disk.Position = diskGeometry.BytesPerSector; byte[] sector = Utilities.ReadFully(disk, diskGeometry.BytesPerSector); _primaryHeader = new GptHeader(diskGeometry.BytesPerSector); if (!_primaryHeader.ReadFrom(sector, 0) || !ReadEntries(_primaryHeader)) { disk.Position = disk.Length - diskGeometry.BytesPerSector; disk.Read(sector, 0, sector.Length); _secondaryHeader = new GptHeader(diskGeometry.BytesPerSector); if (!_secondaryHeader.ReadFrom(sector, 0) || !ReadEntries(_secondaryHeader)) { throw new IOException("No valid GUID Partition Table found"); } // Generate from the primary table from the secondary one _primaryHeader = new GptHeader(_secondaryHeader); _primaryHeader.HeaderLba = _secondaryHeader.AlternateHeaderLba; _primaryHeader.AlternateHeaderLba = _secondaryHeader.HeaderLba; _primaryHeader.PartitionEntriesLba = 2; // If the disk is writeable, fix up the primary partition table based on the // (valid) secondary table. if (disk.CanWrite) { WritePrimaryHeader(); } } if (_secondaryHeader == null) { _secondaryHeader = new GptHeader(diskGeometry.BytesPerSector); disk.Position = disk.Length - diskGeometry.BytesPerSector; disk.Read(sector, 0, sector.Length); if (!_secondaryHeader.ReadFrom(sector, 0) || !ReadEntries(_secondaryHeader)) { // Generate from the secondary table from the primary one _secondaryHeader = new GptHeader(_primaryHeader); _secondaryHeader.HeaderLba = _secondaryHeader.AlternateHeaderLba; _secondaryHeader.AlternateHeaderLba = _secondaryHeader.HeaderLba; _secondaryHeader.PartitionEntriesLba = _secondaryHeader.HeaderLba - Utilities.RoundUp(_secondaryHeader.PartitionEntryCount * _secondaryHeader.PartitionEntrySize, diskGeometry.BytesPerSector); // If the disk is writeable, fix up the secondary partition table based on the // (valid) primary table. if (disk.CanWrite) { WriteSecondaryHeader(); } } } }