示例#1
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);
        }
示例#2
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));
                }
            }
示例#3
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
            }
        }