Ejemplo n.º 1
0
        public static TOCBlock ReadFromDisk(Disk disk, PrivateHeader privateHeader, bool usePrimaryTOC)
        {
            ulong sectorIndex;

            if (usePrimaryTOC)
            {
                sectorIndex = privateHeader.PrivateRegionStartLBA + privateHeader.PrimaryTocLBA;
            }
            else
            {
                sectorIndex = privateHeader.PrivateRegionStartLBA + privateHeader.SecondaryTocLBA;
            }

            byte[] sector    = disk.ReadSector((long)sectorIndex);
            string signature = ByteReader.ReadAnsiString(sector, 0x00, 8);

            if (signature == TOCBlockSignature)
            {
                TOCBlock tocBlock = new TOCBlock(sector);
                if (tocBlock.IsChecksumValid)
                {
                    return(tocBlock);
                }
            }

            return(null);
        }
        public static long FindUnusedRegion(PrivateHeader privateHeader, TOCBlock tocBlock, int sectorCount)
        {
            bool[] bitmap = GetPrivateRegionUsageBitmap(privateHeader, tocBlock);
            // Reserve the first, second, third, third-last and second-last sectors for TOCBlocks
            bitmap[0] = true;
            bitmap[1] = true;
            bitmap[2] = true;
            bitmap[privateHeader.PrivateRegionSizeLBA - 3] = true;
            bitmap[privateHeader.PrivateRegionSizeLBA - 2] = true;

            int startIndex = 0;
            int freeCount  = 0;

            for (int index = 0; index < bitmap.Length; index++)
            {
                if (bitmap[index] == false) // free
                {
                    if (freeCount == 0)
                    {
                        startIndex = index;
                    }
                    freeCount++;
                    if (freeCount == sectorCount)
                    {
                        return((long)privateHeader.PrivateRegionStartLBA + startIndex);
                    }
                }
                else
                {
                    freeCount = 0;
                }
            }

            return(-1);
        }
Ejemplo n.º 3
0
        public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, KernelUpdateLogPage record)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.LogStart + record.PageIndex;

            byte[] sector = record.GetBytes();
            disk.WriteSectors((long)sectorIndex, sector);
        }
        public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, VolumeManagerDatabaseHeader header)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;

            byte[] bytes = header.GetBytes();
            disk.WriteSectors((long)sectorIndex, bytes);
        }
Ejemplo n.º 5
0
        public static TOCBlock ReadFromDisk(Disk disk, PrivateHeader privateHeader)
        {
            TOCBlock tocBlock = ReadFromDisk(disk, privateHeader, true);

            if (tocBlock == null)
            {
                tocBlock = ReadFromDisk(disk, privateHeader, false);
            }
            return(tocBlock);
        }
Ejemplo n.º 6
0
        public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader)
        {
            TOCBlock tocBlock = TOCBlock.ReadFromDisk(disk, privateHeader);

            if (tocBlock != null)
            {
                return(ReadFromDisk(disk, privateHeader, tocBlock));
            }
            return(null);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// This method will write privateHeader to disk as well
 /// </summary>
 public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     privateHeader.UpdateSequenceNumber++;
     tocBlock.UpdateSequenceNumber++;
     byte[] bytes = tocBlock.GetBytes();
     disk.WriteSectors((long)(privateHeader.PrivateRegionStartLBA + privateHeader.PreviousPrimaryTocLBA), bytes);
     disk.WriteSectors((long)(privateHeader.PrivateRegionStartLBA + privateHeader.PreviousSecondaryTocLBA), bytes);
     privateHeader.PrimaryTocLBA   = privateHeader.PreviousPrimaryTocLBA;
     privateHeader.SecondaryTocLBA = privateHeader.PreviousSecondaryTocLBA;
     PrivateHeader.WriteToDisk(disk, privateHeader);
 }
 // The secondary TOC is usually alternated between the third-last and the second-last sectors of the private region.
 public static long FindUnusedLBAForSecondaryToc(PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     bool[] bitmap = GetPrivateRegionUsageBitmap(privateHeader, tocBlock);
     for (int index = bitmap.Length - 1; index >= 0; index--)
     {
         if (bitmap[index] == false)
         {
             return((long)privateHeader.PrivateRegionStartLBA + index);
         }
     }
     return(-1);
 }
