Example #1
0
 /// <summary>
 /// Creates a new FAT32 partition that covers the entire drive.
 /// </summary>
 /// <param name="aDisk">The disk to create the partition for.</param>
 /// <param name="bootable">Whether to mark the partition as bootable or not.</param>
 /// <returns>The new partition information.</returns>
 public static PartitionInfo CreateFAT32PartitionInfo(Hardware.Devices.DiskDevice aDisk, bool bootable)
 {
     //Can't remember why but we have to start at 3rd logical block
     //  - First sector (sector 0) is for the MBR
     //  - Why do we leave a second sector empty after it?
     return(new PartitionInfo(bootable, 0xC, 2U, (uint)(aDisk.BlockCount - 2)));
 }
Example #2
0
 public VolumeDescriptor(Hardware.Devices.DiskDevice disk, uint startBlock, uint numBlocks, byte[] data)
     : base(disk, 0, 0)
 {
     Code    = (TypeCodes)data[0];
     Id      = ByteConverter.GetASCIIStringFromASCII(data, 1, 5);
     Version = data[6];
 }
Example #3
0
 public PrimaryVolumeDescriptor(Hardware.Devices.DiskDevice disk, uint startBlock, uint numBlocks, byte[] data)
     : base(disk, startBlock, numBlocks, data)
 {
     SystemIdentifier                  = ByteConverter.GetASCIIStringFromASCII(data, 8, 32);
     VolumeIdentifier                  = ByteConverter.GetASCIIStringFromASCII(data, 40, 32);
     VolumeSpaceSize                   = ByteConverter.ToUInt32(data, 80);
     VolumeSetSize                     = ByteConverter.ToUInt16(data, 120);
     VolumeSequenceNumber              = ByteConverter.ToUInt16(data, 124);
     LogicalBlockSize                  = ByteConverter.ToUInt16(data, 128);
     PathTableSize                     = ByteConverter.ToUInt32(data, 132);
     Location_PathTable_TypeL          = ByteConverter.ToUInt32(data, 140);
     Location_PathTable_Optional_TypeL = ByteConverter.ToUInt32(data, 144);
     RootDirectory                     = new DirectoryRecord(data, 156, true);
     VolumeSetIdentifier               = ByteConverter.GetASCIIStringFromASCII(data, 190, 128);
     PublisherIdentifier               = ByteConverter.GetASCIIStringFromASCII(data, 318, 128);
     DataPreparerIdentifier            = ByteConverter.GetASCIIStringFromASCII(data, 446, 128);
     ApplicationIdentifier             = ByteConverter.GetASCIIStringFromASCII(data, 574, 128);
     CopyrightFileIdentifier           = ByteConverter.GetASCIIStringFromASCII(data, 702, 38);
     AbstractFileIdentifier            = ByteConverter.GetASCIIStringFromASCII(data, 740, 36);
     BibliographicFileIdentifier       = ByteConverter.GetASCIIStringFromASCII(data, 776, 37);
     VolumeCreationDateTime            = new DateTime(data, 813);
     VolumeModificationDateTime        = new DateTime(data, 830);
     VolumeExpirationDateTime          = new DateTime(data, 847);
     VolumeEffectiveDateTime           = new DateTime(data, 864);
     FileStructureVersion              = data[881];
 }
Example #4
0
        public ISO9660(Hardware.Devices.DiskDevice disk)
        {
            byte[]           data      = disk.NewBlockArray(1);
            VolumeDescriptor desciptor = null;
            uint             sector    = 0x10;

            do
            {
                disk.ReadBlock(sector, 1, data);
                desciptor = VolumeDescriptor.CreateDescriptor(disk, sector, 1);
                VolumeDescriptors.Add(desciptor);

                sector++;
            }while (desciptor.Code != VolumeDescriptor.TypeCodes.SetTerminator);
        }
Example #5
0
            public static VolumeDescriptor CreateDescriptor(Hardware.Devices.DiskDevice disk, uint startBlock, uint numBlocks)
            {
                byte[] data = disk.NewBlockArray(numBlocks);
                disk.ReadBlock(startBlock, numBlocks, data);

                switch ((TypeCodes)data[0])
                {
                case TypeCodes.BootRecord:
                    return(new BootRecord(disk, startBlock, numBlocks, data));

                case TypeCodes.Primary:
                    return(new PrimaryVolumeDescriptor(disk, startBlock, numBlocks, data));

                case TypeCodes.SetTerminator:
                    return(new SetTerminatorVolumeDescriptor(disk, startBlock, numBlocks, data));

                default:
                    return(new VolumeDescriptor(disk, startBlock, numBlocks, data));
                }
            }
