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));
        }
Example #3
0
        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();
                    }
                }
            }
        }