Ejemplo n.º 9
0
 public void SetLastEntry(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, ulong committedTransactionID, ulong pendingTransactionID)
 {
     if (m_pages.Count > 0)
     {
         m_pages[0].SetLastEntry(committedTransactionID, pendingTransactionID);
         // Windows kernel stores the last committedTransactionID / pendingTransactionID in memory,
         // and it will overwrite the values we write as soon as dmadmin is started,
         // However, it doesn't seem to cause any issues
         KernelUpdateLogPage.WriteToDisk(disk, privateHeader, tocBlock, m_pages[0]);
     }
     else
     {
         throw new InvalidOperationException("KLog records have not been previously read from disk");
     }
 }
Ejemplo n.º 10
0
        public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, VolumeManagerDatabaseHeader header)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;

            byte[] headerBytes = header.GetBytes();
            if (disk.BytesPerSector > Length)
            {
                byte[] sectorBytes = disk.ReadSector((long)sectorIndex);
                ByteWriter.WriteBytes(sectorBytes, 0, headerBytes);
                disk.WriteSectors((long)sectorIndex, sectorBytes);
            }
            else
            {
                disk.WriteSectors((long)sectorIndex, headerBytes);
            }
        }
 public static DynamicDisk ReadFromDisk(Disk disk)
 {
     if (IsDynamicDisk(disk))
     {
         PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(disk);
         if (privateHeader != null)
         {
             TOCBlock tocBlock = TOCBlock.ReadFromDisk(disk, privateHeader);
             if (tocBlock != null)
             {
                 return(new DynamicDisk(disk, privateHeader, tocBlock));
             }
         }
     }
     return(null);
 }
Ejemplo n.º 12
0
        public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, KernelUpdateLogPage page)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.LogStart + (uint)(page.PageIndex * Length / disk.BytesPerSector);
            int   pageOffset  = ((int)page.PageIndex * Length) % disk.BytesPerSector;

            byte[] pageBytes = page.GetBytes();
            if (disk.BytesPerSector > Length)
            {
                byte[] sectorBytes = disk.ReadSector((long)sectorIndex);
                ByteWriter.WriteBytes(sectorBytes, pageOffset, pageBytes);
                disk.WriteSectors((long)sectorIndex, sectorBytes);
            }
            else
            {
                disk.WriteSectors((long)sectorIndex, pageBytes);
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// This method will write privateHeader to disk as well
        /// </summary>
        public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            privateHeader.UpdateSequenceNumber++;
            tocBlock.UpdateSequenceNumber++;
            byte[] tocBytes = tocBlock.GetBytes();
            if (disk.BytesPerSector > Length)
            {
                tocBytes = ByteUtils.Concatenate(tocBytes, new byte[disk.BytesPerSector - TOCBlock.Length]);
            }
            long alternatePrimaryTOCLBA   = PrivateRegionHelper.FindUnusedLBAForPrimaryToc(privateHeader, tocBlock);
            long alternateSecondaryTOCLBA = PrivateRegionHelper.FindUnusedLBAForSecondaryToc(privateHeader, tocBlock);

            disk.WriteSectors(alternatePrimaryTOCLBA, tocBytes);
            disk.WriteSectors(alternateSecondaryTOCLBA, tocBytes);
            privateHeader.PrimaryTocLBA   = (ulong)alternatePrimaryTOCLBA;
            privateHeader.SecondaryTocLBA = (ulong)alternateSecondaryTOCLBA;
            PrivateHeader.WriteToDisk(disk, privateHeader);
        }