Example #6
0
        /// <summary>
        /// Formats the specified using the specified partition informations.
        /// </summary>
        /// <param name="aDisk">The disk to format.</param>
        /// <param name="partitionInfos">The partition informations to use for the format.</param>
        public static void FormatDisk(Hardware.Devices.DiskDevice aDisk, List partitionInfos)
        {
            //Necessary to remove any trace of GPT:
            //  Overwrite first 256 sectors with 0s (should do the trick)
            aDisk.WriteBlock(0UL, 256U, null);

#if MBR_TRACE
            BasicConsole.WriteLine("Creating new MBR data...");
#endif
            byte[] newMBRData = new byte[512];

            newMBRData[0x1FE] = 0x55;
            newMBRData[0x1FF] = 0xAA;

#if MBR_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "Set signature: ") + newMBRData[0x1FE] + " " + newMBRData[0x1FF]);
            BasicConsole.DelayOutput(1);

            BasicConsole.WriteLine(((FOS_System.String) "Num new partitions: ") + partitionInfos.Count);
            BasicConsole.DelayOutput(1);
#endif

            uint part1Offset = 0x1BE;
            for (uint i = 0; i < partitionInfos.Count; i++)
            {
                PartitionInfo partInfo   = (PartitionInfo)partitionInfos[(int)i];
                uint          partOffset = part1Offset + (0x10 * i);
#if MBR_TRACE
                BasicConsole.WriteLine(((FOS_System.String) "Partition ") + i + " @ " + partOffset);
                BasicConsole.WriteLine(((FOS_System.String) "Bootable : ") + partInfo.Bootable);
                BasicConsole.WriteLine(((FOS_System.String) "SystemID : ") + partInfo.SystemID);
                BasicConsole.WriteLine(((FOS_System.String) "StartSector : ") + partInfo.StartSector);
                BasicConsole.WriteLine(((FOS_System.String) "SectorCount : ") + partInfo.SectorCount);
                BasicConsole.DelayOutput(2);
#endif

                //Bootable / active
                newMBRData[partOffset + 0] = (byte)(partInfo.Bootable ? 0x81 : 0x00);
                //System ID
                newMBRData[partOffset + 4] = partInfo.SystemID;
                //Start sector
                newMBRData[partOffset + 8]  = (byte)(partInfo.StartSector);
                newMBRData[partOffset + 9]  = (byte)(partInfo.StartSector >> 8);
                newMBRData[partOffset + 10] = (byte)(partInfo.StartSector >> 16);
                newMBRData[partOffset + 11] = (byte)(partInfo.StartSector >> 24);
                //Sector count
                newMBRData[partOffset + 12] = (byte)(partInfo.SectorCount);
                newMBRData[partOffset + 13] = (byte)(partInfo.SectorCount >> 8);
                newMBRData[partOffset + 14] = (byte)(partInfo.SectorCount >> 16);
                newMBRData[partOffset + 15] = (byte)(partInfo.SectorCount >> 24);

#if MBR_TRACE
                BasicConsole.WriteLine("Reading back data...");
                byte   bootable    = newMBRData[partOffset + 0];
                byte   systemID    = newMBRData[partOffset + 4];
                UInt32 startSector = ByteConverter.ToUInt32(newMBRData, partOffset + 8);
                UInt32 sectorCount = ByteConverter.ToUInt32(newMBRData, partOffset + 12);
                BasicConsole.WriteLine(((FOS_System.String) "Bootable : ") + bootable);
                BasicConsole.WriteLine(((FOS_System.String) "SystemID : ") + systemID);
                BasicConsole.WriteLine(((FOS_System.String) "StartSector : ") + startSector);
                BasicConsole.WriteLine(((FOS_System.String) "SectorCount : ") + sectorCount);
                BasicConsole.DelayOutput(2);
#endif
            }

#if MBR_TRACE
            BasicConsole.WriteLine("Writing data...");
#endif
            aDisk.WriteBlock(0UL, 1U, newMBRData);
#if MBR_TRACE
            BasicConsole.WriteLine("Data written.");
            BasicConsole.DelayOutput(1);
#endif
            aDisk.CleanCaches();
        }