Ejemplo n.º 14
0
        public static void WriteDatabaseRecordFragment(DynamicDisk disk, DatabaseRecordFragment fragment, int blockSize)
        {
            if (fragment.SequenceNumber < FirstSequenceNumber)
            {
                throw new ArgumentException("VBLK SequenceNumber must start from 4");
            }

            PrivateHeader privateHeader      = disk.PrivateHeader;
            TOCBlock      tocBlock           = disk.TOCBlock;
            ulong         sectorIndex        = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;
            int           fragmentsPerSector = (int)(disk.Disk.BytesPerSector / blockSize);

            sectorIndex += (ulong)(fragment.SequenceNumber / fragmentsPerSector);
            byte[] sectorBytes   = disk.Disk.ReadSector((long)sectorIndex);
            byte[] fragmentBytes = fragment.GetBytes(blockSize); // should we use the same database header?
            int    indexInSector = (int)(fragment.SequenceNumber % fragmentsPerSector);

            Array.Copy(fragmentBytes, 0, sectorBytes, indexInSector * blockSize, blockSize);
            disk.Disk.WriteSectors((long)sectorIndex, sectorBytes);
        }
        private static bool[] GetPrivateRegionUsageBitmap(PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            // usage bitmap:
            bool[] bitmap = new bool[privateHeader.PrivateRegionSizeLBA];
            bitmap[privateHeader.PrimaryPrivateHeaderLBA]   = true;
            bitmap[privateHeader.SecondaryPrivateHeaderLBA] = true;
            bitmap[privateHeader.PrimaryTocLBA]             = true;
            bitmap[privateHeader.SecondaryTocLBA]           = true;

            foreach (TOCRegion region in tocBlock.Regions)
            {
                for (int index = 0; index < (int)region.SizeLBA; index++)
                {
                    bitmap[(int)region.StartLBA + index] = true;
                }
            }
            return(bitmap);
        }
Ejemplo n.º 16
0
        public static VolumeManagerDatabaseHeader ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;

            byte[] sector    = disk.ReadSector((long)sectorIndex);
            string signature = ByteReader.ReadAnsiString(sector, 0x00, 4);

            if (signature == VolumeManagerDatabaseSignature)
            {
                return(new VolumeManagerDatabaseHeader(sector));
            }
            else
            {
                return(null);
            }
        }
 public DynamicDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     m_disk          = disk;
     m_privateHeader = privateHeader;
     m_tocBlock      = tocBlock;
 }
Ejemplo n.º 18
0
        public static KernelUpdateLogPage ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, int pageIndex)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.LogStart + (uint)(pageIndex * Length / disk.BytesPerSector);
            int   pageOffset  = (pageIndex * Length) % disk.BytesPerSector;

            byte[] sector = disk.ReadSector((long)sectorIndex);
            if (pageOffset > 0)
            {
                sector = ByteReader.ReadBytes(sector, pageOffset, Length);
            }
            KernelUpdateLogPage result = new KernelUpdateLogPage(sector);

            return(result);
        }
Ejemplo n.º 19
0
        public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            VolumeManagerDatabaseHeader databaseHeader = VolumeManagerDatabaseHeader.ReadFromDisk(disk, privateHeader, tocBlock);

            if (databaseHeader == null || !databaseHeader.IsVersionSupported)
            {
                return(null);
            }

            // The first VBLK entry is the subsequent entry to the VMDB header.
            // Note: On a disk with 4KB sectors, VBLKs will reside in the same sector as the VMDB header.
            ulong firstSector    = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart; // we skip the VMDB
            int   databaseLength = (int)(databaseHeader.HeaderSize + databaseHeader.NumberOfVBlks * databaseHeader.BlockSize);
            int   sectorCount    = (int)Math.Ceiling(databaseLength / (double)disk.BytesPerSector);

            byte[] databaseBytes     = disk.ReadSectors((long)firstSector, sectorCount);
            int    numberOfFragments = (int)(databaseHeader.NumberOfVBlks - FirstSequenceNumber);
            List <DatabaseRecord> databaseRecords = ReadDatabaseRecords(databaseBytes, (int)databaseHeader.HeaderSize, (int)databaseHeader.BlockSize, numberOfFragments);

            // read all KLog blocks
            KernelUpdateLog kernelUpdateLog = KernelUpdateLog.ReadFromDisk(disk, privateHeader, tocBlock);
            DynamicDisk     dynamicDisk     = new DynamicDisk(disk, privateHeader, tocBlock);

            return(new VolumeManagerDatabaseCopy(dynamicDisk, databaseHeader, databaseRecords, kernelUpdateLog));
        }
        public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            VolumeManagerDatabaseHeader databaseHeader = VolumeManagerDatabaseHeader.ReadFromDisk(disk, privateHeader, tocBlock);

            if (databaseHeader == null)
            {
                return(null);
            }
            List <DatabaseRecord> databaseRecords = new List <DatabaseRecord>();

            // The first VBLK entry is the subsequent entry to the VMDB, which located at (ConfigurationStartLBA + Item1Start)
            ulong firstSector = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart + 1;  // we skip the VMDB
            int   sectorCount = (int)Math.Ceiling((long)databaseHeader.NumberOfVBlks * databaseHeader.BlockSize / (decimal)disk.BytesPerSector);

            byte[] databaseBytes = disk.ReadSectors((long)firstSector, sectorCount);

            // read all VBLK blocks:
            // Note: fragments are not necessarily contiguous!
            Dictionary <uint, List <DatabaseRecordFragment> > fragments = new Dictionary <uint, List <DatabaseRecordFragment> >();

            for (uint index = 0; index < databaseHeader.NumberOfVBlks - 4; index++)
            {
                byte[] fragmentBytes = new byte[databaseHeader.BlockSize];
#warning long array index not supported
                Array.Copy(databaseBytes, (int)(index * databaseHeader.BlockSize), fragmentBytes, 0, (int)databaseHeader.BlockSize);
                DatabaseRecordFragment fragment = DatabaseRecordFragment.GetDatabaseRecordFragment(fragmentBytes);

                if (fragment != null) // null fragment means VBLK is empty
                {
                    if (fragments.ContainsKey(fragment.GroupNumber))
                    {
                        fragments[fragment.GroupNumber].Add(fragment);
                    }
                    else
                    {
                        List <DatabaseRecordFragment> recordFragments = new List <DatabaseRecordFragment>();
                        recordFragments.Add(fragment);
                        fragments.Add(fragment.GroupNumber, recordFragments);
                    }
                }
            }

            // We have all the fragments and we can now assemble the records:
            // We assume that fragments with lower FragmentNumber appear in the database before fragments
            // of the same group with higher FragmentNumber.
            foreach (List <DatabaseRecordFragment> recorFragments in fragments.Values)
            {
                DatabaseRecord databaseRecord = DatabaseRecord.GetDatabaseRecord(recorFragments);
                databaseRecords.Add(databaseRecord);
            }

            // read all KLog blocks
            KernelUpdateLog kernelUpdateLog = KernelUpdateLog.ReadFromDisk(disk, privateHeader, tocBlock);
            DynamicDisk     dynamicDisk     = new DynamicDisk(disk, privateHeader, tocBlock);
            return(new VolumeManagerDatabase(dynamicDisk, databaseHeader, databaseRecords, kernelUpdateLog));
        }
 public static long FindUnusedSector(PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     return(FindUnusedRegion(privateHeader, tocBlock, 1));
 }
Ejemplo n.º 22
0
        public static KernelUpdateLog ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            List <KernelUpdateLogPage> pages     = new List <KernelUpdateLogPage>();
            KernelUpdateLogPage        firstPage = KernelUpdateLogPage.ReadFromDisk(disk, privateHeader, tocBlock, 0);

            pages.Add(firstPage);
            for (int index = 2; index < firstPage.NumberOfPages; index++)
            {
                KernelUpdateLogPage page = KernelUpdateLogPage.ReadFromDisk(disk, privateHeader, tocBlock, index);
                pages.Add(page);
            }
            return(new KernelUpdateLog(pages));
        }
Ejemplo n.º 23
0
        public static KernelUpdateLogPage ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, int kLogIndex)
        {
            ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.LogStart + (uint)kLogIndex;

            byte[] sector = disk.ReadSector((long)sectorIndex);
            KernelUpdateLogPage result = new KernelUpdateLogPage(sector);

            return(result);
        }