Example #7
0
        /// <summary>
        /// Initialises a new GPT and attempts to read its information from the specified disk.
        /// </summary>
        /// <param name="disk">The disk to read the GPT from.</param>
        public GPT(Hardware.Devices.DiskDevice disk)
        {
#if GPT_TRACE
            BasicConsole.WriteLine("Checking for GPT...");
            BasicConsole.DelayOutput(1);
#endif
            //Assumed block size of 512.
            uint blockSize = 512;

            //Note: The GPT format specifies a protective MBR entry (1 partition
            //          covering the entire disk) immediately followed (byte-wise)
            //          by the GPT. Thus the GPT must come at 512th byte.
            //      However, some disks can have 4096 bytes per sector (/block)
            //          so the code below might break as reading LBA 1 (2nd LBA) would
            //          return the wrong data. We probably ought to find some way to
            //          check the block size and just load the required amount of data.

            //Check for single MBR partition with 0xEE system ID
            byte[] blockData = new byte[blockSize];
            //Read the first sector of data.
            disk.ReadBlock(0UL, 1U, blockData);

            //Attempt to read the MBR
            MBR TheMBR = new MBR(blockData);
            //If the MBR isn't valid, the protective MBR partition specified as part of GPT
            //  isn't present / valid so this isn't a valid GPT.
            if (!TheMBR.IsValid)
            {
#if GPT_TRACE
                BasicConsole.WriteLine("MBR invalid.");
                BasicConsole.DelayOutput(1);
#endif

                return;
            }
            //Or, if there is not one and only one partition in the MBR then the
            //  protective MBR isn't valid so this isn't a valid GPT
            else if (TheMBR.NumPartitions != 1)
            {
#if GPT_TRACE
                BasicConsole.WriteLine("No partitions in MBR.");
                BasicConsole.DelayOutput(1);
#endif
                return;
            }
            //Or, the first (/only) partition entry has the wrong ID. 0xEE is the partition
            //  ID for a GOT formatted MBR partition.
            else if (TheMBR.Partitions[0].SystemID != 0xEE)
            {
#if GPT_TRACE
                BasicConsole.WriteLine(((FOS_System.String) "MBR partition 0 system ID not GPT. ") + TheMBR.Partitions[0].SystemID);
                BasicConsole.DelayOutput(1);
#endif

                return;
            }

#if GPT_TRACE
            BasicConsole.WriteLine("GPT MBR partition detected.");
            BasicConsole.DelayOutput(1);
#endif

            //Now we know this is very-likely to be GPT formatted.
            //  But we must check the GPT header for signature etc.

            //Read the GPT block
            disk.ReadBlock(1UL, 1U, blockData);

            //Check for GPT signature: 0x45 0x46 0x49 0x20 0x50 0x41 0x52 0x54
            bool OK = blockData[0] == 0x45;
            OK = OK && blockData[1] == 0x46;
            OK = OK && blockData[2] == 0x49;
            OK = OK && blockData[3] == 0x20;
            OK = OK && blockData[4] == 0x50;
            OK = OK && blockData[5] == 0x41;
            OK = OK && blockData[6] == 0x52;
            OK = OK && blockData[7] == 0x54;

            //If any part of the ID was wrong, this is not a valid GPT.
            if (!OK)
            {
#if GPT_TRACE
                BasicConsole.WriteLine("GPT signature invalid.");
                BasicConsole.DelayOutput(1);
#endif
                return;
            }

            //Now we know, this is a valid GPT. Whether or not the actual entries are valid
            //  is yet to be determined. There is of course the small chance that some other
            //  data has conflicted with GPT data and that this isn't a GPT, it just looks
            //  like it. If that is the case, what idiot formatted the disk we are reading
            //  because a conflict like that is impossible to detect without user input!
            IsValid = true;

#if GPT_TRACE
            BasicConsole.WriteLine("Valid GPT detected.");
            BasicConsole.DelayOutput(5);
#endif

            //Load-in GPT global data
            Revision                    = ByteConverter.ToUInt32(blockData, 8);
            HeaderSize                  = ByteConverter.ToUInt32(blockData, 12);
            HeaderCRC32                 = ByteConverter.ToUInt32(blockData, 16);
            HeaderLBA                   = ByteConverter.ToUInt64(blockData, 24);
            HeaderBackupLBA             = ByteConverter.ToUInt64(blockData, 32);
            FirstUsableLBAForPartitions = ByteConverter.ToUInt64(blockData, 40);
            LastUsableLBAForPartitions  = ByteConverter.ToUInt64(blockData, 48);

#if GPT_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "Revision : ") + Revision);
            BasicConsole.WriteLine(((FOS_System.String) "Header size : ") + HeaderSize);
            BasicConsole.WriteLine(((FOS_System.String) "Header CRC32 : ") + HeaderCRC32);
            BasicConsole.WriteLine(((FOS_System.String) "Header LBA : ") + HeaderLBA);
            BasicConsole.WriteLine(((FOS_System.String) "Header Backup LBA : ") + HeaderBackupLBA);
            BasicConsole.WriteLine(((FOS_System.String) "First usable LBA for partitions : ") + FirstUsableLBAForPartitions);
            BasicConsole.WriteLine(((FOS_System.String) "Last usable LBA for partitions : ") + LastUsableLBAForPartitions);
            BasicConsole.DelayOutput(5);
#endif

            //Load the disk ID
            DiskGUID     = new byte[16];
            DiskGUID[0]  = blockData[56];
            DiskGUID[1]  = blockData[57];
            DiskGUID[2]  = blockData[58];
            DiskGUID[3]  = blockData[59];
            DiskGUID[4]  = blockData[60];
            DiskGUID[5]  = blockData[61];
            DiskGUID[6]  = blockData[62];
            DiskGUID[7]  = blockData[63];
            DiskGUID[8]  = blockData[64];
            DiskGUID[9]  = blockData[65];
            DiskGUID[10] = blockData[66];
            DiskGUID[11] = blockData[67];
            DiskGUID[12] = blockData[68];
            DiskGUID[13] = blockData[69];
            DiskGUID[14] = blockData[70];
            DiskGUID[15] = blockData[71];

            //Load more global GPT data
            StartingLBAOfPartitionArray = ByteConverter.ToUInt64(blockData, 72);
            NumPartitionEntries         = ByteConverter.ToUInt32(blockData, 80);
            SizeOfPartitionEntry        = ByteConverter.ToUInt32(blockData, 84);
            PartitionArrayCRC32         = ByteConverter.ToUInt32(blockData, 88);

#if GPT_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "Start LBA of part arrray : ") + StartingLBAOfPartitionArray);
            BasicConsole.WriteLine(((FOS_System.String) "Num part entries : ") + NumPartitionEntries);
            BasicConsole.WriteLine(((FOS_System.String) "Size of part entry : ") + SizeOfPartitionEntry);
            BasicConsole.WriteLine(((FOS_System.String) "Part array CRC32 : ") + PartitionArrayCRC32);
            BasicConsole.DelayOutput(5);
#endif

            ulong blockNum        = StartingLBAOfPartitionArray;
            uint  entriesPerBlock = blockSize / SizeOfPartitionEntry;

#if GPT_TRACE
            BasicConsole.WriteLine("Reading partition entries...");
            BasicConsole.WriteLine(((FOS_System.String) "blockNum=") + blockNum);
            BasicConsole.WriteLine(((FOS_System.String) "entriesPerBlock=") + entriesPerBlock);
            BasicConsole.DelayOutput(1);
#endif

            //TODO: Check the CRC32 values of the header and partition table
            //      are correct.
            //Note: By not checking the CRCs, we have the option to manually edit
            //      the GPT without rejecting it if CRCs end up incorrect.
            //TODO: Add an override option to ignore the CRCs
            //TODO: Add a method to update / correct the CRCs

            //Read partition infos
            for (uint i = 0; i < NumPartitionEntries; i++)
            {
                //If we're on a block boundary, we need to load the next block
                //  of data to parse.
                if (i % entriesPerBlock == 0)
                {
#if GPT_TRACE
                    BasicConsole.WriteLine("Reading block data...");
                    BasicConsole.WriteLine(((FOS_System.String) "blockNum=") + blockNum);
                    BasicConsole.DelayOutput(1);
#endif
                    //Load the next block of data
                    disk.ReadBlock(blockNum++, 1u, blockData);
                }

                //Calculate the offset into the current data block
                uint offset = (i % entriesPerBlock) * SizeOfPartitionEntry;
#if GPT_TRACE
                BasicConsole.WriteLine("Reading entry...");
                BasicConsole.WriteLine(((FOS_System.String) "offset=") + offset);
#endif
                //Attempt to load the partition info
                PartitionInfo inf = new PartitionInfo(blockData, offset, SizeOfPartitionEntry);
                //Partitions are marked as empty by an all-zero type ID. If the partition is empty,
                //  there is no point adding it.
                if (!inf.Empty)
                {
#if GPT_TRACE
                    BasicConsole.WriteLine("Entry not empty.");
#endif
                    //Add the non-empty partition
                    Partitions.Add(inf);
                }
#if GPT_TRACE
                else
                {
                    BasicConsole.WriteLine("Entry empty.");
                }
#endif
            }
        }
Example #8
0
 public SetTerminatorVolumeDescriptor(Hardware.Devices.DiskDevice disk, uint startBlock, uint numBlocks, byte[] data)
     : base(disk, startBlock, numBlocks, data)
 {
 }
Example #9
0
 public BootRecord(Hardware.Devices.DiskDevice disk, uint startBlock, uint numBlocks, byte[] data)
     : base(disk, startBlock, numBlocks, data)
 {
     BootSystemIdentifier = ByteConverter.GetASCIIStringFromASCII(data, 7, 32);
     BootSystem           = ByteConverter.GetASCIIStringFromASCII(data, 39, 32);
 }