Exemple #1
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            if ((stream.Length - Marshal.SizeOf <Footer>()) % 512 != 0)
            {
                return(false);
            }

            byte[] buffer = new byte[Marshal.SizeOf <Footer>()];
            stream.Seek(-buffer.Length, SeekOrigin.End);
            stream.Read(buffer, 0, buffer.Length);

            _footer = Marshal.ByteArrayToStructureLittleEndian <Footer>(buffer);

            string sig = StringHandlers.CToString(_footer.signature);

            var   regexSignature = new Regex(REGEX_DRI);
            Match matchSignature = regexSignature.Match(sig);

            if (!matchSignature.Success)
            {
                return(false);
            }

            if (_footer.bpb.sptrack * _footer.bpb.cylinders * _footer.bpb.heads != _footer.bpb.sectors)
            {
                return(false);
            }

            if ((_footer.bpb.sectors * _footer.bpb.bps) + Marshal.SizeOf <Footer>() != stream.Length)
            {
                return(false);
            }

            _imageInfo.Cylinders          = _footer.bpb.cylinders;
            _imageInfo.Heads              = _footer.bpb.heads;
            _imageInfo.SectorsPerTrack    = _footer.bpb.sptrack;
            _imageInfo.Sectors            = _footer.bpb.sectors;
            _imageInfo.SectorSize         = _footer.bpb.bps;
            _imageInfo.ApplicationVersion = matchSignature.Groups["version"].Value;

            _driImageFilter = imageFilter;

            _imageInfo.ImageSize            = (ulong)(stream.Length - Marshal.SizeOf <Footer>());
            _imageInfo.CreationTime         = imageFilter.GetCreationTime();
            _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();

            AaruConsole.DebugWriteLine("DRI DiskCopy plugin", "Image application = {0} version {1}",
                                       _imageInfo.Application, _imageInfo.ApplicationVersion);

            // Correct some incorrect data in images of NEC 2HD disks
            if (_imageInfo.Cylinders == 77 &&
                _imageInfo.Heads == 2 &&
                _imageInfo.SectorsPerTrack == 16 &&
                _imageInfo.SectorSize == 512 &&
                (_footer.bpb._driveCode == DriveCode.md2hd || _footer.bpb._driveCode == DriveCode.mf2hd))
            {
                _imageInfo.SectorsPerTrack = 8;
                _imageInfo.SectorSize      = 1024;
            }

            _imageInfo.MediaType = Geometry.GetMediaType(((ushort)_imageInfo.Cylinders, (byte)_imageInfo.Heads,
                                                          (ushort)_imageInfo.SectorsPerTrack, _imageInfo.SectorSize,
                                                          MediaEncoding.MFM, false));

            switch (_imageInfo.MediaType)
            {
            case MediaType.NEC_525_HD when _footer.bpb._driveCode == DriveCode.mf2hd ||
                _footer.bpb._driveCode == DriveCode.mf2ed:
                _imageInfo.MediaType = MediaType.NEC_35_HD_8;

                break;

            case MediaType.DOS_525_HD when _footer.bpb._driveCode == DriveCode.mf2hd ||
                _footer.bpb._driveCode == DriveCode.mf2ed:
                _imageInfo.MediaType = MediaType.NEC_35_HD_15;

                break;

            case MediaType.RX50 when _footer.bpb._driveCode == DriveCode.md2dd ||
                _footer.bpb._driveCode == DriveCode.md2hd:
                _imageInfo.MediaType = MediaType.ATARI_35_SS_DD;

                break;
            }

            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;

            AaruConsole.VerboseWriteLine("Digital Research DiskCopy image contains a disk of type {0}",
                                         _imageInfo.MediaType);

            return(true);
        }
Exemple #2
0
        static void Read(string devPath, Device dev, bool multiple)
        {
            uint   address   = 0;
            uint   blockSize = 512;
            ushort count     = 1;
            bool   byteAddr  = false;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for READ_{0}_BLOCK command:", multiple ? "MULTIPLE" : "SINGLE");
                AaruConsole.WriteLine("Read from {1}: {0}", address, byteAddr ? "byte" : "block");
                AaruConsole.WriteLine("Expected block size: {0} bytes", blockSize);

                if (multiple)
                {
                    AaruConsole.WriteLine("Will read {0} blocks", count);
                }

                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to MultiMediaCard commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to MultiMediaCard commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("Use byte addressing?: ");
                    strDev = System.Console.ReadLine();

                    if (!bool.TryParse(strDev, out byteAddr))
                    {
                        AaruConsole.WriteLine("Not a boolean. Press any key to continue...");
                        byteAddr = false;
                        System.Console.ReadKey();

                        continue;
                    }

                    AaruConsole.Write("Read from {0}?: ", byteAddr ? "byte" : "block");
                    strDev = System.Console.ReadLine();

                    if (!uint.TryParse(strDev, out address))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        address = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    if (multiple)
                    {
                        AaruConsole.Write("How many blocks to read?");
                        strDev = System.Console.ReadLine();

                        if (!ushort.TryParse(strDev, out count))
                        {
                            AaruConsole.WriteLine("Not a number. Press any key to continue...");
                            count = 1;
                            System.Console.ReadKey();

                            continue;
                        }
                    }

                    AaruConsole.Write("How many bytes to expect in a block?");
                    strDev = System.Console.ReadLine();

                    if (!uint.TryParse(strDev, out blockSize))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        blockSize = 512;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();

            bool sense = dev.Read(out byte[] buffer, out uint[] response, address, blockSize,
                                  multiple ? count : (ushort)1, byteAddr, dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending READ_{0}_BLOCK to the device:", multiple ? "MULTIPLE" : "SINGLE");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer));
            AaruConsole.WriteLine("Response has {0} elements.", response?.Length.ToString() ?? "null");
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print buffer.");
            AaruConsole.WriteLine("2.- Print response buffer.");
            AaruConsole.WriteLine("3.- Send command again.");
            AaruConsole.WriteLine("4.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to MultiMediaCard commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to MultiMediaCard commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ_{0}_BLOCK buffer:", multiple ? "MULTIPLE" : "SINGLE");

                if (buffer != null)
                {
                    PrintHex.PrintHexArray(buffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ_{0}_BLOCK response:", multiple ? "MULTIPLE" : "SINGLE");

                if (response != null)
                {
                    foreach (uint res in response)
                    {
                        AaruConsole.Write("0x{0:x8} ", res);
                    }

                    AaruConsole.WriteLine();
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 3: goto start;

            case 4: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #3
0
        static void SendExtendedCsd(string devPath, Device dev)
        {
start:
            System.Console.Clear();
            bool sense = dev.ReadExtendedCsd(out byte[] buffer, out uint[] response, dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending SEND_EXT_CSD to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer));
            AaruConsole.WriteLine("Response has {0} elements.", response?.Length.ToString() ?? "null");
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print buffer.");
            AaruConsole.WriteLine("2.- Decode buffer.");
            AaruConsole.WriteLine("3.- Print response buffer.");
            AaruConsole.WriteLine("4.- Send command again.");
            AaruConsole.WriteLine("0.- Return to MultiMediaCard commands menu.");
            AaruConsole.Write("Choose: ");

            string strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out int item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to MultiMediaCard commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("SEND_EXT_CSD buffer:");

                if (buffer != null)
                {
                    PrintHex.PrintHexArray(buffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("SEND_EXT_CSD decoded buffer:");

                if (buffer != null)
                {
                    AaruConsole.WriteLine("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(buffer));
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 3:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("SEND_EXT_CSD response:");

                if (response != null)
                {
                    foreach (uint res in response)
                    {
                        AaruConsole.Write("0x{0:x8} ", res);
                    }

                    AaruConsole.WriteLine();
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 4: goto start;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #4
0
        static void ReadSectors(string devPath, Device dev, bool retries)
        {
            ushort cylinder = 0;
            byte   head     = 0;
            byte   sector   = 1;
            byte   count    = 1;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for READ SECTORS {0}command:", retries ? "WITH RETRIES " : "");
                AaruConsole.WriteLine("Cylinder: {0}", cylinder);
                AaruConsole.WriteLine("Head: {0}", head);
                AaruConsole.WriteLine("Sector: {0}", sector);
                AaruConsole.WriteLine("Count: {0}", count);
                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to CHS ATA commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to CHS ATA commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("What cylinder?: ");
                    strDev = System.Console.ReadLine();

                    if (!ushort.TryParse(strDev, out cylinder))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        cylinder = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    AaruConsole.Write("What head?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out head))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        head = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    if (head > 15)
                    {
                        AaruConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15...");
                        head = 15;
                    }

                    AaruConsole.Write("What sector?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out sector))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        sector = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    AaruConsole.Write("How many sectors?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out count))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        count = 0;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();

            bool sense = dev.Read(out byte[] buffer, out AtaErrorRegistersChs errorRegisters, retries, cylinder, head,
                                  sector, count, dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending READ SECTORS {0}to the device:", retries ? "WITH RETRIES " : "");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer));
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print buffer.");
            AaruConsole.WriteLine("2.- Decode error registers.");
            AaruConsole.WriteLine("3.- Send command again.");
            AaruConsole.WriteLine("4.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to CHS ATA commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to CHS ATA commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ SECTORS {0}response:", retries ? "WITH RETRIES " : "");

                if (buffer != null)
                {
                    PrintHex.PrintHexArray(buffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ SECTORS {0}status registers:", retries ? "WITH RETRIES " : "");
                AaruConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters));
                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 3: goto start;

            case 4: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #5
0
        bool ScsiFindReadCommand()
        {
            if (Blocks == 0)
            {
                GetDeviceBlocks();
            }

            if (Blocks == 0)
            {
                return(true);
            }

            byte[] senseBuf;
            int    tries      = 0;
            uint   lba        = 0;
            bool   mediumScan = false;

            if (_dev.ScsiType == PeripheralDeviceTypes.OpticalDevice)
            {
                mediumScan = !_dev.MediumScan(out _, true, false, false, false, false, lba, 1, (uint)Blocks,
                                              out uint foundLba, out _, _timeout, out _);

                if (mediumScan)
                {
                    lba = foundLba;
                }
            }

            var rnd = new Random();

            while (tries < 10)
            {
                _read6 = !_dev.Read6(out _, out senseBuf, lba, LogicalBlockSize, _timeout, out _);

                _read10 = !_dev.Read10(out _, out senseBuf, 0, false, false, false, false, lba, LogicalBlockSize, 0, 1,
                                       _timeout, out _);

                _read12 = !_dev.Read12(out _, out senseBuf, 0, false, false, false, false, lba, LogicalBlockSize, 0, 1,
                                       false, _timeout, out _);

                _read16 = !_dev.Read16(out _, out senseBuf, 0, false, false, false, lba, LogicalBlockSize, 0, 1, false,
                                       _timeout, out _);

                if (_read6 ||
                    _read10 ||
                    _read12 ||
                    _read16)
                {
                    break;
                }

                lba = (uint)rnd.Next(1, (int)Blocks);

                if (mediumScan)
                {
                    mediumScan = !_dev.MediumScan(out _, true, false, false, false, false, lba, 1, (uint)Blocks,
                                                  out uint foundLba, out _, _timeout, out _);

                    if (mediumScan)
                    {
                        lba = foundLba;
                    }
                }

                tries++;
            }

            if (!_read6 &&
                !_read10 &&
                !_read12 &&
                !_read16)
            {
                // Magneto-opticals may have empty LBA 0 but we know they work with READ(12)
                if (_dev.ScsiType == PeripheralDeviceTypes.OpticalDevice)
                {
                    ErrorMessage = "Cannot read medium, aborting scan...";

                    return(true);
                }

                _read12 = true;
            }

            if (_read6 &&
                !_read10 &&
                !_read12 &&
                !_read16 &&
                Blocks > 0x001FFFFF + 1)
            {
                ErrorMessage =
                    $"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)";

                return(true);
            }

            if (Blocks > 0x001FFFFF + 1)
            {
                _read6 = false;
            }

            if (_read10)
            {
                _read12 = false;
            }

            if (!_read16 &&
                Blocks > 0xFFFFFFFF + (long)1)
            {
                ErrorMessage =
                    $"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)";

                return(true);
            }

            if (Blocks > 0xFFFFFFFF + (long)1)
            {
                _read10 = false;
                _read12 = false;
            }

            _seek6 = !_dev.Seek6(out senseBuf, lba, _timeout, out _);

            _seek10 = !_dev.Seek10(out senseBuf, lba, _timeout, out _);

            if (CanReadRaw)
            {
                bool testSense;
                CanReadRaw = false;

                if (_dev.ScsiType != PeripheralDeviceTypes.MultiMediaDevice)
                {
                    /*testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 0xFFFF, timeout, out duration);
                     * if (testSense && !dev.Error)
                     * {
                     *  decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
                     *  if (decSense.HasValue)
                     *  {
                     *      if (decSense.Value.SenseKey == Aaru.Decoders.SCSI.SenseKeys.IllegalRequest &&
                     *          decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
                     *      {
                     *          readRaw = true;
                     *          if (decSense.Value.InformationValid && decSense.Value.ILI)
                     *          {
                     *              longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
                     *              readLong16 = !dev.ReadLong16(out readBuffer, out senseBuf, false, 0, longBlockSize, timeout, out duration);
                     *          }
                     *      }
                     *  }
                     * }*/

                    testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, 0xFFFF, _timeout, out _);
                    FixedSense?decSense;

                    if (testSense && !_dev.Error)
                    {
                        decSense = Sense.DecodeFixed(senseBuf);

                        if (decSense?.SenseKey == SenseKeys.IllegalRequest &&
                            decSense.Value.ASC == 0x24 &&
                            decSense.Value.ASCQ == 0x00)
                        {
                            CanReadRaw = true;

                            if (decSense.Value.InformationValid &&
                                decSense.Value.ILI)
                            {
                                LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);

                                _readLong10 = !_dev.ReadLong10(out _, out senseBuf, false, false, 0,
                                                               (ushort)LongBlockSize, _timeout, out _);
                            }
                        }
                    }

                    if (CanReadRaw && LongBlockSize == LogicalBlockSize)
                    {
                        switch (LogicalBlockSize)
                        {
                        case 512:
                        {
                            foreach (ushort testSize in new ushort[]
                                {
                                    // Long sector sizes for floppies
                                    514,

                                    // Long sector sizes for SuperDisk
                                    536, 558,

                                    // Long sector sizes for 512-byte magneto-opticals
                                    600, 610, 630
                                })
                            {
                                testSense = _dev.ReadLong16(out _, out senseBuf, false, 0, testSize, _timeout,
                                                            out _);

                                if (!testSense &&
                                    !_dev.Error)
                                {
                                    _readLong16   = true;
                                    LongBlockSize = testSize;
                                    CanReadRaw    = true;

                                    break;
                                }

                                testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize,
                                                            _timeout, out _);

                                if (testSense || _dev.Error)
                                {
                                    continue;
                                }

                                _readLong10   = true;
                                LongBlockSize = testSize;
                                CanReadRaw    = true;

                                break;
                            }

                            break;
                        }

                        case 1024:
                        {
                            foreach (ushort testSize in new ushort[]
                                {
                                    // Long sector sizes for floppies
                                    1026,

                                    // Long sector sizes for 1024-byte magneto-opticals
                                    1200
                                })
                            {
                                testSense = _dev.ReadLong16(out _, out senseBuf, false, 0, testSize, _timeout,
                                                            out _);

                                if (!testSense &&
                                    !_dev.Error)
                                {
                                    _readLong16   = true;
                                    LongBlockSize = testSize;
                                    CanReadRaw    = true;

                                    break;
                                }

                                testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize,
                                                            _timeout, out _);

                                if (testSense || _dev.Error)
                                {
                                    continue;
                                }

                                _readLong10   = true;
                                LongBlockSize = testSize;
                                CanReadRaw    = true;

                                break;
                            }

                            break;
                        }

                        case 2048:
                        {
                            testSense = _dev.ReadLong16(out _, out senseBuf, false, 0, 2380, _timeout, out _);

                            if (!testSense &&
                                !_dev.Error)
                            {
                                _readLong16   = true;
                                LongBlockSize = 2380;
                                CanReadRaw    = true;
                            }
                            else
                            {
                                testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, 2380, _timeout,
                                                            out _);

                                if (!testSense &&
                                    !_dev.Error)
                                {
                                    _readLong10   = true;
                                    LongBlockSize = 2380;
                                    CanReadRaw    = true;
                                }
                            }

                            break;
                        }

                        case 4096:
                        {
                            testSense = _dev.ReadLong16(out _, out senseBuf, false, 0, 4760, _timeout, out _);

                            if (!testSense &&
                                !_dev.Error)
                            {
                                _readLong16   = true;
                                LongBlockSize = 4760;
                                CanReadRaw    = true;
                            }
                            else
                            {
                                testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, 4760, _timeout,
                                                            out _);

                                if (!testSense &&
                                    !_dev.Error)
                                {
                                    _readLong10   = true;
                                    LongBlockSize = 4760;
                                    CanReadRaw    = true;
                                }
                            }

                            break;
                        }

                        case 8192:
                        {
                            testSense = _dev.ReadLong16(out _, out senseBuf, false, 0, 9424, _timeout, out _);

                            if (!testSense &&
                                !_dev.Error)
                            {
                                _readLong16   = true;
                                LongBlockSize = 9424;
                                CanReadRaw    = true;
                            }
                            else
                            {
                                testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, 9424, _timeout,
                                                            out _);

                                if (!testSense &&
                                    !_dev.Error)
                                {
                                    _readLong10   = true;
                                    LongBlockSize = 9424;
                                    CanReadRaw    = true;
                                }
                            }

                            break;
                        }
                        }
                    }

                    if (!CanReadRaw &&
                        _dev.Manufacturer == "SYQUEST")
                    {
                        testSense = _dev.SyQuestReadLong10(out _, out senseBuf, 0, 0xFFFF, _timeout, out _);

                        if (testSense)
                        {
                            decSense = Sense.DecodeFixed(senseBuf);

                            if (decSense.HasValue)
                            {
                                if (decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
                                    decSense.Value.ASC == 0x24 &&
                                    decSense.Value.ASCQ == 0x00)
                                {
                                    CanReadRaw = true;

                                    if (decSense.Value.InformationValid &&
                                        decSense.Value.ILI)
                                    {
                                        LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);

                                        _syqReadLong10 =
                                            !_dev.SyQuestReadLong10(out _, out senseBuf, 0, LongBlockSize, _timeout,
                                                                    out _);
                                    }
                                }
                                else
                                {
                                    testSense = _dev.SyQuestReadLong6(out _, out senseBuf, 0, 0xFFFF, _timeout, out _);

                                    if (testSense)
                                    {
                                        decSense = Sense.DecodeFixed(senseBuf);

                                        if (decSense?.SenseKey == SenseKeys.IllegalRequest &&
                                            decSense.Value.ASC == 0x24 &&
                                            decSense.Value.ASCQ == 0x00)
                                        {
                                            CanReadRaw = true;

                                            if (decSense.Value.InformationValid &&
                                                decSense.Value.ILI)
                                            {
                                                LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);

                                                _syqReadLong6 =
                                                    !_dev.SyQuestReadLong6(out _, out senseBuf, 0, LongBlockSize,
                                                                           _timeout, out _);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (!CanReadRaw &&
                            LogicalBlockSize == 256)
                        {
                            testSense = _dev.SyQuestReadLong6(out _, out senseBuf, 0, 262, _timeout, out _);

                            if (!testSense &&
                                !_dev.Error)
                            {
                                _syqReadLong6 = true;
                                LongBlockSize = 262;
                                CanReadRaw    = true;
                            }
                        }
                    }
                }
                else
                {
                    switch (_dev.Manufacturer)
                    {
                    case "HL-DT-ST":
                        _hldtstReadRaw = !_dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _);

                        break;

                    case "PLEXTOR":
                        _plextorReadRaw = !_dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _);

                        break;
                    }

                    if (_hldtstReadRaw || _plextorReadRaw)
                    {
                        CanReadRaw    = true;
                        LongBlockSize = 2064;
                    }

                    // READ LONG (10) for some DVD drives
                    if (!CanReadRaw &&
                        _dev.Manufacturer == "MATSHITA")
                    {
                        testSense = _dev.ReadLong10(out _, out senseBuf, false, false, 0, 37856, _timeout, out _);

                        if (!testSense &&
                            !_dev.Error)
                        {
                            _readLongDvd  = true;
                            LongBlockSize = 37856;
                            CanReadRaw    = true;
                        }
                    }
                }
            }

            if (CanReadRaw)
            {
                if (_readLong16)
                {
                    AaruConsole.WriteLine("Using SCSI READ LONG (16) command.");
                }
                else if (_readLong10 || _readLongDvd)
                {
                    AaruConsole.WriteLine("Using SCSI READ LONG (10) command.");
                }
                else if (_syqReadLong10)
                {
                    AaruConsole.WriteLine("Using SyQuest READ LONG (10) command.");
                }
                else if (_syqReadLong6)
                {
                    AaruConsole.WriteLine("Using SyQuest READ LONG (6) command.");
                }
                else if (_hldtstReadRaw)
                {
                    AaruConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
                }
                else if (_plextorReadRaw)
                {
                    AaruConsole.WriteLine("Using Plextor raw DVD reading.");
                }
            }
            else if (_read6)
            {
                AaruConsole.WriteLine("Using SCSI READ (6) command.");
            }
            else if (_read10)
            {
                AaruConsole.WriteLine("Using SCSI READ (10) command.");
            }
            else if (_read12)
            {
                AaruConsole.WriteLine("Using SCSI READ (12) command.");
            }
            else if (_read16)
            {
                AaruConsole.WriteLine("Using SCSI READ (16) command.");
            }

            return(false);
        }
Exemple #6
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            byte[] hdr = new byte[133];

            stream.Read(hdr, 0, 133);
            _header = Marshal.ByteArrayToStructureLittleEndian <Header>(hdr);

            AaruConsole.DebugWriteLine("CopyQM plugin", "header.magic = 0x{0:X4}", _header.magic);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.mark = 0x{0:X2}", _header.mark);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectorSize = {0}", _header.sectorSize);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectorPerCluster = {0}", _header.sectorPerCluster);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.reservedSectors = {0}", _header.reservedSectors);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.fatCopy = {0}", _header.fatCopy);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.rootEntries = {0}", _header.rootEntries);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectors = {0}", _header.sectors);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.mediaType = 0x{0:X2}", _header.mediaType);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerFat = {0}", _header.sectorsPerFat);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerTrack = {0}", _header.sectorsPerTrack);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.heads = {0}", _header.heads);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.hidden = {0}", _header.hidden);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.sectorsBig = {0}", _header.sectorsBig);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.description = {0}", _header.description);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.blind = {0}", _header.blind);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.density = {0}", _header.density);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.imageCylinders = {0}", _header.imageCylinders);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.totalCylinders = {0}", _header.totalCylinders);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.crc = 0x{0:X8}", _header.crc);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.volumeLabel = {0}", _header.volumeLabel);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.time = 0x{0:X4}", _header.time);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.date = 0x{0:X4}", _header.date);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.commentLength = {0}", _header.commentLength);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.secbs = {0}", _header.secbs);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.unknown = 0x{0:X4}", _header.unknown);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.interleave = {0}", _header.interleave);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.skew = {0}", _header.skew);
            AaruConsole.DebugWriteLine("CopyQM plugin", "header.drive = {0}", _header.drive);

            byte[] cmt = new byte[_header.commentLength];
            stream.Read(cmt, 0, _header.commentLength);
            _imageInfo.Comments = StringHandlers.CToString(cmt);
            _decodedImage       = new MemoryStream();

            _calculatedDataCrc = 0;

            while (stream.Position + 2 < stream.Length)
            {
                byte[] runLengthBytes = new byte[2];

                if (stream.Read(runLengthBytes, 0, 2) != 2)
                {
                    break;
                }

                short runLength = BitConverter.ToInt16(runLengthBytes, 0);

                if (runLength < 0)
                {
                    byte   repeatedByte  = (byte)stream.ReadByte();
                    byte[] repeatedArray = new byte[runLength * -1];
                    ArrayHelpers.ArrayFill(repeatedArray, repeatedByte);

                    for (int i = 0; i < runLength * -1; i++)
                    {
                        _decodedImage.WriteByte(repeatedByte);

                        _calculatedDataCrc = _copyQmCrcTable[(repeatedByte ^ _calculatedDataCrc) & 0x3F] ^
                                             (_calculatedDataCrc >> 8);
                    }
                }
                else if (runLength > 0)
                {
                    byte[] nonRepeated = new byte[runLength];
                    stream.Read(nonRepeated, 0, runLength);
                    _decodedImage.Write(nonRepeated, 0, runLength);

                    foreach (byte c in nonRepeated)
                    {
                        _calculatedDataCrc =
                            _copyQmCrcTable[(c ^ _calculatedDataCrc) & 0x3F] ^ (_calculatedDataCrc >> 8);
                    }
                }
            }

            // In case there is omitted data
            long sectors = _header.sectorsPerTrack * _header.heads * _header.totalCylinders;

            long fillingLen = (sectors * _header.sectorSize) - _decodedImage.Length;

            if (fillingLen > 0)
            {
                byte[] filling = new byte[fillingLen];
                ArrayHelpers.ArrayFill(filling, (byte)0xF6);
                _decodedImage.Write(filling, 0, filling.Length);
            }

            int sum = 0;

            for (int i = 0; i < hdr.Length - 1; i++)
            {
                sum += hdr[i];
            }

            _headerChecksumOk = ((-1 * sum) & 0xFF) == _header.headerChecksum;

            AaruConsole.DebugWriteLine("CopyQM plugin", "Calculated header checksum = 0x{0:X2}, {1}", (-1 * sum) & 0xFF,
                                       _headerChecksumOk);

            AaruConsole.DebugWriteLine("CopyQM plugin", "Calculated data CRC = 0x{0:X8}, {1}", _calculatedDataCrc,
                                       _calculatedDataCrc == _header.crc);

            _imageInfo.Application          = "CopyQM";
            _imageInfo.CreationTime         = DateHandlers.DosToDateTime(_header.date, _header.time);
            _imageInfo.LastModificationTime = _imageInfo.CreationTime;
            _imageInfo.MediaTitle           = _header.volumeLabel;
            _imageInfo.ImageSize            = (ulong)(stream.Length - 133 - _header.commentLength);
            _imageInfo.Sectors    = (ulong)sectors;
            _imageInfo.SectorSize = _header.sectorSize;

            _imageInfo.MediaType = Geometry.GetMediaType(((ushort)_header.totalCylinders, (byte)_header.heads,
                                                          _header.sectorsPerTrack, (uint)_header.sectorSize,
                                                          MediaEncoding.MFM, false));

            switch (_imageInfo.MediaType)
            {
            case MediaType.NEC_525_HD when _header.drive == COPYQM_35_HD || _header.drive == COPYQM_35_ED:
                _imageInfo.MediaType = MediaType.NEC_35_HD_8;

                break;

            case MediaType.DOS_525_HD when _header.drive == COPYQM_35_HD || _header.drive == COPYQM_35_ED:
                _imageInfo.MediaType = MediaType.NEC_35_HD_15;

                break;

            case MediaType.RX50 when _header.drive == COPYQM_525_DD || _header.drive == COPYQM_525_HD:
                _imageInfo.MediaType = MediaType.ATARI_35_SS_DD;

                break;
            }

            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            _decodedDisk            = _decodedImage.ToArray();

            _decodedImage.Close();

            AaruConsole.VerboseWriteLine("CopyQM image contains a disk of type {0}", _imageInfo.MediaType);

            if (!string.IsNullOrEmpty(_imageInfo.Comments))
            {
                AaruConsole.VerboseWriteLine("CopyQM comments: {0}", _imageInfo.Comments);
            }

            _imageInfo.Heads           = _header.heads;
            _imageInfo.Cylinders       = _header.totalCylinders;
            _imageInfo.SectorsPerTrack = _header.sectorsPerTrack;

            return(true);
        }
Exemple #7
0
        static void Identify(string devPath, Device dev)
        {
start:
            System.Console.Clear();

            bool sense = dev.AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs errorRegisters,
                                         out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending IDENTIFY DEVICE to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer));
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print buffer.");
            AaruConsole.WriteLine("2.- Decode buffer.");
            AaruConsole.WriteLine("3.- Decode error registers.");
            AaruConsole.WriteLine("4.- Send command again.");
            AaruConsole.WriteLine("0.- Return to CHS ATA commands menu.");
            AaruConsole.Write("Choose: ");

            string strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out int item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to CHS ATA commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("IDENTIFY DEVICE response:");

                if (buffer != null)
                {
                    PrintHex.PrintHexArray(buffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("IDENTIFY DEVICE decoded response:");

                if (buffer != null)
                {
                    AaruConsole.WriteLine("{0}", Decoders.ATA.Identify.Prettify(buffer));
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 3:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("IDENTIFY DEVICE status registers:");
                AaruConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters));
                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 4: goto start;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #8
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.ASCII;
            information = "";
            var isoMetadata = new StringBuilder();

            byte[] vdMagic = new byte[5];     // Volume Descriptor magic "CD001"
            byte[] hsMagic = new byte[5];     // Volume Descriptor magic "CDROM"

            string bootSpec = "";

            PrimaryVolumeDescriptor?pvd      = null;
            PrimaryVolumeDescriptor?jolietvd = null;
            BootRecord?bvd = null;
            HighSierraPrimaryVolumeDescriptor?hsvd = null;
            FileStructureVolumeDescriptor?    fsvd = null;
            ElToritoBootRecord?torito = null;

            // ISO9660 is designed for 2048 bytes/sector devices
            if (imagePlugin.Info.SectorSize < 2048)
            {
                return;
            }

            // ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size.
            if (partition.End < 16)
            {
                return;
            }

            ulong counter = 0;

            byte[] vdSector = imagePlugin.ReadSector(16 + counter + partition.Start);
            int    xaOff    = vdSector.Length == 2336 ? 8 : 0;

            Array.Copy(vdSector, 0x009 + xaOff, hsMagic, 0, 5);
            bool highSierraInfo = Encoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC;
            int  hsOff          = 0;

            if (highSierraInfo)
            {
                hsOff = 8;
            }

            bool cdiInfo = false;
            bool evd     = false;
            bool vpd     = false;

            while (true)
            {
                AaruConsole.DebugWriteLine("ISO9660 plugin", "Processing VD loop no. {0}", counter);

                // Seek to Volume Descriptor
                AaruConsole.DebugWriteLine("ISO9660 plugin", "Reading sector {0}", 16 + counter + partition.Start);
                byte[] vdSectorTmp = imagePlugin.ReadSector(16 + counter + partition.Start);
                vdSector = new byte[vdSectorTmp.Length - xaOff];
                Array.Copy(vdSectorTmp, xaOff, vdSector, 0, vdSector.Length);

                byte vdType = vdSector[0 + hsOff]; // Volume Descriptor Type, should be 1 or 2.
                AaruConsole.DebugWriteLine("ISO9660 plugin", "VDType = {0}", vdType);

                if (vdType == 255) // Supposedly we are in the PVD.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                Array.Copy(vdSector, 0x001, vdMagic, 0, 5);
                Array.Copy(vdSector, 0x009, hsMagic, 0, 5);

                if (Encoding.GetString(vdMagic) != ISO_MAGIC &&
                    Encoding.GetString(hsMagic) != HIGH_SIERRA_MAGIC &&
                    Encoding.GetString(vdMagic) != CDI_MAGIC
                    ) // Recognized, it is an ISO9660, now check for rest of data.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                cdiInfo |= Encoding.GetString(vdMagic) == CDI_MAGIC;

                switch (vdType)
                {
                case 0:
                {
                    bvd = Marshal.ByteArrayToStructureLittleEndian <BootRecord>(vdSector, hsOff, 2048 - hsOff);

                    bootSpec = "Unknown";

                    if (Encoding.GetString(bvd.Value.system_id).Substring(0, 23) == "EL TORITO SPECIFICATION")
                    {
                        bootSpec = "El Torito";

                        torito =
                            Marshal.ByteArrayToStructureLittleEndian <ElToritoBootRecord>(vdSector, hsOff,
                                                                                          2048 - hsOff);
                    }

                    break;
                }

                case 1:
                {
                    if (highSierraInfo)
                    {
                        hsvd = Marshal.
                               ByteArrayToStructureLittleEndian <HighSierraPrimaryVolumeDescriptor>(vdSector);
                    }
                    else if (cdiInfo)
                    {
                        fsvd = Marshal.ByteArrayToStructureBigEndian <FileStructureVolumeDescriptor>(vdSector);
                    }
                    else
                    {
                        pvd = Marshal.ByteArrayToStructureLittleEndian <PrimaryVolumeDescriptor>(vdSector);
                    }

                    break;
                }

                case 2:
                {
                    PrimaryVolumeDescriptor svd =
                        Marshal.ByteArrayToStructureLittleEndian <PrimaryVolumeDescriptor>(vdSector);

                    // Check if this is Joliet
                    if (svd.version == 1)
                    {
                        if (svd.escape_sequences[0] == '%' &&
                            svd.escape_sequences[1] == '/')
                        {
                            if (svd.escape_sequences[2] == '@' ||
                                svd.escape_sequences[2] == 'C' ||
                                svd.escape_sequences[2] == 'E')
                            {
                                jolietvd = svd;
                            }
                            else
                            {
                                AaruConsole.WriteLine("ISO9660 plugin",
                                                      "Found unknown supplementary volume descriptor");
                            }
                        }
                    }
                    else
                    {
                        evd = true;
                    }

                    break;
                }

                case 3:
                {
                    vpd = true;

                    break;
                }
                }

                counter++;
            }

            DecodedVolumeDescriptor decodedVd;
            var decodedJolietVd = new DecodedVolumeDescriptor();

            XmlFsType = new FileSystemType();

            if (pvd == null &&
                hsvd == null &&
                fsvd == null)
            {
                information = "ERROR: Could not find primary volume descriptor";

                return;
            }

            if (highSierraInfo)
            {
                decodedVd = DecodeVolumeDescriptor(hsvd.Value);
            }
            else if (cdiInfo)
            {
                decodedVd = DecodeVolumeDescriptor(fsvd.Value);
            }
            else
            {
                decodedVd = DecodeVolumeDescriptor(pvd.Value);
            }

            if (jolietvd != null)
            {
                decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value);
            }

            uint rootLocation = 0;
            uint rootSize     = 0;

            // No need to read root on CD-i, as extensions are not supported...
            if (!cdiInfo)
            {
                rootLocation = highSierraInfo ? hsvd.Value.root_directory_record.extent
                                   : pvd.Value.root_directory_record.extent;

                if (highSierraInfo)
                {
                    rootSize = hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size;

                    if (hsvd.Value.root_directory_record.size % hsvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
                else
                {
                    rootSize = pvd.Value.root_directory_record.size / pvd.Value.logical_block_size;

                    if (pvd.Value.root_directory_record.size % pvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
            }

            byte[] rootDir      = new byte[0];
            int    rootOff      = 0;
            bool   xaExtensions = false;
            bool   apple        = false;
            bool   susp         = false;
            bool   rrip         = false;
            bool   ziso         = false;
            bool   amiga        = false;
            bool   aaip         = false;
            List <ContinuationArea> contareas = new List <ContinuationArea>();
            List <byte[]>           refareas  = new List <byte[]>();
            var suspInformation = new StringBuilder();

            if (rootLocation + rootSize < imagePlugin.Info.Sectors)
            {
                rootDir = imagePlugin.ReadSectors(rootLocation, rootSize);
            }

            // Walk thru root directory to see system area extensions in use
            while (rootOff + Marshal.SizeOf <DirectoryRecord>() < rootDir.Length &&
                   !cdiInfo)
            {
                DirectoryRecord record =
                    Marshal.ByteArrayToStructureLittleEndian <DirectoryRecord>(rootDir, rootOff,
                                                                               Marshal.SizeOf <DirectoryRecord>());

                int saOff = Marshal.SizeOf <DirectoryRecord>() + record.name_len;
                saOff += saOff % 2;
                int saLen = record.length - saOff;

                if (saLen > 0 &&
                    rootOff + saOff + saLen <= rootDir.Length)
                {
                    byte[] sa = new byte[saLen];
                    Array.Copy(rootDir, rootOff + saOff, sa, 0, saLen);
                    saOff = 0;

                    while (saOff < saLen)
                    {
                        bool noneFound = true;

                        if (Marshal.SizeOf <CdromXa>() + saOff <= saLen)
                        {
                            CdromXa xa = Marshal.ByteArrayToStructureBigEndian <CdromXa>(sa);

                            if (xa.signature == XA_MAGIC)
                            {
                                xaExtensions = true;
                                saOff       += Marshal.SizeOf <CdromXa>();
                                noneFound    = false;
                            }
                        }

                        if (saOff + 2 >= saLen)
                        {
                            break;
                        }

                        ushort nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                        switch (nextSignature)
                        {
                        // Easy, contains size field
                        case APPLE_MAGIC:
                            apple     = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;

                            break;

                        // Not easy, contains size field
                        case APPLE_MAGIC_OLD:
                            apple = true;
                            var appleId = (AppleOldId)sa[saOff + 2];
                            noneFound = false;

                            switch (appleId)
                            {
                            case AppleOldId.ProDOS:
                                saOff += Marshal.SizeOf <AppleProDOSOldSystemUse>();

                                break;

                            case AppleOldId.TypeCreator:
                            case AppleOldId.TypeCreatorBundle:
                                saOff += Marshal.SizeOf <AppleHFSTypeCreatorSystemUse>();

                                break;

                            case AppleOldId.TypeCreatorIcon:
                            case AppleOldId.TypeCreatorIconBundle:
                                saOff += Marshal.SizeOf <AppleHFSIconSystemUse>();

                                break;

                            case AppleOldId.HFS:
                                saOff += Marshal.SizeOf <AppleHFSOldSystemUse>();

                                break;
                            }

                            break;

                        // IEEE-P1281 aka SUSP 1.12
                        case SUSP_INDICATOR:
                            susp      = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;

                            while (saOff + 2 < saLen)
                            {
                                nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                                switch (nextSignature)
                                {
                                case APPLE_MAGIC:
                                    if (sa[saOff + 3] == 1 &&
                                        sa[saOff + 2] == 7)
                                    {
                                        apple = true;
                                    }
                                    else
                                    {
                                        apple |= sa[saOff + 3] != 1;
                                    }

                                    break;

                                case SUSP_CONTINUATION when saOff + sa[saOff + 2] <= saLen:
                                    byte[] ce = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, ce, 0, ce.Length);

                                    ContinuationArea ca =
                                        Marshal.ByteArrayToStructureBigEndian <ContinuationArea>(ce);

                                    contareas.Add(ca);

                                    break;

                                case SUSP_REFERENCE when saOff + sa[saOff + 2] <= saLen:
                                    byte[] er = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, er, 0, er.Length);
                                    refareas.Add(er);

                                    break;
                                }

                                rrip |= nextSignature == RRIP_MAGIC ||
                                        nextSignature == RRIP_POSIX_ATTRIBUTES ||
                                        nextSignature == RRIP_POSIX_DEV_NO ||
                                        nextSignature == RRIP_SYMLINK ||
                                        nextSignature == RRIP_NAME ||
                                        nextSignature == RRIP_CHILDLINK ||
                                        nextSignature == RRIP_PARENTLINK ||
                                        nextSignature == RRIP_RELOCATED_DIR ||
                                        nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                                ziso  |= nextSignature == ZISO_MAGIC;
                                amiga |= nextSignature == AMIGA_MAGIC;

                                aaip |= nextSignature == AAIP_MAGIC || (nextSignature == AAIP_MAGIC_OLD &&
                                                                        sa[saOff + 3] == 1 &&
                                                                        sa[saOff + 2] >= 9);

                                saOff += sa[saOff + 2];

                                if (nextSignature == SUSP_TERMINATOR)
                                {
                                    break;
                                }
                            }

                            break;
                        }

                        if (noneFound)
                        {
                            break;
                        }
                    }
                }

                rootOff += record.length;

                if (record.length == 0)
                {
                    break;
                }
            }

            foreach (ContinuationArea ca in contareas)
            {
                uint caLen = (ca.ca_length_be + ca.offset_be) /
                             (highSierraInfo ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size);

                if ((ca.ca_length_be + ca.offset_be) %
                    (highSierraInfo ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size) > 0)
                {
                    caLen++;
                }

                byte[] caSectors = imagePlugin.ReadSectors(ca.block_be, caLen);
                byte[] caData    = new byte[ca.ca_length_be];
                Array.Copy(caSectors, ca.offset_be, caData, 0, ca.ca_length_be);
                int caOff = 0;

                while (caOff < ca.ca_length_be)
                {
                    ushort nextSignature = BigEndianBitConverter.ToUInt16(caData, caOff);

                    switch (nextSignature)
                    {
                    // Apple never said to include its extensions inside a continuation area, but just in case
                    case APPLE_MAGIC:
                        if (caData[caOff + 3] == 1 &&
                            caData[caOff + 2] == 7)
                        {
                            apple = true;
                        }
                        else
                        {
                            apple |= caData[caOff + 3] != 1;
                        }

                        break;

                    case SUSP_REFERENCE when caOff + caData[caOff + 2] <= ca.ca_length_be:
                        byte[] er = new byte[caData[caOff + 2]];
                        Array.Copy(caData, caOff, er, 0, er.Length);
                        refareas.Add(er);

                        break;
                    }

                    rrip |= nextSignature == RRIP_MAGIC || nextSignature == RRIP_POSIX_ATTRIBUTES ||
                            nextSignature == RRIP_POSIX_DEV_NO || nextSignature == RRIP_SYMLINK ||
                            nextSignature == RRIP_NAME || nextSignature == RRIP_CHILDLINK ||
                            nextSignature == RRIP_PARENTLINK || nextSignature == RRIP_RELOCATED_DIR ||
                            nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                    ziso  |= nextSignature == ZISO_MAGIC;
                    amiga |= nextSignature == AMIGA_MAGIC;

                    aaip |= nextSignature == AAIP_MAGIC || (nextSignature == AAIP_MAGIC_OLD && caData[caOff + 3] == 1 &&
                                                            caData[caOff + 2] >= 9);

                    caOff += caData[caOff + 2];
                }
            }

            if (refareas.Count > 0)
            {
                suspInformation.AppendLine("----------------------------------------");
                suspInformation.AppendLine("SYSTEM USE SHARING PROTOCOL INFORMATION:");
                suspInformation.AppendLine("----------------------------------------");

                counter = 1;

                foreach (byte[] erb in refareas)
                {
                    ReferenceArea er    = Marshal.ByteArrayToStructureBigEndian <ReferenceArea>(erb);
                    string        extId = Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>(), er.id_len);

                    string extDes = Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>() + er.id_len, er.des_len);

                    string extSrc = Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>() + er.id_len + er.des_len,
                                                       er.src_len);

                    suspInformation.AppendFormat("Extension: {0}", counter).AppendLine();
                    suspInformation.AppendFormat("\tID: {0}, version {1}", extId, er.ext_ver).AppendLine();
                    suspInformation.AppendFormat("\tDescription: {0}", extDes).AppendLine();
                    suspInformation.AppendFormat("\tSource: {0}", extSrc).AppendLine();
                    counter++;
                }
            }

            byte[]          ipbinSector = imagePlugin.ReadSector(0 + partition.Start);
            CD.IPBin?       segaCd      = CD.DecodeIPBin(ipbinSector);
            Saturn.IPBin?   saturn      = Saturn.DecodeIPBin(ipbinSector);
            Dreamcast.IPBin?dreamcast   = Dreamcast.DecodeIPBin(ipbinSector);

            string fsFormat;

            if (highSierraInfo)
            {
                fsFormat = "High Sierra Format";
            }
            else if (cdiInfo)
            {
                fsFormat = "CD-i";
            }
            else
            {
                fsFormat = "ISO9660";
            }

            isoMetadata.AppendFormat("{0} file system", fsFormat).AppendLine();

            if (xaExtensions)
            {
                isoMetadata.AppendLine("CD-ROM XA extensions present.");
            }

            if (amiga)
            {
                isoMetadata.AppendLine("Amiga extensions present.");
            }

            if (apple)
            {
                isoMetadata.AppendLine("Apple extensions present.");
            }

            if (jolietvd != null)
            {
                isoMetadata.AppendLine("Joliet extensions present.");
            }

            if (susp)
            {
                isoMetadata.AppendLine("System Use Sharing Protocol present.");
            }

            if (rrip)
            {
                isoMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
            }

            if (aaip)
            {
                isoMetadata.AppendLine("Arbitrary Attribute Interchange Protocol present.");
            }

            if (ziso)
            {
                isoMetadata.AppendLine("zisofs compression present.");
            }

            if (evd)
            {
                isoMetadata.AppendLine("Contains Enhanved Volume Descriptor.");
            }

            if (vpd)
            {
                isoMetadata.AppendLine("Contains Volume Partition Descriptor.");
            }

            if (bvd != null)
            {
                isoMetadata.AppendFormat("Disc bootable following {0} specifications.", bootSpec).AppendLine();
            }

            if (segaCd != null)
            {
                isoMetadata.AppendLine("This is a SegaCD / MegaCD disc.");
                isoMetadata.AppendLine(CD.Prettify(segaCd));
            }

            if (saturn != null)
            {
                isoMetadata.AppendLine("This is a Sega Saturn disc.");
                isoMetadata.AppendLine(Saturn.Prettify(saturn));
            }

            if (dreamcast != null)
            {
                isoMetadata.AppendLine("This is a Sega Dreamcast disc.");
                isoMetadata.AppendLine(Dreamcast.Prettify(dreamcast));
            }

            isoMetadata.AppendFormat("{0}------------------------------", cdiInfo ? "---------------" : "").
            AppendLine();

            isoMetadata.AppendFormat("{0}VOLUME DESCRIPTOR INFORMATION:", cdiInfo ? "FILE STRUCTURE " : "").
            AppendLine();

            isoMetadata.AppendFormat("{0}------------------------------", cdiInfo ? "---------------" : "").
            AppendLine();

            isoMetadata.AppendFormat("System identifier: {0}", decodedVd.SystemIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume identifier: {0}", decodedVd.VolumeIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume set identifier: {0}", decodedVd.VolumeSetIdentifier).AppendLine();
            isoMetadata.AppendFormat("Publisher identifier: {0}", decodedVd.PublisherIdentifier).AppendLine();
            isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedVd.DataPreparerIdentifier).AppendLine();
            isoMetadata.AppendFormat("Application identifier: {0}", decodedVd.ApplicationIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume creation date: {0}", decodedVd.CreationTime).AppendLine();

            if (decodedVd.HasModificationTime)
            {
                isoMetadata.AppendFormat("Volume modification date: {0}", decodedVd.ModificationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
            }

            if (decodedVd.HasExpirationTime)
            {
                isoMetadata.AppendFormat("Volume expiration date: {0}", decodedVd.ExpirationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
            }

            if (decodedVd.HasEffectiveTime)
            {
                isoMetadata.AppendFormat("Volume effective date: {0}", decodedVd.EffectiveTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
            }

            isoMetadata.AppendFormat("Volume has {0} blocks of {1} bytes each", decodedVd.Blocks, decodedVd.BlockSize).
            AppendLine();

            if (jolietvd != null)
            {
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendLine("JOLIET VOLUME DESCRIPTOR INFORMATION:");
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendFormat("System identifier: {0}", decodedJolietVd.SystemIdentifier).AppendLine();
                isoMetadata.AppendFormat("Volume identifier: {0}", decodedJolietVd.VolumeIdentifier).AppendLine();

                isoMetadata.AppendFormat("Volume set identifier: {0}", decodedJolietVd.VolumeSetIdentifier).
                AppendLine();

                isoMetadata.AppendFormat("Publisher identifier: {0}", decodedJolietVd.PublisherIdentifier).AppendLine();

                isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedJolietVd.DataPreparerIdentifier).
                AppendLine();

                isoMetadata.AppendFormat("Application identifier: {0}", decodedJolietVd.ApplicationIdentifier).
                AppendLine();

                isoMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVd.CreationTime).AppendLine();

                if (decodedJolietVd.HasModificationTime)
                {
                    isoMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVd.ModificationTime).
                    AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
                }

                if (decodedJolietVd.HasExpirationTime)
                {
                    isoMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVd.ExpirationTime).
                    AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
                }

                if (decodedJolietVd.HasEffectiveTime)
                {
                    isoMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVd.EffectiveTime).AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
                }
            }

            if (torito != null)
            {
                vdSector = imagePlugin.ReadSector(torito.Value.catalog_sector + partition.Start);

                int toritoOff = 0;

                if (vdSector[toritoOff] != 1)
                {
                    goto exit_torito;
                }

                ElToritoValidationEntry valentry =
                    Marshal.ByteArrayToStructureLittleEndian <ElToritoValidationEntry>(vdSector, toritoOff,
                                                                                       EL_TORITO_ENTRY_SIZE);

                if (valentry.signature != EL_TORITO_MAGIC)
                {
                    goto exit_torito;
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                ElToritoInitialEntry initialEntry =
                    Marshal.ByteArrayToStructureLittleEndian <ElToritoInitialEntry>(vdSector, toritoOff,
                                                                                    EL_TORITO_ENTRY_SIZE);

                initialEntry.boot_type = (ElToritoEmulation)((byte)initialEntry.boot_type & 0xF);

                AaruConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.load_rba = {0}",
                                           initialEntry.load_rba);

                AaruConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.sector_count = {0}",
                                           initialEntry.sector_count);

                byte[] bootImage =
                    (initialEntry.load_rba + partition.Start + initialEntry.sector_count) - 1 <=
                    partition.End
                        ? imagePlugin.ReadSectors(initialEntry.load_rba + partition.Start, initialEntry.sector_count)
                        : null;

                isoMetadata.AppendLine("----------------------");
                isoMetadata.AppendLine("EL TORITO INFORMATION:");
                isoMetadata.AppendLine("----------------------");

                isoMetadata.AppendLine("Initial entry:");
                isoMetadata.AppendFormat("\tDeveloper ID: {0}", Encoding.GetString(valentry.developer_id)).AppendLine();

                if (initialEntry.bootable == ElToritoIndicator.Bootable)
                {
                    isoMetadata.AppendFormat("\tBootable on {0}", valentry.platform_id).AppendLine();

                    isoMetadata.AppendFormat("\tBootable image starts at sector {0} and runs for {1} sectors",
                                             initialEntry.load_rba, initialEntry.sector_count).AppendLine();

                    if (valentry.platform_id == ElToritoPlatform.x86)
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at segment {0:X4}h",
                                                 initialEntry.load_seg == 0 ? 0x7C0 : initialEntry.load_seg).
                        AppendLine();
                    }
                    else
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at 0x{0:X8}",
                                                 (uint)initialEntry.load_seg * 10).AppendLine();
                    }

                    switch (initialEntry.boot_type)
                    {
                    case ElToritoEmulation.None:
                        isoMetadata.AppendLine("\tImage uses no emulation");

                        break;

                    case ElToritoEmulation.Md2hd:
                        isoMetadata.AppendLine("\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");

                        break;

                    case ElToritoEmulation.Mf2hd:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");

                        break;

                    case ElToritoEmulation.Mf2ed:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");

                        break;

                    default:
                        isoMetadata.AppendFormat("\tImage uses unknown emulation type {0}",
                                                 (byte)initialEntry.boot_type).AppendLine();

                        break;
                    }

                    isoMetadata.AppendFormat("\tSystem type: 0x{0:X2}", initialEntry.system_type).AppendLine();

                    if (bootImage != null)
                    {
                        isoMetadata.AppendFormat("\tBootable image's SHA1: {0}", Sha1Context.Data(bootImage, out _)).
                        AppendLine();
                    }
                }
                else
                {
                    isoMetadata.AppendLine("\tNot bootable");
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                const int SECTION_COUNTER = 2;

                while (toritoOff < vdSector.Length &&
                       (vdSector[toritoOff] == (byte)ElToritoIndicator.Header ||
                        vdSector[toritoOff] == (byte)ElToritoIndicator.LastHeader))
                {
                    ElToritoSectionHeaderEntry sectionHeader =
                        Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionHeaderEntry>(vdSector, toritoOff,
                                                                                              EL_TORITO_ENTRY_SIZE);

                    toritoOff += EL_TORITO_ENTRY_SIZE;

                    isoMetadata.AppendFormat("Boot section {0}:", SECTION_COUNTER);

                    isoMetadata.AppendFormat("\tSection ID: {0}", Encoding.GetString(sectionHeader.identifier)).
                    AppendLine();

                    for (int entryCounter = 1; entryCounter <= sectionHeader.entries && toritoOff < vdSector.Length;
                         entryCounter++)
                    {
                        ElToritoSectionEntry sectionEntry =
                            Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionEntry>(vdSector, toritoOff,
                                                                                            EL_TORITO_ENTRY_SIZE);

                        toritoOff += EL_TORITO_ENTRY_SIZE;

                        isoMetadata.AppendFormat("\tEntry {0}:", entryCounter);

                        if (sectionEntry.bootable == ElToritoIndicator.Bootable)
                        {
                            bootImage =
                                (sectionEntry.load_rba + partition.Start + sectionEntry.sector_count) - 1 <=
                                partition.End
                                    ? imagePlugin.ReadSectors(sectionEntry.load_rba + partition.Start,
                                                              sectionEntry.sector_count) : null;

                            isoMetadata.AppendFormat("\t\tBootable on {0}", sectionHeader.platform_id).AppendLine();

                            isoMetadata.AppendFormat("\t\tBootable image starts at sector {0} and runs for {1} sectors",
                                                     sectionEntry.load_rba, sectionEntry.sector_count).AppendLine();

                            if (valentry.platform_id == ElToritoPlatform.x86)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at segment {0:X4}h",
                                                         sectionEntry.load_seg == 0 ? 0x7C0 : sectionEntry.load_seg).
                                AppendLine();
                            }
                            else
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at 0x{0:X8}",
                                                         (uint)sectionEntry.load_seg * 10).AppendLine();
                            }

                            switch ((ElToritoEmulation)((byte)sectionEntry.boot_type & 0xF))
                            {
                            case ElToritoEmulation.None:
                                isoMetadata.AppendLine("\t\tImage uses no emulation");

                                break;

                            case ElToritoEmulation.Md2hd:
                                isoMetadata.
                                AppendLine("\t\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");

                                break;

                            case ElToritoEmulation.Mf2hd:
                                isoMetadata.
                                AppendLine("\t\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");

                                break;

                            case ElToritoEmulation.Mf2ed:
                                isoMetadata.
                                AppendLine("\t\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");

                                break;

                            default:
                                isoMetadata.AppendFormat("\t\tImage uses unknown emulation type {0}",
                                                         (byte)initialEntry.boot_type).AppendLine();

                                break;
                            }

                            isoMetadata.AppendFormat("\t\tSelection criteria type: {0}",
                                                     sectionEntry.selection_criteria_type).AppendLine();

                            isoMetadata.AppendFormat("\t\tSystem type: 0x{0:X2}", sectionEntry.system_type).
                            AppendLine();

                            if (bootImage != null)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image's SHA1: {0}",
                                                         Sha1Context.Data(bootImage, out _)).AppendLine();
                            }
                        }
                        else
                        {
                            isoMetadata.AppendLine("\t\tNot bootable");
                        }

                        var flags = (ElToritoFlags)((byte)sectionEntry.boot_type & 0xF0);

                        if (flags.HasFlag(ElToritoFlags.ATAPI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains ATAPI drivers");
                        }

                        if (flags.HasFlag(ElToritoFlags.SCSI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains SCSI drivers");
                        }

                        if (!flags.HasFlag(ElToritoFlags.Continued))
                        {
                            continue;
                        }

                        while (toritoOff < vdSector.Length)
                        {
                            ElToritoSectionEntryExtension sectionExtension =
                                Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionEntryExtension>(vdSector,
                                                                                                         toritoOff,
                                                                                                         EL_TORITO_ENTRY_SIZE);

                            toritoOff += EL_TORITO_ENTRY_SIZE;

                            if (!sectionExtension.extension_flags.HasFlag(ElToritoFlags.Continued))
                            {
                                break;
                            }
                        }
                    }

                    if (sectionHeader.header_id == ElToritoIndicator.LastHeader)
                    {
                        break;
                    }
                }
            }

exit_torito:

            if (refareas.Count > 0)
            {
                isoMetadata.Append(suspInformation);
            }

            XmlFsType.Type = fsFormat;

            if (jolietvd != null)
            {
                XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;

                if (string.IsNullOrEmpty(decodedJolietVd.SystemIdentifier) ||
                    decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length)
                {
                    XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
                }
                else
                {
                    XmlFsType.SystemIdentifier = string.IsNullOrEmpty(decodedJolietVd.SystemIdentifier) ? null
                                                     : decodedJolietVd.SystemIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.VolumeSetIdentifier) ||
                    decodedVd.VolumeSetIdentifier.Length > decodedJolietVd.VolumeSetIdentifier.Length)
                {
                    XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
                }
                else
                {
                    XmlFsType.VolumeSetIdentifier = string.IsNullOrEmpty(decodedJolietVd.VolumeSetIdentifier) ? null
                                                        : decodedJolietVd.VolumeSetIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.PublisherIdentifier) ||
                    decodedVd.PublisherIdentifier.Length > decodedJolietVd.PublisherIdentifier.Length)
                {
                    XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
                }
                else
                {
                    XmlFsType.PublisherIdentifier = string.IsNullOrEmpty(decodedJolietVd.PublisherIdentifier) ? null
                                                        : decodedJolietVd.PublisherIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.DataPreparerIdentifier) ||
                    decodedVd.DataPreparerIdentifier.Length > decodedJolietVd.DataPreparerIdentifier.Length)
                {
                    XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                }
                else
                {
                    XmlFsType.DataPreparerIdentifier = string.IsNullOrEmpty(decodedJolietVd.DataPreparerIdentifier)
                                                           ? null : decodedJolietVd.DataPreparerIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.ApplicationIdentifier) ||
                    decodedVd.ApplicationIdentifier.Length > decodedJolietVd.ApplicationIdentifier.Length)
                {
                    XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
                }
                else
                {
                    XmlFsType.ApplicationIdentifier = string.IsNullOrEmpty(decodedJolietVd.ApplicationIdentifier) ? null
                                                          : decodedJolietVd.ApplicationIdentifier;
                }

                XmlFsType.CreationDate          = decodedJolietVd.CreationTime;
                XmlFsType.CreationDateSpecified = true;

                if (decodedJolietVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedJolietVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedJolietVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedJolietVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedJolietVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedJolietVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }
            else
            {
                XmlFsType.SystemIdentifier       = decodedVd.SystemIdentifier;
                XmlFsType.VolumeName             = decodedVd.VolumeIdentifier;
                XmlFsType.VolumeSetIdentifier    = decodedVd.VolumeSetIdentifier;
                XmlFsType.PublisherIdentifier    = decodedVd.PublisherIdentifier;
                XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                XmlFsType.ApplicationIdentifier  = decodedVd.ApplicationIdentifier;
                XmlFsType.CreationDate           = decodedVd.CreationTime;
                XmlFsType.CreationDateSpecified  = true;

                if (decodedVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }

            XmlFsType.Bootable   |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
            XmlFsType.Clusters    = decodedVd.Blocks;
            XmlFsType.ClusterSize = decodedVd.BlockSize;

            information = isoMetadata.ToString();
        }
Exemple #9
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            if (stream.Length < 512)
            {
                return(false);
            }

            byte[] headerB = new byte[256];
            stream.Read(headerB, 0, 256);
            CpcDiskInfo header = Marshal.ByteArrayToStructureLittleEndian <CpcDiskInfo>(headerB);

            if (!cpcdskId.SequenceEqual(header.magic.Take(cpcdskId.Length)) &&
                !edskId.SequenceEqual(header.magic) &&
                !du54Id.SequenceEqual(header.magic))
            {
                return(false);
            }

            extended = edskId.SequenceEqual(header.magic);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Extended = {0}", extended);

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.magic = \"{0}\"",
                                       StringHandlers.CToString(header.magic));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.magic2 = \"{0}\"",
                                       StringHandlers.CToString(header.magic2));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.creator = \"{0}\"",
                                       StringHandlers.CToString(header.creator));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracks = {0}", header.tracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.sides = {0}", header.sides);

            if (!extended)
            {
                AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracksize = {0}", header.tracksize);
            }
            else
            {
                for (int i = 0; i < header.tracks; i++)
                {
                    for (int j = 0; j < header.sides; j++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "Track {0} Side {1} size = {2}", i, j,
                                                   header.tracksizeTable[(i * header.sides) + j] * 256);
                    }
                }
            }

            ulong currentSector = 0;

            sectors      = new Dictionary <ulong, byte[]>();
            addressMarks = new Dictionary <ulong, byte[]>();
            ulong readtracks        = 0;
            bool  allTracksSameSize = true;
            ulong sectorsPerTrack   = 0;

            // Seek to first track descriptor
            stream.Seek(256, SeekOrigin.Begin);

            for (int i = 0; i < header.tracks; i++)
            {
                for (int j = 0; j < header.sides; j++)
                {
                    // Track not stored in image
                    if (extended && header.tracksizeTable[(i * header.sides) + j] == 0)
                    {
                        continue;
                    }

                    long trackPos = stream.Position;

                    byte[] trackB = new byte[256];
                    stream.Read(trackB, 0, 256);
                    CpcTrackInfo trackInfo = Marshal.ByteArrayToStructureLittleEndian <CpcTrackInfo>(trackB);

                    if (!trackId.SequenceEqual(trackInfo.magic))
                    {
                        AaruConsole.ErrorWriteLine("Not the expected track info.");

                        return(false);
                    }

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].magic = \"{0}\"",
                                               StringHandlers.CToString(trackInfo.magic), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].bps = {0}",
                                               SizeCodeToBytes(trackInfo.bps), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].dataRate = {0}", trackInfo.dataRate,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].filler = 0x{0:X2}",
                                               trackInfo.filler, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].gap3 = 0x{0:X2}", trackInfo.gap3, i,
                                               j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].padding = {0}", trackInfo.padding,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].recordingMode = {0}",
                                               trackInfo.recordingMode, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sectors = {0}", trackInfo.sectors,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].side = {0}", trackInfo.side, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].track = {0}", trackInfo.track, i,
                                               j);

                    if (trackInfo.sectors != sectorsPerTrack)
                    {
                        if (sectorsPerTrack == 0)
                        {
                            sectorsPerTrack = trackInfo.sectors;
                        }
                        else
                        {
                            allTracksSameSize = false;
                        }
                    }

                    byte[][] thisTrackSectors      = new byte[trackInfo.sectors][];
                    byte[][] thisTrackAddressMarks = new byte[trackInfo.sectors][];

                    for (int k = 1; k <= trackInfo.sectors; k++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].id = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].id, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].len = {0}",
                                                   trackInfo.sectorsInfo[k - 1].len, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].side = {0}",
                                                   trackInfo.sectorsInfo[k - 1].side, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].size = {0}",
                                                   SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size), i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st1 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st1, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st2 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st2, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].track = {0}",
                                                   trackInfo.sectorsInfo[k - 1].track, i, j, k);

                        int sectLen = extended ? trackInfo.sectorsInfo[k - 1].len
                                          : SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size);

                        byte[] sector = new byte[sectLen];
                        stream.Read(sector, 0, sectLen);

                        if (sectLen < SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, sector.Length);
                            sector = temp;
                        }
                        else if (sectLen > SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, temp.Length);
                            sector = temp;
                        }

                        thisTrackSectors[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = sector;

                        byte[] amForCrc = new byte[8];
                        amForCrc[0] = 0xA1;
                        amForCrc[1] = 0xA1;
                        amForCrc[2] = 0xA1;
                        amForCrc[3] = (byte)IBMIdType.AddressMark;
                        amForCrc[4] = trackInfo.sectorsInfo[k - 1].track;
                        amForCrc[5] = trackInfo.sectorsInfo[k - 1].side;
                        amForCrc[6] = trackInfo.sectorsInfo[k - 1].id;
                        amForCrc[7] = (byte)trackInfo.sectorsInfo[k - 1].size;

                        CRC16IBMContext.Data(amForCrc, 8, out byte[] amCrc);

                        byte[] addressMark = new byte[22];
                        Array.Copy(amForCrc, 0, addressMark, 12, 8);
                        Array.Copy(amCrc, 0, addressMark, 20, 2);

                        thisTrackAddressMarks[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = addressMark;
                    }

                    for (int s = 0; s < thisTrackSectors.Length; s++)
                    {
                        sectors.Add(currentSector, thisTrackSectors[s]);
                        addressMarks.Add(currentSector, thisTrackAddressMarks[s]);
                        currentSector++;

                        if (thisTrackSectors[s].Length > imageInfo.SectorSize)
                        {
                            imageInfo.SectorSize = (uint)thisTrackSectors[s].Length;
                        }
                    }

                    stream.Seek(trackPos, SeekOrigin.Begin);

                    if (extended)
                    {
                        stream.Seek(header.tracksizeTable[(i * header.sides) + j] * 256, SeekOrigin.Current);
                        imageInfo.ImageSize += (ulong)(header.tracksizeTable[(i * header.sides) + j] * 256) - 256;
                    }
                    else
                    {
                        stream.Seek(header.tracksize, SeekOrigin.Current);
                        imageInfo.ImageSize += (ulong)header.tracksize - 256;
                    }

                    readtracks++;
                }
            }

            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} sectors", sectors.Count);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} tracks", readtracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "All tracks are same size? {0}", allTracksSameSize);

            imageInfo.Application          = StringHandlers.CToString(header.creator);
            imageInfo.CreationTime         = imageFilter.GetCreationTime();
            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
            imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
            imageInfo.Sectors      = (ulong)sectors.Count;
            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            imageInfo.MediaType    = MediaType.CompactFloppy;
            imageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark);

            // Debug writing full disk as raw

            /*
             * FileStream foo = new FileStream(Path.GetFileNameWithoutExtension(imageFilter.GetFilename()) + ".bin", FileMode.Create);
             * for(ulong i = 0; i < (ulong)sectors.Count; i++)
             * {
             *  byte[] foob;
             *  sectors.TryGetValue(i, out foob);
             *  foo.Write(foob, 0, foob.Length);
             * }
             * foo.Close();
             */

            imageInfo.Cylinders       = header.tracks;
            imageInfo.Heads           = header.sides;
            imageInfo.SectorsPerTrack = (uint)(imageInfo.Sectors / (imageInfo.Cylinders * imageInfo.Heads));

            return(true);
        }
Exemple #10
0
        public bool Open(IFilter imageFilter)
        {
            Header     = new ScpHeader();
            _scpStream = imageFilter.GetDataForkStream();
            _scpStream.Seek(0, SeekOrigin.Begin);

            if (_scpStream.Length < Marshal.SizeOf <ScpHeader>())
            {
                return(false);
            }

            byte[] hdr = new byte[Marshal.SizeOf <ScpHeader>()];
            _scpStream.Read(hdr, 0, Marshal.SizeOf <ScpHeader>());

            Header = Marshal.ByteArrayToStructureLittleEndian <ScpHeader>(hdr);

            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.signature = \"{0}\"",
                                       StringHandlers.CToString(Header.signature));

            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.version = {0}.{1}", (Header.version & 0xF0) >> 4,
                                       Header.version & 0xF);

            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.type = {0}", Header.type);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.revolutions = {0}", Header.revolutions);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.start = {0}", Header.start);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.end = {0}", Header.end);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.flags = {0}", Header.flags);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.bitCellEncoding = {0}", Header.bitCellEncoding);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.heads = {0}", Header.heads);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.reserved = {0}", Header.reserved);
            AaruConsole.DebugWriteLine("SuperCardPro plugin", "header.checksum = 0x{0:X8}", Header.checksum);

            if (!_scpSignature.SequenceEqual(Header.signature))
            {
                return(false);
            }

            ScpTracks = new Dictionary <byte, TrackHeader>();

            for (byte t = Header.start; t <= Header.end; t++)
            {
                if (t >= Header.offsets.Length)
                {
                    break;
                }

                _scpStream.Position = Header.offsets[t];

                var trk = new TrackHeader
                {
                    Signature = new byte[3],
                    Entries   = new TrackEntry[Header.revolutions]
                };

                _scpStream.Read(trk.Signature, 0, trk.Signature.Length);
                trk.TrackNumber = (byte)_scpStream.ReadByte();

                if (!trk.Signature.SequenceEqual(_trkSignature))
                {
                    AaruConsole.DebugWriteLine("SuperCardPro plugin",
                                               "Track header at {0} contains incorrect signature.", Header.offsets[t]);

                    continue;
                }

                if (trk.TrackNumber != t)
                {
                    AaruConsole.DebugWriteLine("SuperCardPro plugin", "Track number at {0} should be {1} but is {2}.",
                                               Header.offsets[t], t, trk.TrackNumber);

                    continue;
                }

                AaruConsole.DebugWriteLine("SuperCardPro plugin", "Found track {0} at {1}.", t, Header.offsets[t]);

                for (byte r = 0; r < Header.revolutions; r++)
                {
                    byte[] rev = new byte[Marshal.SizeOf <TrackEntry>()];
                    _scpStream.Read(rev, 0, Marshal.SizeOf <TrackEntry>());

                    trk.Entries[r] = Marshal.ByteArrayToStructureLittleEndian <TrackEntry>(rev);

                    // De-relative offsets
                    trk.Entries[r].dataOffset += Header.offsets[t];
                }

                ScpTracks.Add(t, trk);
            }

            if (Header.flags.HasFlag(ScpFlags.HasFooter))
            {
                long position = _scpStream.Position;
                _scpStream.Seek(-4, SeekOrigin.End);

                while (_scpStream.Position >= position)
                {
                    byte[] footerSig = new byte[4];
                    _scpStream.Read(footerSig, 0, 4);
                    uint footerMagic = BitConverter.ToUInt32(footerSig, 0);

                    if (footerMagic == FOOTER_SIGNATURE)
                    {
                        _scpStream.Seek(-Marshal.SizeOf <Footer>(), SeekOrigin.Current);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "Found footer at {0}", _scpStream.Position);

                        byte[] ftr = new byte[Marshal.SizeOf <Footer>()];
                        _scpStream.Read(ftr, 0, Marshal.SizeOf <Footer>());

                        Footer footer = Marshal.ByteArrayToStructureLittleEndian <Footer>(ftr);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.manufacturerOffset = 0x{0:X8}",
                                                   footer.manufacturerOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.modelOffset = 0x{0:X8}",
                                                   footer.modelOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.serialOffset = 0x{0:X8}",
                                                   footer.serialOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.creatorOffset = 0x{0:X8}",
                                                   footer.creatorOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationOffset = 0x{0:X8}",
                                                   footer.applicationOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.commentsOffset = 0x{0:X8}",
                                                   footer.commentsOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.creationTime = {0}",
                                                   footer.creationTime);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.modificationTime = {0}",
                                                   footer.modificationTime);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationVersion = {0}.{1}",
                                                   (footer.applicationVersion & 0xF0) >> 4,
                                                   footer.applicationVersion & 0xF);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.hardwareVersion = {0}.{1}",
                                                   (footer.hardwareVersion & 0xF0) >> 4, footer.hardwareVersion & 0xF);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.firmwareVersion = {0}.{1}",
                                                   (footer.firmwareVersion & 0xF0) >> 4, footer.firmwareVersion & 0xF);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.imageVersion = {0}.{1}",
                                                   (footer.imageVersion & 0xF0) >> 4, footer.imageVersion & 0xF);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "footer.signature = \"{0}\"",
                                                   StringHandlers.CToString(BitConverter.GetBytes(footer.signature)));

                        _imageInfo.DriveManufacturer = ReadPStringUtf8(_scpStream, footer.manufacturerOffset);
                        _imageInfo.DriveModel        = ReadPStringUtf8(_scpStream, footer.modelOffset);
                        _imageInfo.DriveSerialNumber = ReadPStringUtf8(_scpStream, footer.serialOffset);
                        _imageInfo.Creator           = ReadPStringUtf8(_scpStream, footer.creatorOffset);
                        _imageInfo.Application       = ReadPStringUtf8(_scpStream, footer.applicationOffset);
                        _imageInfo.Comments          = ReadPStringUtf8(_scpStream, footer.commentsOffset);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveManufacturer = \"{0}\"",
                                                   _imageInfo.DriveManufacturer);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveModel = \"{0}\"",
                                                   _imageInfo.DriveModel);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveSerialNumber = \"{0}\"",
                                                   _imageInfo.DriveSerialNumber);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreator = \"{0}\"",
                                                   _imageInfo.Creator);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageApplication = \"{0}\"",
                                                   _imageInfo.Application);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageComments = \"{0}\"",
                                                   _imageInfo.Comments);

                        _imageInfo.CreationTime = footer.creationTime != 0
                                                      ? DateHandlers.UnixToDateTime(footer.creationTime)
                                                      : imageFilter.GetCreationTime();

                        _imageInfo.LastModificationTime = footer.modificationTime != 0
                                                              ? DateHandlers.UnixToDateTime(footer.modificationTime)
                                                              : imageFilter.GetLastWriteTime();

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreationTime = {0}",
                                                   _imageInfo.CreationTime);

                        AaruConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageLastModificationTime = {0}",
                                                   _imageInfo.LastModificationTime);

                        _imageInfo.ApplicationVersion =
                            $"{(footer.applicationVersion & 0xF0) >> 4}.{footer.applicationVersion & 0xF}";

                        _imageInfo.DriveFirmwareRevision =
                            $"{(footer.firmwareVersion & 0xF0) >> 4}.{footer.firmwareVersion & 0xF}";

                        _imageInfo.Version = $"{(footer.imageVersion & 0xF0) >> 4}.{footer.imageVersion & 0xF}";

                        break;
                    }

                    _scpStream.Seek(-8, SeekOrigin.Current);
                }
            }
            else
            {
                _imageInfo.Application          = "SuperCardPro";
                _imageInfo.ApplicationVersion   = $"{(Header.version & 0xF0) >> 4}.{Header.version & 0xF}";
                _imageInfo.CreationTime         = imageFilter.GetCreationTime();
                _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
                _imageInfo.Version = "1.5";
            }

            throw new NotImplementedException("Flux decoding is not yet implemented.");
        }
Exemple #11
0
        /// <summary>Implements creating a metadata sidecar</summary>
        /// <returns>The metadata sidecar</returns>
        public CICMMetadataType Create()
        {
            // For fast debugging, skip checksum
            //goto skipImageChecksum;

            byte[] data;
            long   position = 0;

            UpdateStatus("Hashing image file...");
            InitProgress();

            while (position < _fi.Length - 1048576)
            {
                if (_aborted)
                {
                    return(_sidecar);
                }

                data = new byte[1048576];
                _fs.Read(data, 0, 1048576);

                UpdateProgress("Hashing image file byte {0} of {1}", position, _fi.Length);

                _imgChkWorker.Update(data);

                position += 1048576;
            }

            data = new byte[_fi.Length - position];
            _fs.Read(data, 0, (int)(_fi.Length - position));

            UpdateProgress("Hashing image file byte {0} of {1}", position, _fi.Length);

            _imgChkWorker.Update(data);

            // For fast debugging, skip checksum
            //skipImageChecksum:

            EndProgress();
            _fs.Close();

            List <ChecksumType> imgChecksums = _imgChkWorker.End();

            _sidecar.OpticalDisc = null;
            _sidecar.BlockMedia  = null;
            _sidecar.AudioMedia  = null;
            _sidecar.LinearMedia = null;

            if (_aborted)
            {
                return(_sidecar);
            }

            switch (_image.Info.XmlMediaType)
            {
            case XmlMediaType.OpticalDisc:
                if (_image is IOpticalMediaImage opticalImage)
                {
                    OpticalDisc(opticalImage, _filterId, _imagePath, _fi, _plugins, imgChecksums, ref _sidecar,
                                _encoding);
                }
                else
                {
                    AaruConsole.
                    ErrorWriteLine("The specified image says it contains an optical media but at the same time says it does not support them.");

                    AaruConsole.ErrorWriteLine("Please open an issue at Github.");
                }

                break;

            case XmlMediaType.BlockMedia:
                BlockMedia(_image, _filterId, _imagePath, _fi, _plugins, imgChecksums, ref _sidecar, _encoding);

                break;

            case XmlMediaType.LinearMedia:
                LinearMedia(_image, _filterId, _imagePath, _fi, _plugins, imgChecksums, ref _sidecar, _encoding);

                break;

            case XmlMediaType.AudioMedia:
                AudioMedia(_image, _filterId, _imagePath, _fi, _plugins, imgChecksums, ref _sidecar, _encoding);

                break;
            }

            return(_sidecar);
        }
Exemple #12
0
        /// <summary>Sends the MMC READ CD command</summary>
        /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
        /// <param name="buffer">Buffer where the MMC READ CD response will be stored</param>
        /// <param name="senseBuffer">Sense buffer.</param>
        /// <param name="timeout">Timeout in seconds.</param>
        /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
        /// <param name="lba">Start block address.</param>
        /// <param name="transferLength">How many blocks to read.</param>
        /// <param name="blockSize">Block size.</param>
        /// <param name="expectedSectorType">Expected sector type.</param>
        /// <param name="dap">If set to <c>true</c> CD-DA should be modified by mute and interpolation</param>
        /// <param name="relAddr">If set to <c>true</c> address is relative to current position.</param>
        /// <param name="sync">If set to <c>true</c> we request the sync bytes for data sectors.</param>
        /// <param name="headerCodes">Header codes.</param>
        /// <param name="userData">If set to <c>true</c> we request the user data.</param>
        /// <param name="edcEcc">If set to <c>true</c> we request the EDC/ECC fields for data sectors.</param>
        /// <param name="c2Error">C2 error options.</param>
        /// <param name="subchannel">Subchannel selection.</param>
        public bool ReadCd(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint transferLength,
                           MmcSectorTypes expectedSectorType, bool dap, bool relAddr, bool sync,
                           MmcHeaderCodes headerCodes, bool userData, bool edcEcc, MmcErrorField c2Error,
                           MmcSubchannel subchannel, uint timeout, out double duration)
        {
            senseBuffer = new byte[32];
            byte[] cdb = new byte[12];

            cdb[0] = (byte)ScsiCommands.ReadCd;
            cdb[1] = (byte)((byte)expectedSectorType << 2);

            if (dap)
            {
                cdb[1] += 0x02;
            }

            if (relAddr)
            {
                cdb[1] += 0x01;
            }

            cdb[2]  = (byte)((lba & 0xFF000000) >> 24);
            cdb[3]  = (byte)((lba & 0xFF0000) >> 16);
            cdb[4]  = (byte)((lba & 0xFF00) >> 8);
            cdb[5]  = (byte)(lba & 0xFF);
            cdb[6]  = (byte)((transferLength & 0xFF0000) >> 16);
            cdb[7]  = (byte)((transferLength & 0xFF00) >> 8);
            cdb[8]  = (byte)(transferLength & 0xFF);
            cdb[9]  = (byte)((byte)c2Error << 1);
            cdb[9] += (byte)((byte)headerCodes << 5);

            if (sync)
            {
                cdb[9] += 0x80;
            }

            if (userData)
            {
                cdb[9] += 0x10;
            }

            if (edcEcc)
            {
                cdb[9] += 0x08;
            }

            cdb[10] = (byte)subchannel;

            buffer = new byte[blockSize * transferLength];

            LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
                                        out bool sense);

            Error = LastError != 0;

            AaruConsole.DebugWriteLine("SCSI Device",
                                       "READ CD (LBA: {1}, Block Size: {2}, Transfer Length: {3}, Expected Sector Type: {4}, DAP: {5}, Relative Address: {6}, Sync: {7}, Headers: {8}, User Data: {9}, ECC/EDC: {10}, C2: {11}, Subchannel: {12}, Sense: {13}, Last Error: {14}) took {0} ms.",
                                       duration, lba, blockSize, transferLength, expectedSectorType, dap, relAddr, sync,
                                       headerCodes, userData, edcEcc, c2Error, subchannel, sense, LastError);

            return(sense);
        }
Exemple #13
0
        /// <summary>Sends the MMC READ DISC STRUCTURE command</summary>
        /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
        /// <param name="buffer">Buffer where the SCSI READ DISC STRUCTURE response will be stored</param>
        /// <param name="senseBuffer">Sense buffer.</param>
        /// <param name="mediaType">Medium type for requested disc structure</param>
        /// <param name="address">Medium address for requested disc structure</param>
        /// <param name="layerNumber">Medium layer for requested disc structure</param>
        /// <param name="timeout">Timeout in seconds.</param>
        /// <param name="format">Which disc structure are we requesting</param>
        /// <param name="agid">AGID used in medium copy protection</param>
        /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
        public bool ReadDiscStructure(out byte[] buffer, out byte[] senseBuffer, MmcDiscStructureMediaType mediaType,
                                      uint address, byte layerNumber, MmcDiscStructureFormat format, byte agid,
                                      uint timeout, out double duration)
        {
            senseBuffer = new byte[32];
            byte[] cdb = new byte[12];
            buffer = new byte[8];

            cdb[0]  = (byte)ScsiCommands.ReadDiscStructure;
            cdb[1]  = (byte)((byte)mediaType & 0x0F);
            cdb[2]  = (byte)((address & 0xFF000000) >> 24);
            cdb[3]  = (byte)((address & 0xFF0000) >> 16);
            cdb[4]  = (byte)((address & 0xFF00) >> 8);
            cdb[5]  = (byte)(address & 0xFF);
            cdb[6]  = layerNumber;
            cdb[7]  = (byte)format;
            cdb[8]  = (byte)((buffer.Length & 0xFF00) >> 8);
            cdb[9]  = (byte)(buffer.Length & 0xFF);
            cdb[10] = (byte)((agid & 0x03) << 6);

            LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
                                        out bool sense);

            Error = LastError != 0;

            if (sense)
            {
                return(true);
            }

            ushort strctLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);

            // WORKAROUND: Some drives return incorrect length information. As these structures are fixed length just apply known length.
            if (mediaType == MmcDiscStructureMediaType.Bd)
            {
                switch (format)
                {
                case MmcDiscStructureFormat.DiscInformation:
                    buffer = new byte[4100];

                    break;

                case MmcDiscStructureFormat.BdBurstCuttingArea:
                    buffer = new byte[68];

                    break;

                case MmcDiscStructureFormat.BdDds:
                    buffer = new byte[strctLength < 100 ? 100 : strctLength];

                    break;

                case MmcDiscStructureFormat.CartridgeStatus:
                    buffer = new byte[8];

                    break;

                case MmcDiscStructureFormat.BdSpareAreaInformation:
                    buffer = new byte[16];

                    break;

                default:
                    buffer = new byte[strctLength];

                    break;
                }
            }
            else
            {
                buffer = new byte[strctLength];
            }

            cdb[8]      = (byte)((buffer.Length & 0xFF00) >> 8);
            cdb[9]      = (byte)(buffer.Length & 0xFF);
            senseBuffer = new byte[32];

            LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
                                        out sense);

            Error = LastError != 0;

            AaruConsole.DebugWriteLine("SCSI Device",
                                       "READ DISC STRUCTURE (Media Type: {1}, Address: {2}, Layer Number: {3}, Format: {4}, AGID: {5}, Sense: {6}, Last Error: {7}) took {0} ms.",
                                       duration, mediaType, address, layerNumber, format, agid, sense, LastError);

            return(sense);
        }
Exemple #14
0
        void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardwareType currentTry,
                             ExtentsULong extents, int offsetBytes, bool readcd, int sectorsForOffset, uint subSize,
                             MmcSubchannel supportedSubchannel, ref double totalDuration)
        {
            bool sense = true;                   // Sense indicator

            byte[]     cmdBuf = null;            // Data buffer
            double     cmdDuration;              // Command execution time
            const uint sectorSize = 2352;        // Full sector size

            byte[]            senseBuf = null;   // Sense buffer
            PlextorSubchannel supportedPlextorSubchannel;

            switch (supportedSubchannel)
            {
            case MmcSubchannel.None:
                supportedPlextorSubchannel = PlextorSubchannel.None;

                break;

            case MmcSubchannel.Raw:
                supportedPlextorSubchannel = PlextorSubchannel.All;

                break;

            case MmcSubchannel.Q16:
                supportedPlextorSubchannel = PlextorSubchannel.Q16;

                break;

            case MmcSubchannel.Rw:
                supportedPlextorSubchannel = PlextorSubchannel.Pack;

                break;

            default:
                supportedPlextorSubchannel = PlextorSubchannel.None;

                break;
            }

            if (_resume.BadBlocks.Count <= 0 ||
                _aborted ||
                _retryPasses <= 0)
            {
                return;
            }

            int  pass              = 1;
            bool forward           = true;
            bool runningPersistent = false;

            Modes.ModePage?currentModePage = null;
            byte[]         md6;
            byte[]         md10;

            if (_persistent)
            {
                Modes.ModePage_01_MMC pgMmc;

                sense = _dev.ModeSense6(out cmdBuf, out _, false, ScsiModeSensePageControl.Current, 0x01, _dev.Timeout,
                                        out _);

                if (sense)
                {
                    sense = _dev.ModeSense10(out cmdBuf, out _, false, ScsiModeSensePageControl.Current, 0x01,
                                             _dev.Timeout, out _);

                    if (!sense)
                    {
                        Modes.DecodedMode?dcMode10 =
                            Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);

                        if (dcMode10?.Pages != null)
                        {
                            foreach (Modes.ModePage modePage in dcMode10.Value.Pages)
                            {
                                if (modePage.Page == 0x01 &&
                                    modePage.Subpage == 0x00)
                                {
                                    currentModePage = modePage;
                                }
                            }
                        }
                    }
                }
                else
                {
                    Modes.DecodedMode?dcMode6 = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);

                    if (dcMode6?.Pages != null)
                    {
                        foreach (Modes.ModePage modePage in dcMode6.Value.Pages)
                        {
                            if (modePage.Page == 0x01 &&
                                modePage.Subpage == 0x00)
                            {
                                currentModePage = modePage;
                            }
                        }
                    }
                }

                if (currentModePage == null)
                {
                    pgMmc = new Modes.ModePage_01_MMC
                    {
                        PS = false, ReadRetryCount = 32, Parameter = 0x00
                    };

                    currentModePage = new Modes.ModePage
                    {
                        Page = 0x01, Subpage = 0x00, PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
                    };
                }

                pgMmc = new Modes.ModePage_01_MMC
                {
                    PS = false, ReadRetryCount = 255, Parameter = 0x20
                };

                var md = new Modes.DecodedMode
                {
                    Header = new Modes.ModeHeader(), Pages = new[]
                    {
                        new Modes.ModePage
                        {
                            Page = 0x01, Subpage = 0x00, PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
                        }
                    }
                };

                md6  = Modes.EncodeMode6(md, _dev.ScsiType);
                md10 = Modes.EncodeMode10(md, _dev.ScsiType);

                UpdateStatus?.Invoke("Sending MODE SELECT to drive (return damaged blocks).");
                _dumpLog.WriteLine("Sending MODE SELECT to drive (return damaged blocks).");
                sense = _dev.ModeSelect(md6, out senseBuf, true, false, _dev.Timeout, out _);

                if (sense)
                {
                    sense = _dev.ModeSelect10(md10, out senseBuf, true, false, _dev.Timeout, out _);
                }

                if (sense)
                {
                    UpdateStatus?.
                    Invoke("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");

                    AaruConsole.DebugWriteLine("Error: {0}", Sense.PrettifySense(senseBuf));

                    _dumpLog.WriteLine("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");
                }
                else
                {
                    runningPersistent = true;
                }
            }

            InitProgress?.Invoke();
cdRepeatRetry:
            ulong[]      tmpArray = _resume.BadBlocks.ToArray();
            List <ulong> sectorsNotEvenPartial = new List <ulong>();

            foreach (ulong badSector in tmpArray)
            {
                if (_aborted)
                {
                    currentTry.Extents = ExtentsConverter.ToMetadata(extents);
                    _dumpLog.WriteLine("Aborted!");

                    break;
                }

                PulseProgress?.Invoke(string.Format("Retrying sector {0}, pass {1}, {3}{2}", badSector, pass,
                                                    forward ? "forward" : "reverse",
                                                    runningPersistent ? "recovering partial data, " : ""));

                byte sectorsToReRead   = 1;
                uint badSectorToReRead = (uint)badSector;

                if (_fixOffset &&
                    audioExtents.Contains(badSector) &&
                    offsetBytes != 0)
                {
                    if (offsetBytes > 0)
                    {
                        badSectorToReRead -= (uint)sectorsForOffset;
                    }

                    sectorsToReRead = (byte)(sectorsForOffset + 1);
                }

                if (_supportsPlextorD8 && audioExtents.Contains(badSector))
                {
                    sense = ReadPlextorWithSubchannel(out cmdBuf, out senseBuf, badSectorToReRead, blockSize,
                                                      sectorsToReRead, supportedPlextorSubchannel, out cmdDuration);

                    totalDuration += cmdDuration;
                }
                else if (readcd)
                {
                    sense = _dev.ReadCd(out cmdBuf, out senseBuf, badSectorToReRead, blockSize, sectorsToReRead,
                                        MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
                                        true, MmcErrorField.None, supportedSubchannel, _dev.Timeout, out cmdDuration);

                    totalDuration += cmdDuration;
                }

                if (sense || _dev.Error)
                {
                    if (!runningPersistent)
                    {
                        continue;
                    }

                    FixedSense?decSense = Sense.DecodeFixed(senseBuf);

                    // MEDIUM ERROR, retry with ignore error below
                    if (decSense.HasValue &&
                        decSense.Value.ASC == 0x11)
                    {
                        if (!sectorsNotEvenPartial.Contains(badSector))
                        {
                            sectorsNotEvenPartial.Add(badSector);
                        }
                    }
                }

                // Because one block has been partially used to fix the offset
                if (_fixOffset &&
                    audioExtents.Contains(badSector) &&
                    offsetBytes != 0)
                {
                    uint blocksToRead = sectorsToReRead;

                    FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, ref blocksToRead,
                                  subSize, ref cmdBuf, blockSize, false);
                }

                if (!sense &&
                    !_dev.Error)
                {
                    _resume.BadBlocks.Remove(badSector);
                    extents.Add(badSector);
                    UpdateStatus?.Invoke($"Correctly retried sector {badSector} in pass {pass}.");
                    _dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass);
                    sectorsNotEvenPartial.Remove(badSector);
                }

                if (supportedSubchannel != MmcSubchannel.None)
                {
                    byte[] data = new byte[sectorSize];
                    byte[] sub  = new byte[subSize];
                    Array.Copy(cmdBuf, 0, data, 0, sectorSize);
                    Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
                    _outputPlugin.WriteSectorLong(data, badSector);
                    _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
                }
                else
                {
                    _outputPlugin.WriteSectorLong(cmdBuf, badSector);
                }
            }

            if (pass < _retryPasses &&
                !_aborted &&
                _resume.BadBlocks.Count > 0)
            {
                pass++;
                forward = !forward;
                _resume.BadBlocks.Sort();
                _resume.BadBlocks.Reverse();

                goto cdRepeatRetry;
            }

            EndProgress?.Invoke();

            // TODO: Enable when underlying images support lead-outs

            /*
             *  RetryCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration,
             *         leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd,
             *         supportedSubchannel, subSize, ref totalDuration);
             */

            // Try to ignore read errors, on some drives this allows to recover partial even if damaged data
            if (_persistent && sectorsNotEvenPartial.Count > 0)
            {
                var pgMmc = new Modes.ModePage_01_MMC
                {
                    PS = false, ReadRetryCount = 255, Parameter = 0x01
                };

                var md = new Modes.DecodedMode
                {
                    Header = new Modes.ModeHeader(), Pages = new[]
                    {
                        new Modes.ModePage
                        {
                            Page = 0x01, Subpage = 0x00, PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
                        }
                    }
                };

                md6  = Modes.EncodeMode6(md, _dev.ScsiType);
                md10 = Modes.EncodeMode10(md, _dev.ScsiType);

                _dumpLog.WriteLine("Sending MODE SELECT to drive (ignore error correction).");
                sense = _dev.ModeSelect(md6, out senseBuf, true, false, _dev.Timeout, out _);

                if (sense)
                {
                    sense = _dev.ModeSelect10(md10, out senseBuf, true, false, _dev.Timeout, out _);
                }

                if (!sense)
                {
                    runningPersistent = true;

                    InitProgress?.Invoke();

                    foreach (ulong badSector in sectorsNotEvenPartial)
                    {
                        if (_aborted)
                        {
                            currentTry.Extents = ExtentsConverter.ToMetadata(extents);
                            _dumpLog.WriteLine("Aborted!");

                            break;
                        }

                        PulseProgress?.Invoke($"Trying to get partial data for sector {badSector}");

                        if (readcd)
                        {
                            sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1,
                                                MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
                                                true, true, MmcErrorField.None, supportedSubchannel, _dev.Timeout,
                                                out cmdDuration);

                            totalDuration += cmdDuration;
                        }

                        if (sense || _dev.Error)
                        {
                            continue;
                        }

                        _dumpLog.WriteLine("Got partial data for sector {0} in pass {1}.", badSector, pass);

                        if (supportedSubchannel != MmcSubchannel.None)
                        {
                            byte[] data = new byte[sectorSize];
                            byte[] sub  = new byte[subSize];
                            Array.Copy(cmdBuf, 0, data, 0, sectorSize);
                            Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
                            _outputPlugin.WriteSectorLong(data, badSector);
                            _outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
                        }
                        else
                        {
                            _outputPlugin.WriteSectorLong(cmdBuf, badSector);
                        }
                    }

                    EndProgress?.Invoke();
                }
            }

            if (runningPersistent && currentModePage.HasValue)
            {
                var md = new Modes.DecodedMode
                {
                    Header = new Modes.ModeHeader(), Pages = new[]
                    {
                        currentModePage.Value
                    }
                };

                md6  = Modes.EncodeMode6(md, _dev.ScsiType);
                md10 = Modes.EncodeMode10(md, _dev.ScsiType);

                _dumpLog.WriteLine("Sending MODE SELECT to drive (return device to previous status).");
                sense = _dev.ModeSelect(md6, out senseBuf, true, false, _dev.Timeout, out _);

                if (sense)
                {
                    _dev.ModeSelect10(md10, out senseBuf, true, false, _dev.Timeout, out _);
                }
            }

            EndProgress?.Invoke();
        }
Exemple #15
0
        static void Park(string devPath, Device dev)
        {
start:
            System.Console.Clear();
            bool sense = dev.CertancePark(out byte[] senseBuffer, dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending PARK to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Sense buffer is {0} bytes.", senseBuffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Sense buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(senseBuffer));
            AaruConsole.WriteLine("PARK decoded sense:");
            AaruConsole.Write("{0}", Sense.PrettifySense(senseBuffer));
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print sense buffer.");
            AaruConsole.WriteLine("2.- Send command again.");
            AaruConsole.WriteLine("0.- Return to Certance vendor commands menu.");
            AaruConsole.Write("Choose: ");

            string strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out int item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to Certance vendor commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("PARK sense:");

                if (senseBuffer != null)
                {
                    PrintHex.PrintHexArray(senseBuffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2: goto start;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #16
0
        public static void PrintImageInfo(IMediaImage imageFormat)
        {
            AaruConsole.WriteLine("Image information:");

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Version))
            {
                AaruConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version);
            }
            else
            {
                AaruConsole.WriteLine("Format: {0}", imageFormat.Format);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application) &&
                !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion))
            {
                AaruConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application,
                                      imageFormat.Info.ApplicationVersion);
            }
            else if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
            {
                AaruConsole.WriteLine("Was created with {0}", imageFormat.Info.Application);
            }

            AaruConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize);

            AaruConsole.
            WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)",
                      imageFormat.Info.Sectors, imageFormat.Info.SectorSize,
                      imageFormat.Info.Sectors * imageFormat.Info.SectorSize);

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
            {
                AaruConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator);
            }

            if (imageFormat.Info.CreationTime != DateTime.MinValue)
            {
                AaruConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime);
            }

            if (imageFormat.Info.LastModificationTime != DateTime.MinValue)
            {
                AaruConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime);
            }

            AaruConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType,
                                  imageFormat.Info.XmlMediaType);

            AaruConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have");
            AaruConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have");

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Comments))
            {
                AaruConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments);
            }

            if (imageFormat.Info.MediaSequence != 0 &&
                imageFormat.Info.LastMediaSequence != 0)
            {
                AaruConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence,
                                      imageFormat.Info.LastMediaSequence);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
            {
                AaruConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
            {
                AaruConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
            {
                AaruConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
            {
                AaruConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
            {
                AaruConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
            {
                AaruConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
            {
                AaruConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
            {
                AaruConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
            {
                AaruConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber);
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
            {
                AaruConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision);
            }

            if (imageFormat.Info.Cylinders > 0 &&
                imageFormat.Info.Heads > 0 &&
                imageFormat.Info.SectorsPerTrack > 0 &&
                imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc &&
                (!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape))
            {
                AaruConsole.WriteLine("Media geometry: {0} cylinders, {1} heads, {2} sectors per track",
                                      imageFormat.Info.Cylinders, imageFormat.Info.Heads,
                                      imageFormat.Info.SectorsPerTrack);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Count > 0)
            {
                AaruConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count);

                foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
                {
                    AaruConsole.Write("{0} ", tag);
                }

                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableSectorTags != null &&
                imageFormat.Info.ReadableSectorTags.Count > 0)
            {
                AaruConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count);

                foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
                {
                    AaruConsole.Write("{0} ", tag);
                }

                AaruConsole.WriteLine();
            }

            AaruConsole.WriteLine();
            PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;

            byte[] scsiVendorId = null;

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_INQUIRY) == true)
            {
                byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);

                scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F);

                if (inquiry.Length >= 16)
                {
                    scsiVendorId = new byte[8];
                    Array.Copy(inquiry, 8, scsiVendorId, 0, 8);
                }

                AaruConsole.WriteLine("SCSI INQUIRY contained in image:");
                AaruConsole.Write("{0}", Inquiry.Prettify(inquiry));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.ATA_IDENTIFY) == true)
            {
                byte[] identify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY);

                AaruConsole.WriteLine("ATA IDENTIFY contained in image:");
                AaruConsole.Write("{0}", Identify.Prettify(identify));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.ATAPI_IDENTIFY) == true)
            {
                byte[] identify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY);

                AaruConsole.WriteLine("ATAPI IDENTIFY contained in image:");
                AaruConsole.Write("{0}", Identify.Prettify(identify));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_MODESENSE_10) == true)
            {
                byte[]            modeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10);
                Modes.DecodedMode?decMode     = Modes.DecodeMode10(modeSense10, scsiDeviceType);

                if (decMode.HasValue)
                {
                    AaruConsole.WriteLine("SCSI MODE SENSE (10) contained in image:");
                    PrintScsiModePages.Print(decMode.Value, scsiDeviceType, scsiVendorId);
                    AaruConsole.WriteLine();
                }
            }
            else if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_MODESENSE_6) == true)
            {
                byte[]            modeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6);
                Modes.DecodedMode?decMode    = Modes.DecodeMode6(modeSense6, scsiDeviceType);

                if (decMode.HasValue)
                {
                    AaruConsole.WriteLine("SCSI MODE SENSE (6) contained in image:");
                    PrintScsiModePages.Print(decMode.Value, scsiDeviceType, scsiVendorId);
                    AaruConsole.WriteLine();
                }
            }
            else if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SCSI_MODEPAGE_2A) == true)
            {
                byte[] mode2A = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODEPAGE_2A);

                AaruConsole.Write("{0}", Modes.PrettifyModePage_2A(mode2A));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC) == true)
            {
                byte[] toc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC);

                if (toc.Length > 0)
                {
                    ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0));

                    if (dataLen + 2 != toc.Length)
                    {
                        byte[] tmp = new byte[toc.Length + 2];
                        Array.Copy(toc, 0, tmp, 2, toc.Length);
                        tmp[0] = (byte)((toc.Length & 0xFF00) >> 8);
                        tmp[1] = (byte)(toc.Length & 0xFF);
                        toc    = tmp;
                    }

                    AaruConsole.WriteLine("CompactDisc Table of Contents contained in image:");
                    AaruConsole.Write("{0}", FullTOC.Prettify(toc));
                    AaruConsole.WriteLine();
                }
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_PMA) == true)
            {
                byte[] pma = imageFormat.ReadDiskTag(MediaTagType.CD_PMA);

                if (pma.Length > 0)
                {
                    ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0));

                    if (dataLen + 2 != pma.Length)
                    {
                        byte[] tmp = new byte[pma.Length + 2];
                        Array.Copy(pma, 0, tmp, 2, pma.Length);
                        tmp[0] = (byte)((pma.Length & 0xFF00) >> 8);
                        tmp[1] = (byte)(pma.Length & 0xFF);
                        pma    = tmp;
                    }

                    AaruConsole.WriteLine("CompactDisc Power Management Area contained in image:");
                    AaruConsole.Write("{0}", PMA.Prettify(pma));
                    AaruConsole.WriteLine();
                }
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_ATIP) == true)
            {
                byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP);

                uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0));

                if (dataLen + 4 != atip.Length)
                {
                    byte[] tmp = new byte[atip.Length + 4];
                    Array.Copy(atip, 0, tmp, 4, atip.Length);
                    tmp[0] = (byte)((atip.Length & 0xFF000000) >> 24);
                    tmp[1] = (byte)((atip.Length & 0xFF0000) >> 16);
                    tmp[2] = (byte)((atip.Length & 0xFF00) >> 8);
                    tmp[3] = (byte)(atip.Length & 0xFF);
                    atip   = tmp;
                }

                AaruConsole.WriteLine("CompactDisc Absolute Time In Pregroove (ATIP) contained in image:");
                AaruConsole.Write("{0}", ATIP.Prettify(atip));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_TEXT) == true)
            {
                byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT);

                uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0));

                if (dataLen + 4 != cdtext.Length)
                {
                    byte[] tmp = new byte[cdtext.Length + 4];
                    Array.Copy(cdtext, 0, tmp, 4, cdtext.Length);
                    tmp[0] = (byte)((cdtext.Length & 0xFF000000) >> 24);
                    tmp[1] = (byte)((cdtext.Length & 0xFF0000) >> 16);
                    tmp[2] = (byte)((cdtext.Length & 0xFF00) >> 8);
                    tmp[3] = (byte)(cdtext.Length & 0xFF);
                    cdtext = tmp;
                }

                AaruConsole.WriteLine("CompactDisc Lead-in's CD-Text contained in image:");
                AaruConsole.Write("{0}", CDTextOnLeadIn.Prettify(cdtext));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.CD_MCN) == true)
            {
                byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN);

                AaruConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}",
                                      Encoding.UTF8.GetString(mcn));

                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVD_PFI) == true)
            {
                byte[] pfi = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI);

                AaruConsole.WriteLine("DVD Physical Format Information contained in image:");
                AaruConsole.Write("{0}", PFI.Prettify(pfi));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDRAM_DDS) == true)
            {
                byte[] dds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS);

                AaruConsole.WriteLine("DVD-RAM Disc Definition Structure contained in image:");
                AaruConsole.Write("{0}", DDS.Prettify(dds));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.DVDR_PFI) == true)
            {
                byte[] pfi = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI);

                AaruConsole.WriteLine("DVD-R Physical Format Information contained in image:");
                AaruConsole.Write("{0}", PFI.Prettify(pfi));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_DI) == true)
            {
                byte[] di = imageFormat.ReadDiskTag(MediaTagType.BD_DI);

                AaruConsole.WriteLine("Bluray Disc Information contained in image:");
                AaruConsole.Write("{0}", DI.Prettify(di));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.BD_DDS) == true)
            {
                byte[] dds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS);

                AaruConsole.WriteLine("Bluray Disc Definition Structure contained in image:");
                AaruConsole.Write("{0}", Decoders.Bluray.DDS.Prettify(dds));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.PCMCIA_CIS) == true)
            {
                byte[] cis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS);

                AaruConsole.WriteLine("PCMCIA CIS:");
                Tuple[] tuples = CIS.GetTuples(cis);

                if (tuples != null)
                {
                    foreach (Tuple tuple in tuples)
                    {
                        switch (tuple.Code)
                        {
                        case TupleCodes.CISTPL_NULL:
                        case TupleCodes.CISTPL_END: break;

                        case TupleCodes.CISTPL_DEVICEGEO:
                        case TupleCodes.CISTPL_DEVICEGEO_A:
                            AaruConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple));

                            break;

                        case TupleCodes.CISTPL_MANFID:
                            AaruConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple));

                            break;

                        case TupleCodes.CISTPL_VERS_1:
                            AaruConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple));

                            break;

                        case TupleCodes.CISTPL_ALTSTR:
                        case TupleCodes.CISTPL_BAR:
                        case TupleCodes.CISTPL_BATTERY:
                        case TupleCodes.CISTPL_BYTEORDER:
                        case TupleCodes.CISTPL_CFTABLE_ENTRY:
                        case TupleCodes.CISTPL_CFTABLE_ENTRY_CB:
                        case TupleCodes.CISTPL_CHECKSUM:
                        case TupleCodes.CISTPL_CONFIG:
                        case TupleCodes.CISTPL_CONFIG_CB:
                        case TupleCodes.CISTPL_DATE:
                        case TupleCodes.CISTPL_DEVICE:
                        case TupleCodes.CISTPL_DEVICE_A:
                        case TupleCodes.CISTPL_DEVICE_OA:
                        case TupleCodes.CISTPL_DEVICE_OC:
                        case TupleCodes.CISTPL_EXTDEVIC:
                        case TupleCodes.CISTPL_FORMAT:
                        case TupleCodes.CISTPL_FORMAT_A:
                        case TupleCodes.CISTPL_FUNCE:
                        case TupleCodes.CISTPL_FUNCID:
                        case TupleCodes.CISTPL_GEOMETRY:
                        case TupleCodes.CISTPL_INDIRECT:
                        case TupleCodes.CISTPL_JEDEC_A:
                        case TupleCodes.CISTPL_JEDEC_C:
                        case TupleCodes.CISTPL_LINKTARGET:
                        case TupleCodes.CISTPL_LONGLINK_A:
                        case TupleCodes.CISTPL_LONGLINK_C:
                        case TupleCodes.CISTPL_LONGLINK_CB:
                        case TupleCodes.CISTPL_LONGLINK_MFC:
                        case TupleCodes.CISTPL_NO_LINK:
                        case TupleCodes.CISTPL_ORG:
                        case TupleCodes.CISTPL_PWR_MGMNT:
                        case TupleCodes.CISTPL_SPCL:
                        case TupleCodes.CISTPL_SWIL:
                        case TupleCodes.CISTPL_VERS_2:
                            AaruConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}",
                                                       tuple.Code);

                            break;

                        default:
                            AaruConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}",
                                                       (byte)tuple.Code);

                            break;
                        }
                    }
                }
                else
                {
                    AaruConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
                }
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_CID) == true)
            {
                byte[] cid = imageFormat.ReadDiskTag(MediaTagType.SD_CID);

                AaruConsole.WriteLine("SecureDigital CID contained in image:");
                AaruConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyCID(cid));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_CSD) == true)
            {
                byte[] csd = imageFormat.ReadDiskTag(MediaTagType.SD_CSD);

                AaruConsole.WriteLine("SecureDigital CSD contained in image:");
                AaruConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyCSD(csd));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_SCR) == true)
            {
                byte[] scr = imageFormat.ReadDiskTag(MediaTagType.SD_SCR);

                AaruConsole.WriteLine("SecureDigital SCR contained in image:");
                AaruConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifySCR(scr));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.SD_OCR) == true)
            {
                byte[] ocr = imageFormat.ReadDiskTag(MediaTagType.SD_OCR);

                AaruConsole.WriteLine("SecureDigital OCR contained in image:");
                AaruConsole.Write("{0}", Decoders.SecureDigital.Decoders.PrettifyOCR(ocr));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_CID) == true)
            {
                byte[] cid = imageFormat.ReadDiskTag(MediaTagType.MMC_CID);

                AaruConsole.WriteLine("MultiMediaCard CID contained in image:");
                AaruConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyCID(cid));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_CSD) == true)
            {
                byte[] csd = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD);

                AaruConsole.WriteLine("MultiMediaCard CSD contained in image:");
                AaruConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyCSD(csd));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_ExtendedCSD) == true)
            {
                byte[] ecsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD);

                AaruConsole.WriteLine("MultiMediaCard ExtendedCSD contained in image:");
                AaruConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyExtendedCSD(ecsd));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.MMC_OCR) == true)
            {
                byte[] ocr = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR);

                AaruConsole.WriteLine("MultiMediaCard OCR contained in image:");
                AaruConsole.Write("{0}", Decoders.MMC.Decoders.PrettifyOCR(ocr));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.Xbox_PFI) == true)
            {
                byte[] xpfi = imageFormat.ReadDiskTag(MediaTagType.Xbox_PFI);

                AaruConsole.WriteLine("Xbox Physical Format Information contained in image:");
                AaruConsole.Write("{0}", PFI.Prettify(xpfi));
                AaruConsole.WriteLine();
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.Xbox_DMI) == true)
            {
                byte[] xdmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI);

                if (DMI.IsXbox(xdmi))
                {
                    DMI.XboxDMI?xmi = DMI.DecodeXbox(xdmi);

                    if (xmi.HasValue)
                    {
                        AaruConsole.WriteLine("Xbox DMI contained in image:");
                        AaruConsole.Write("{0}", DMI.PrettifyXbox(xmi));
                        AaruConsole.WriteLine();
                    }
                }

                if (DMI.IsXbox360(xdmi))
                {
                    DMI.Xbox360DMI?xmi = DMI.DecodeXbox360(xdmi);

                    if (xmi.HasValue)
                    {
                        AaruConsole.WriteLine("Xbox 360 DMI contained in image:");
                        AaruConsole.Write("{0}", DMI.PrettifyXbox360(xmi));
                        AaruConsole.WriteLine();
                    }
                }
            }

            if (imageFormat.Info.ReadableMediaTags?.Contains(MediaTagType.Xbox_SecuritySector) == true)
            {
                byte[] toc = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector);

                AaruConsole.WriteLine("Xbox Security Sectors contained in image:");
                AaruConsole.Write("{0}", SS.Prettify(toc));
                AaruConsole.WriteLine();
            }

            if (imageFormat is IOpticalMediaImage opticalImage)
            {
                try
                {
                    if (opticalImage.Sessions != null &&
                        opticalImage.Sessions.Count > 0)
                    {
                        AaruConsole.WriteLine("Image sessions:");

                        AaruConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track",
                                              "Last track", "Start", "End");

                        AaruConsole.WriteLine("=========================================================");

                        foreach (Session session in opticalImage.Sessions)
                        {
                            AaruConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence,
                                                  session.StartTrack, session.EndTrack, session.StartSector,
                                                  session.EndSector);
                        }

                        AaruConsole.WriteLine();
                    }
                }
                catch
                {
                    // ignored
                }

                try
                {
                    if (opticalImage.Tracks != null &&
                        opticalImage.Tracks.Count > 0)
                    {
                        AaruConsole.WriteLine("Image tracks:");

                        AaruConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type",
                                              "Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End");

                        AaruConsole.
                        WriteLine("=================================================================================");

                        foreach (Track track in opticalImage.Tracks)
                        {
                            AaruConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}",
                                                  track.TrackSequence, track.TrackType, track.TrackBytesPerSector,
                                                  track.TrackRawBytesPerSector, track.TrackSubchannelType,
                                                  track.TrackPregap, track.TrackStartSector, track.TrackEndSector);
                        }

                        AaruConsole.WriteLine();

                        AaruConsole.WriteLine("Track indexes:");

                        AaruConsole.WriteLine("{0,-7}{1,-7}{2,-12}", "Track", "Index", "Start");

                        AaruConsole.WriteLine("=======================");

                        foreach (Track track in opticalImage.Tracks)
                        {
                            foreach (KeyValuePair <ushort, int> index in track.Indexes)
                            {
                                AaruConsole.WriteLine("{0,-7}{1,-7}{2,-12}", track.TrackSequence, index.Key,
                                                      index.Value);
                            }
                        }
                    }
                }
                catch
                {
                    // ignored
                }
                finally
                {
                    AaruConsole.WriteLine();
                }
            }

            if (imageFormat.DumpHardware == null)
            {
                return;
            }

            int manufacturerLen = MANUFACTURER_STRING.Length;
            int modelLen        = MODEL_STRING.Length;
            int serialLen       = SERIAL_STRING.Length;
            int softwareLen     = SOFTWARE_STRING.Length;
            int versionLen      = VERSION_STRING.Length;
            int osLen           = OS_STRING.Length;
            int sectorLen       = START_STRING.Length;

            foreach (DumpHardwareType dump in imageFormat.DumpHardware)
            {
                if (dump.Manufacturer?.Length > manufacturerLen)
                {
                    manufacturerLen = dump.Manufacturer.Length;
                }

                if (dump.Model?.Length > modelLen)
                {
                    modelLen = dump.Model.Length;
                }

                if (dump.Serial?.Length > serialLen)
                {
                    serialLen = dump.Serial.Length;
                }

                if (dump.Software?.Name?.Length > softwareLen)
                {
                    softwareLen = dump.Software.Name.Length;
                }

                if (dump.Software?.Version?.Length > versionLen)
                {
                    versionLen = dump.Software.Version.Length;
                }

                if (dump.Software?.OperatingSystem?.Length > osLen)
                {
                    osLen = dump.Software.OperatingSystem.Length;
                }

                foreach (ExtentType extent in dump.Extents)
                {
                    if ($"{extent.Start}".Length > sectorLen)
                    {
                        sectorLen = $"{extent.Start}".Length;
                    }

                    if ($"{extent.End}".Length > sectorLen)
                    {
                        sectorLen = $"{extent.End}".Length;
                    }
                }
            }

            manufacturerLen += 2;
            modelLen        += 2;
            serialLen       += 2;
            softwareLen     += 2;
            versionLen      += 2;
            osLen           += 2;
            sectorLen       += 2;
            sectorLen       += 2;

            char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen +
                                        sectorLen + sectorLen];

            for (int i = 0; i < separator.Length; i++)
            {
                separator[i] = '=';
            }

            string format =
                $"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}";

            AaruConsole.WriteLine("Dump hardware information:");

            AaruConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING,
                                  VERSION_STRING, OS_STRING, START_STRING, END_STRING);

            AaruConsole.WriteLine(new string(separator));

            foreach (DumpHardwareType dump in imageFormat.DumpHardware)
            {
                foreach (ExtentType extent in dump.Extents)
                {
                    AaruConsole.WriteLine(format, dump.Manufacturer, dump.Model, dump.Serial, dump.Software.Name,
                                          dump.Software.Version, dump.Software.OperatingSystem, extent.Start,
                                          extent.End);
                }
            }

            AaruConsole.WriteLine();
        }
Exemple #17
0
        public bool Open(IFilter imageFilter)
        {
            Stream imageStream = imageFilter.GetDataForkStream();

            byte[] header = new byte[512];
            byte[] footer;

            imageStream.Seek(0, SeekOrigin.Begin);
            imageStream.Read(header, 0, 512);

            if (imageStream.Length % 2 == 0)
            {
                footer = new byte[512];
                imageStream.Seek(-512, SeekOrigin.End);
                imageStream.Read(footer, 0, 512);
            }
            else
            {
                footer = new byte[511];
                imageStream.Seek(-511, SeekOrigin.End);
                imageStream.Read(footer, 0, 511);
            }

            uint  headerChecksum = BigEndianBitConverter.ToUInt32(header, 0x40);
            uint  footerChecksum = BigEndianBitConverter.ToUInt32(footer, 0x40);
            ulong headerCookie   = BigEndianBitConverter.ToUInt64(header, 0);
            ulong footerCookie   = BigEndianBitConverter.ToUInt64(footer, 0);

            header[0x40] = 0;
            header[0x41] = 0;
            header[0x42] = 0;
            header[0x43] = 0;
            footer[0x40] = 0;
            footer[0x41] = 0;
            footer[0x42] = 0;
            footer[0x43] = 0;

            uint headerCalculatedChecksum = VhdChecksum(header);
            uint footerCalculatedChecksum = VhdChecksum(footer);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}",
                                       headerChecksum, headerCalculatedChecksum);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}",
                                       footerChecksum, footerCalculatedChecksum);

            byte[] usableHeader;
            uint   usableChecksum;

            if (headerCookie == IMAGE_COOKIE &&
                headerChecksum == headerCalculatedChecksum)
            {
                usableHeader   = header;
                usableChecksum = headerChecksum;
            }
            else if (footerCookie == IMAGE_COOKIE &&
                     footerChecksum == footerCalculatedChecksum)
            {
                usableHeader   = footer;
                usableChecksum = footerChecksum;
            }
            else
            {
                throw new
                      ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened.");
            }

            _thisFooter = new HardDiskFooter
            {
                Cookie             = BigEndianBitConverter.ToUInt64(usableHeader, 0x00),
                Features           = BigEndianBitConverter.ToUInt32(usableHeader, 0x08),
                Version            = BigEndianBitConverter.ToUInt32(usableHeader, 0x0C),
                Offset             = BigEndianBitConverter.ToUInt64(usableHeader, 0x10),
                Timestamp          = BigEndianBitConverter.ToUInt32(usableHeader, 0x18),
                CreatorApplication = BigEndianBitConverter.ToUInt32(usableHeader, 0x1C),
                CreatorVersion     = BigEndianBitConverter.ToUInt32(usableHeader, 0x20),
                CreatorHostOs      = BigEndianBitConverter.ToUInt32(usableHeader, 0x24),
                OriginalSize       = BigEndianBitConverter.ToUInt64(usableHeader, 0x28),
                CurrentSize        = BigEndianBitConverter.ToUInt64(usableHeader, 0x30),
                DiskGeometry       = BigEndianBitConverter.ToUInt32(usableHeader, 0x38),
                DiskType           = BigEndianBitConverter.ToUInt32(usableHeader, 0x3C),
                Checksum           = usableChecksum,
                UniqueId           = BigEndianBitConverter.ToGuid(usableHeader, 0x44),
                SavedState         = usableHeader[0x54],
                Reserved           = new byte[usableHeader.Length - 0x55]
            };

            Array.Copy(usableHeader, 0x55, _thisFooter.Reserved, 0, usableHeader.Length - 0x55);

            _thisDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            _thisDateTime = _thisDateTime.AddSeconds(_thisFooter.Timestamp);

            var sha1Ctx = new Sha1Context();

            sha1Ctx.Update(_thisFooter.Reserved);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.cookie = 0x{0:X8}", _thisFooter.Cookie);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.features = 0x{0:X8}", _thisFooter.Features);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.version = 0x{0:X8}", _thisFooter.Version);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.offset = {0}", _thisFooter.Offset);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.timestamp = 0x{0:X8} ({1})", _thisFooter.Timestamp,
                                       _thisDateTime);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorApplication = 0x{0:X8} (\"{1}\")",
                                       _thisFooter.CreatorApplication,
                                       Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(_thisFooter.
                                                                                               CreatorApplication)));

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorVersion = 0x{0:X8}",
                                       _thisFooter.CreatorVersion);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorHostOS = 0x{0:X8} (\"{1}\")",
                                       _thisFooter.CreatorHostOs,
                                       Encoding.ASCII.GetString(BigEndianBitConverter.
                                                                GetBytes(_thisFooter.CreatorHostOs)));

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.originalSize = {0}", _thisFooter.OriginalSize);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.currentSize = {0}", _thisFooter.CurrentSize);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.diskGeometry = 0x{0:X8} (C/H/S: {1}/{2}/{3})",
                                       _thisFooter.DiskGeometry, (_thisFooter.DiskGeometry & 0xFFFF0000) >> 16,
                                       (_thisFooter.DiskGeometry & 0xFF00) >> 8, _thisFooter.DiskGeometry & 0xFF);

            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.diskType = 0x{0:X8}", _thisFooter.DiskType);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.checksum = 0x{0:X8}", _thisFooter.Checksum);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.uniqueId = {0}", _thisFooter.UniqueId);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.savedState = 0x{0:X2}", _thisFooter.SavedState);
            AaruConsole.DebugWriteLine("VirtualPC plugin", "footer.reserved's SHA1 = 0x{0}", sha1Ctx.End());

            if (_thisFooter.Version == VERSION1)
            {
                _imageInfo.Version = "1.0";
            }
            else
            {
                throw new
                      ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {_thisFooter.DiskType} found. Please submit a bug with an example image.");
            }

            switch (_thisFooter.CreatorApplication)
            {
            case CREATOR_QEMU:
            {
                _imageInfo.Application = "QEMU";

                // QEMU always set same version
                _imageInfo.ApplicationVersion = "Unknown";

                break;
            }

            case CREATOR_VIRTUAL_BOX:
            {
                _imageInfo.ApplicationVersion =
                    $"{(_thisFooter.CreatorVersion & 0xFFFF0000) >> 16}.{_thisFooter.CreatorVersion & 0x0000FFFF:D2}";

                switch (_thisFooter.CreatorHostOs)
                {
                case CREATOR_MACINTOSH:
                case CREATOR_MACINTOSH_OLD:
                    _imageInfo.Application = "VirtualBox for Mac";

                    break;

                case CREATOR_WINDOWS:
                    // VirtualBox uses Windows creator for any other OS
                    _imageInfo.Application = "VirtualBox";

                    break;

                default:
                    _imageInfo.Application =
                        $"VirtualBox for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(_thisFooter.CreatorHostOs))}\"";

                    break;
                }

                break;
            }

            case CREATOR_VIRTUAL_SERVER:
            {
                _imageInfo.Application = "Microsoft Virtual Server";

                switch (_thisFooter.CreatorVersion)
                {
                case VERSION_VIRTUAL_SERVER2004:
                    _imageInfo.ApplicationVersion = "2004";

                    break;

                default:
                    _imageInfo.ApplicationVersion = $"Unknown version 0x{_thisFooter.CreatorVersion:X8}";

                    break;
                }

                break;
            }

            case CREATOR_VIRTUAL_PC:
            {
                switch (_thisFooter.CreatorHostOs)
                {
                case CREATOR_MACINTOSH:
                case CREATOR_MACINTOSH_OLD:
                    switch (_thisFooter.CreatorVersion)
                    {
                    case VERSION_VIRTUAL_PC_MAC:
                        _imageInfo.Application        = "Connectix Virtual PC";
                        _imageInfo.ApplicationVersion = "5, 6 or 7";

                        break;

                    default:
                        _imageInfo.ApplicationVersion =
                            $"Unknown version 0x{_thisFooter.CreatorVersion:X8}";

                        break;
                    }

                    break;

                case CREATOR_WINDOWS:
                    switch (_thisFooter.CreatorVersion)
                    {
                    case VERSION_VIRTUAL_PC_MAC:
                        _imageInfo.Application        = "Connectix Virtual PC";
                        _imageInfo.ApplicationVersion = "5, 6 or 7";

                        break;

                    case VERSION_VIRTUAL_PC2004:
                        _imageInfo.Application        = "Microsoft Virtual PC";
                        _imageInfo.ApplicationVersion = "2004";

                        break;

                    case VERSION_VIRTUAL_PC2007:
                        _imageInfo.Application        = "Microsoft Virtual PC";
                        _imageInfo.ApplicationVersion = "2007";

                        break;

                    default:
                        _imageInfo.ApplicationVersion =
                            $"Unknown version 0x{_thisFooter.CreatorVersion:X8}";

                        break;
                    }

                    break;

                default:
                    _imageInfo.Application =
                        $"Virtual PC for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(_thisFooter.CreatorHostOs))}\"";

                    _imageInfo.ApplicationVersion = $"Unknown version 0x{_thisFooter.CreatorVersion:X8}";

                    break;
                }

                break;
            }

            case CREATOR_DISCIMAGECHEF:
            {
                _imageInfo.Application = "DiscImageChef";

                _imageInfo.ApplicationVersion =
                    $"{(_thisFooter.CreatorVersion & 0xFF000000) >> 24}.{(_thisFooter.CreatorVersion & 0xFF0000) >> 16}.{(_thisFooter.CreatorVersion & 0xFF00) >> 8}.{_thisFooter.CreatorVersion & 0xFF}";
            }

            break;

            case CREATOR_AARU:
            {
                _imageInfo.Application = "Aaru";

                _imageInfo.ApplicationVersion =
                    $"{(_thisFooter.CreatorVersion & 0xFF000000) >> 24}.{(_thisFooter.CreatorVersion & 0xFF0000) >> 16}.{(_thisFooter.CreatorVersion & 0xFF00) >> 8}.{_thisFooter.CreatorVersion & 0xFF}";
            }

            break;

            default:
            {
                _imageInfo.Application =
                    $"Unknown application \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(_thisFooter.CreatorHostOs))}\"";

                _imageInfo.ApplicationVersion = $"Unknown version 0x{_thisFooter.CreatorVersion:X8}";

                break;
            }
            }

            _thisFilter           = imageFilter;
            _imageInfo.ImageSize  = _thisFooter.CurrentSize;
            _imageInfo.Sectors    = _thisFooter.CurrentSize / 512;
            _imageInfo.SectorSize = 512;

            _imageInfo.CreationTime         = imageFilter.GetCreationTime();
            _imageInfo.LastModificationTime = _thisDateTime;
            _imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());

            _imageInfo.Cylinders       = (_thisFooter.DiskGeometry & 0xFFFF0000) >> 16;
            _imageInfo.Heads           = (_thisFooter.DiskGeometry & 0xFF00) >> 8;
            _imageInfo.SectorsPerTrack = _thisFooter.DiskGeometry & 0xFF;

            if (_thisFooter.DiskType == TYPE_DYNAMIC ||
                _thisFooter.DiskType == TYPE_DIFFERENCING)
            {
                imageStream.Seek((long)_thisFooter.Offset, SeekOrigin.Begin);
                byte[] dynamicBytes = new byte[1024];
                imageStream.Read(dynamicBytes, 0, 1024);

                uint dynamicChecksum = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x24);

                dynamicBytes[0x24] = 0;
                dynamicBytes[0x25] = 0;
                dynamicBytes[0x26] = 0;
                dynamicBytes[0x27] = 0;

                uint dynamicChecksumCalculated = VhdChecksum(dynamicBytes);

                AaruConsole.DebugWriteLine("VirtualPC plugin",
                                           "Dynamic header checksum = 0x{0:X8}, calculated = 0x{1:X8}", dynamicChecksum,
                                           dynamicChecksumCalculated);

                if (dynamicChecksum != dynamicChecksumCalculated)
                {
                    throw new
                          ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened.");
                }

                _thisDynamic = new DynamicDiskHeader
                {
                    LocatorEntries = new ParentLocatorEntry[8],
                    Reserved2      = new byte[256]
                };

                for (int i = 0; i < 8; i++)
                {
                    _thisDynamic.LocatorEntries[i] = new ParentLocatorEntry();
                }

                _thisDynamic.Cookie          = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x00);
                _thisDynamic.DataOffset      = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x08);
                _thisDynamic.TableOffset     = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x10);
                _thisDynamic.HeaderVersion   = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x18);
                _thisDynamic.MaxTableEntries = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x1C);
                _thisDynamic.BlockSize       = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x20);
                _thisDynamic.Checksum        = dynamicChecksum;
                _thisDynamic.ParentId        = BigEndianBitConverter.ToGuid(dynamicBytes, 0x28);
                _thisDynamic.ParentTimestamp = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x38);
                _thisDynamic.Reserved        = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x3C);
                _thisDynamic.ParentName      = Encoding.BigEndianUnicode.GetString(dynamicBytes, 0x40, 512);

                for (int i = 0; i < 8; i++)
                {
                    _thisDynamic.LocatorEntries[i].PlatformCode =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x00 + (24 * i));

                    _thisDynamic.LocatorEntries[i].PlatformDataSpace =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x04 + (24 * i));

                    _thisDynamic.LocatorEntries[i].PlatformDataLength =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x08 + (24 * i));

                    _thisDynamic.LocatorEntries[i].Reserved =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x0C + (24 * i));

                    _thisDynamic.LocatorEntries[i].PlatformDataOffset =
                        BigEndianBitConverter.ToUInt64(dynamicBytes, 0x240 + 0x10 + (24 * i));
                }

                Array.Copy(dynamicBytes, 0x300, _thisDynamic.Reserved2, 0, 256);

                _parentDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                _parentDateTime = _parentDateTime.AddSeconds(_thisDynamic.ParentTimestamp);

                sha1Ctx = new Sha1Context();
                sha1Ctx.Update(_thisDynamic.Reserved2);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.cookie = 0x{0:X8}", _thisDynamic.Cookie);
                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.dataOffset = {0}", _thisDynamic.DataOffset);
                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.tableOffset = {0}", _thisDynamic.TableOffset);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.headerVersion = 0x{0:X8}",
                                           _thisDynamic.HeaderVersion);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.maxTableEntries = {0}",
                                           _thisDynamic.MaxTableEntries);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.blockSize = {0}", _thisDynamic.BlockSize);
                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.checksum = 0x{0:X8}", _thisDynamic.Checksum);
                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentID = {0}", _thisDynamic.ParentId);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentTimestamp = 0x{0:X8} ({1})",
                                           _thisDynamic.ParentTimestamp, _parentDateTime);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved = 0x{0:X8}", _thisDynamic.Reserved);

                for (int i = 0; i < 8; i++)
                {
                    AaruConsole.DebugWriteLine("VirtualPC plugin",
                                               "dynamic.locatorEntries[{0}].platformCode = 0x{1:X8} (\"{2}\")", i,
                                               _thisDynamic.LocatorEntries[i].PlatformCode,
                                               Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(_thisDynamic.
                                                                                                       LocatorEntries
                                                                                                       [i].
                                                                                                       PlatformCode)));

                    AaruConsole.DebugWriteLine("VirtualPC plugin",
                                               "dynamic.locatorEntries[{0}].platformDataSpace = {1}", i,
                                               _thisDynamic.LocatorEntries[i].PlatformDataSpace);

                    AaruConsole.DebugWriteLine("VirtualPC plugin",
                                               "dynamic.locatorEntries[{0}].platformDataLength = {1}", i,
                                               _thisDynamic.LocatorEntries[i].PlatformDataLength);

                    AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].reserved = 0x{1:X8}", i,
                                               _thisDynamic.LocatorEntries[i].Reserved);

                    AaruConsole.DebugWriteLine("VirtualPC plugin",
                                               "dynamic.locatorEntries[{0}].platformDataOffset = {1}", i,
                                               _thisDynamic.LocatorEntries[i].PlatformDataOffset);
                }

                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentName = \"{0}\"", _thisDynamic.ParentName);
                AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved2's SHA1 = 0x{0}", sha1Ctx.End());

                if (_thisDynamic.HeaderVersion != VERSION1)
                {
                    throw new
                          ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {_thisFooter.DiskType} found. Please submit a bug with an example image.");
                }

                DateTime startTime = DateTime.UtcNow;

                _blockAllocationTable = new uint[_thisDynamic.MaxTableEntries];

                // How many sectors uses the BAT
                int batSectorCount = (int)Math.Ceiling(((double)_thisDynamic.MaxTableEntries * 4) / 512);

                byte[] bat = new byte[_thisDynamic.MaxTableEntries * 4];
                imageStream.Seek((long)_thisDynamic.TableOffset, SeekOrigin.Begin);
                imageStream.Read(bat, 0, batSectorCount);

                ReadOnlySpan <byte> span = bat;

                _blockAllocationTable = MemoryMarshal.
                                        Cast <byte, uint>(span).Slice(0, (int)_thisDynamic.MaxTableEntries).ToArray();

                for (int i = 0; i < _blockAllocationTable.Length; i++)
                {
                    _blockAllocationTable[i] = Swapping.Swap(_blockAllocationTable[i]);
                }

                DateTime endTime = DateTime.UtcNow;

                AaruConsole.DebugWriteLine("VirtualPC plugin", "Filling the BAT took {0} seconds",
                                           (endTime - startTime).TotalSeconds);

                _bitmapSize = (uint)Math.Ceiling((double)_thisDynamic.BlockSize / 512

                                                 // 1 bit per sector on the bitmap
                                                 / 8

                                                 // and aligned to 512 byte boundary
                                                 / 512);

                AaruConsole.DebugWriteLine("VirtualPC plugin", "Bitmap is {0} sectors", _bitmapSize);
            }

            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;

            switch (_thisFooter.DiskType)
            {
            case TYPE_FIXED:
            case TYPE_DYNAMIC:
            {
                // Nothing to do here, really.
                return(true);
            }

            case TYPE_DIFFERENCING:
            {
                _locatorEntriesData = new byte[8][];

                for (int i = 0; i < 8; i++)
                {
                    if (_thisDynamic.LocatorEntries[i].PlatformCode != 0x00000000)
                    {
                        _locatorEntriesData[i] = new byte[_thisDynamic.LocatorEntries[i].PlatformDataLength];
                        imageStream.Seek((long)_thisDynamic.LocatorEntries[i].PlatformDataOffset, SeekOrigin.Begin);

                        imageStream.Read(_locatorEntriesData[i], 0,
                                         (int)_thisDynamic.LocatorEntries[i].PlatformDataLength);

                        switch (_thisDynamic.LocatorEntries[i].PlatformCode)
                        {
                        case PLATFORM_CODE_WINDOWS_ABSOLUTE:
                        case PLATFORM_CODE_WINDOWS_RELATIVE:
                            AaruConsole.DebugWriteLine("VirtualPC plugin",
                                                       "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                       Encoding.ASCII.GetString(_locatorEntriesData[i]));

                            break;

                        case PLATFORM_CODE_WINDOWS_ABSOLUTE_U:
                        case PLATFORM_CODE_WINDOWS_RELATIVE_U:
                            AaruConsole.DebugWriteLine("VirtualPC plugin",
                                                       "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                       Encoding.BigEndianUnicode.
                                                       GetString(_locatorEntriesData[i]));

                            break;

                        case PLATFORM_CODE_MACINTOSH_URI:
                            AaruConsole.DebugWriteLine("VirtualPC plugin",
                                                       "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                       Encoding.UTF8.GetString(_locatorEntriesData[i]));

                            break;

                        default:
                            AaruConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] =", i);
                            PrintHex.PrintHexArray(_locatorEntriesData[i], 64);

                            break;
                        }
                    }
                }

                int    currentLocator = 0;
                bool   locatorFound   = false;
                string parentPath     = null;

                while (!locatorFound &&
                       currentLocator < 8)
                {
                    switch (_thisDynamic.LocatorEntries[currentLocator].PlatformCode)
                    {
                    case PLATFORM_CODE_WINDOWS_ABSOLUTE:
                    case PLATFORM_CODE_WINDOWS_RELATIVE:
                        parentPath = Encoding.ASCII.GetString(_locatorEntriesData[currentLocator]);

                        break;

                    case PLATFORM_CODE_WINDOWS_ABSOLUTE_U:
                    case PLATFORM_CODE_WINDOWS_RELATIVE_U:
                        parentPath = Encoding.BigEndianUnicode.GetString(_locatorEntriesData[currentLocator]);

                        break;

                    case PLATFORM_CODE_MACINTOSH_URI:
                        parentPath =
                            Uri.UnescapeDataString(Encoding.UTF8.GetString(_locatorEntriesData
                                                                           [currentLocator]));

                        if (parentPath.StartsWith("file://localhost", StringComparison.InvariantCulture))
                        {
                            parentPath = parentPath.Remove(0, 16);
                        }
                        else
                        {
                            AaruConsole.DebugWriteLine("VirtualPC plugin",
                                                       "Unsupported protocol classified found in URI parent path: \"{0}\"",
                                                       parentPath);

                            parentPath = null;
                        }

                        break;
                    }

                    if (parentPath != null)
                    {
                        AaruConsole.DebugWriteLine("VirtualPC plugin", "Possible parent path: \"{0}\"", parentPath);

                        IFilter parentFilter =
                            new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));

                        if (parentFilter != null)
                        {
                            locatorFound = true;
                        }

                        if (!locatorFound)
                        {
                            parentPath = null;
                        }
                    }

                    currentLocator++;
                }

                if (!locatorFound)
                {
                    throw new
                          FileNotFoundException("(VirtualPC plugin): Cannot find parent file for differencing disk image");
                }

                {
                    _parentImage = new Vhd();

                    IFilter parentFilter =
                        new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));

                    if (parentFilter == null)
                    {
                        throw new ImageNotSupportedException("(VirtualPC plugin): Cannot find parent image filter");
                    }

                    /*                            PluginBase plugins = new PluginBase();
                     *                          plugins.RegisterAllPlugins();
                     *                          if (!plugins.ImagePluginsList.TryGetValue(Name.ToLower(), out parentImage))
                     *                              throw new SystemException("(VirtualPC plugin): Unable to open myself");*/

                    if (!_parentImage.Identify(parentFilter))
                    {
                        throw new
                              ImageNotSupportedException("(VirtualPC plugin): Parent image is not a Virtual PC disk image");
                    }

                    if (!_parentImage.Open(parentFilter))
                    {
                        throw new ImageNotSupportedException("(VirtualPC plugin): Cannot open parent disk image");
                    }

                    // While specification says that parent and child disk images should contain UUID relationship
                    // in reality it seems that old differencing disk images stored a parent UUID that, nonetheless
                    // the parent never stored itself. So the only real way to know that images are related is
                    // because the parent IS found and SAME SIZE. Ugly...
                    // More funny even, tested parent images show an empty host OS, and child images a correct one.
                    if (_parentImage.Info.Sectors != _imageInfo.Sectors)
                    {
                        throw new
                              ImageNotSupportedException("(VirtualPC plugin): Parent image is of different size");
                    }
                }

                return(true);
            }

            case TYPE_DEPRECATED1:
            case TYPE_DEPRECATED2:
            case TYPE_DEPRECATED3:
            {
                throw new
                      ImageNotSupportedException("(VirtualPC plugin): Deprecated image type found. Please submit a bug with an example image.");
            }

            default:
            {
                throw new
                      ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {_thisFooter.DiskType} found. Please submit a bug with an example image.");
            }
            }
        }
Exemple #18
0
        public static void Scsi(string devPath, Device dev)
        {
            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Send a SCSI command to the device:");
                AaruConsole.WriteLine("1.- Send an Adaptec vendor command to the device.");
                AaruConsole.WriteLine("2.- Send an Archive vendor command to the device.");
                AaruConsole.WriteLine("3.- Send a Certance vendor command to the device.");
                AaruConsole.WriteLine("4.- Send a Fujitsu vendor command to the device.");
                AaruConsole.WriteLine("5.- Send an HL-DT-ST vendor command to the device.");
                AaruConsole.WriteLine("6.- Send a Hewlett-Packard vendor command to the device.");
                AaruConsole.WriteLine("7.- Send a Kreon vendor command to the device.");
                AaruConsole.WriteLine("8.- Send a SCSI MultiMedia Command to the device.");
                AaruConsole.WriteLine("9.- Send a NEC vendor command to the device.");
                AaruConsole.WriteLine("10.- Send a Pioneer vendor command to the device.");
                AaruConsole.WriteLine("11.- Send a Plasmon vendor command to the device.");
                AaruConsole.WriteLine("12.- Send a Plextor vendor command to the device.");
                AaruConsole.WriteLine("13.- Send a SCSI Block Command to the device.");
                AaruConsole.WriteLine("14.- Send a SCSI Media Changer command to the device.");
                AaruConsole.WriteLine("15.- Send a SCSI Primary Command to the device.");
                AaruConsole.WriteLine("16.- Send a SCSI Streaming Command to the device.");
                AaruConsole.WriteLine("17.- Send a SyQuest vendor command to the device.");
                AaruConsole.WriteLine("0.- Return to command class menu.");
                AaruConsole.Write("Choose: ");

                string strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out int item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to command class menu...");

                    return;

                case 1:
                    Adaptec.Menu(devPath, dev);

                    continue;

                case 2:
                    ArchiveCorp.Menu(devPath, dev);

                    continue;

                case 3:
                    Certance.Menu(devPath, dev);

                    continue;

                case 4:
                    Fujitsu.Menu(devPath, dev);

                    continue;

                case 5:
                    HlDtSt.Menu(devPath, dev);

                    continue;

                case 6:
                    Hp.Menu(devPath, dev);

                    continue;

                case 7:
                    Kreon.Menu(devPath, dev);

                    continue;

                case 8:
                    Mmc.Menu(devPath, dev);

                    continue;

                case 9:
                    Nec.Menu(devPath, dev);

                    continue;

                case 10:
                    Pioneer.Menu(devPath, dev);

                    continue;

                case 11:
                    Plasmon.Menu(devPath, dev);

                    continue;

                case 12:
                    Plextor.Menu(devPath, dev);

                    continue;

                case 13:
                    Sbc.Menu(devPath, dev);

                    continue;

                case 14:
                    Smc.Menu(devPath, dev);

                    continue;

                case 15:
                    Spc.Menu(devPath, dev);

                    continue;

                case 16:
                    Ssc.Menu(devPath, dev);

                    continue;

                case 17:
                    SyQuest.Menu(devPath, dev);

                    continue;

                default:
                    AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }
            }
        }
Exemple #19
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            if (stream.Length < 512)
            {
                return(false);
            }

            byte[] qHdrB = new byte[68];
            stream.Read(qHdrB, 0, 68);
            _qHdr = Marshal.SpanToStructureLittleEndian <QedHeader>(qHdrB);

            AaruConsole.DebugWriteLine("QED plugin", "qHdr.magic = 0x{0:X8}", _qHdr.magic);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.cluster_size = {0}", _qHdr.cluster_size);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.table_size = {0}", _qHdr.table_size);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.header_size = {0}", _qHdr.header_size);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.features = {0}", _qHdr.features);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.compat_features = {0}", _qHdr.compat_features);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.autoclear_features = {0}", _qHdr.autoclear_features);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.l1_table_offset = {0}", _qHdr.l1_table_offset);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.image_size = {0}", _qHdr.image_size);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.backing_file_offset = {0}", _qHdr.backing_file_offset);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.backing_file_size = {0}", _qHdr.backing_file_size);

            if (_qHdr.image_size <= 1)
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.image_size), "Image size is too small");
            }

            if (!IsPowerOfTwo(_qHdr.cluster_size))
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.cluster_size), "Cluster size must be a power of 2");
            }

            if (_qHdr.cluster_size < 4096 ||
                _qHdr.cluster_size > 67108864)
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.cluster_size),
                                                      "Cluster size must be between 4 Kbytes and 64 Mbytes");
            }

            if (!IsPowerOfTwo(_qHdr.table_size))
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.table_size), "Table size must be a power of 2");
            }

            if (_qHdr.table_size < 1 ||
                _qHdr.table_size > 16)
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.table_size),
                                                      "Table size must be between 1 and 16 clusters");
            }

            if ((_qHdr.features & QED_FEATURE_MASK) > 0)
            {
                throw new ArgumentOutOfRangeException(nameof(_qHdr.features),
                                                      $"Image uses unknown incompatible features {_qHdr.features & QED_FEATURE_MASK:X}");
            }

            if ((_qHdr.features & QED_FEATURE_BACKING_FILE) == QED_FEATURE_BACKING_FILE)
            {
                throw new NotImplementedException("Differencing images not yet supported");
            }

            _clusterSectors = _qHdr.cluster_size / 512;
            _tableSize      = (_qHdr.cluster_size * _qHdr.table_size) / 8;

            AaruConsole.DebugWriteLine("QED plugin", "qHdr.clusterSectors = {0}", _clusterSectors);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.tableSize = {0}", _tableSize);

            byte[] l1TableB = new byte[_tableSize * 8];
            stream.Seek((long)_qHdr.l1_table_offset, SeekOrigin.Begin);
            stream.Read(l1TableB, 0, (int)_tableSize * 8);
            AaruConsole.DebugWriteLine("QED plugin", "Reading L1 table");
            _l1Table = MemoryMarshal.Cast <byte, ulong>(l1TableB).ToArray();

            _l1Mask = 0;
            int c = 0;

            _clusterBits = Ctz32(_qHdr.cluster_size);
            _l2Mask      = (_tableSize - 1) << _clusterBits;
            _l1Shift     = _clusterBits + Ctz32(_tableSize);

            for (int i = 0; i < 64; i++)
            {
                _l1Mask <<= 1;

                if (c >= 64 - _l1Shift)
                {
                    continue;
                }

                _l1Mask += 1;
                c++;
            }

            _sectorMask = 0;

            for (int i = 0; i < _clusterBits; i++)
            {
                _sectorMask = (_sectorMask << 1) + 1;
            }

            AaruConsole.DebugWriteLine("QED plugin", "qHdr.clusterBits = {0}", _clusterBits);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.l1Mask = {0:X}", _l1Mask);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.l1Shift = {0}", _l1Shift);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.l2Mask = {0:X}", _l2Mask);
            AaruConsole.DebugWriteLine("QED plugin", "qHdr.sectorMask = {0:X}", _sectorMask);

            _maxL2TableCache = MAX_CACHE_SIZE / _tableSize;
            _maxClusterCache = MAX_CACHE_SIZE / _qHdr.cluster_size;

            _imageStream = stream;

            _sectorCache  = new Dictionary <ulong, byte[]>();
            _l2TableCache = new Dictionary <ulong, ulong[]>();
            _clusterCache = new Dictionary <ulong, byte[]>();

            _imageInfo.CreationTime         = imageFilter.GetCreationTime();
            _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
            _imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
            _imageInfo.Sectors      = _qHdr.image_size / 512;
            _imageInfo.SectorSize   = 512;
            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            _imageInfo.MediaType    = MediaType.GENERIC_HDD;
            _imageInfo.ImageSize    = _qHdr.image_size;

            _imageInfo.Cylinders       = (uint)(_imageInfo.Sectors / 16 / 63);
            _imageInfo.Heads           = 16;
            _imageInfo.SectorsPerTrack = 63;

            return(true);
        }
        public static int Invoke(bool debug, bool verbose, uint blockSize, string encodingName, string imagePath,
                                 bool tape)
        {
            MainClass.PrintCopyright();

            if (debug)
            {
                AaruConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
            }

            if (verbose)
            {
                AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
            }

            Statistics.AddCommand("create-sidecar");

            AaruConsole.DebugWriteLine("Create sidecar command", "--block-size={0}", blockSize);
            AaruConsole.DebugWriteLine("Create sidecar command", "--debug={0}", debug);
            AaruConsole.DebugWriteLine("Create sidecar command", "--encoding={0}", encodingName);
            AaruConsole.DebugWriteLine("Create sidecar command", "--input={0}", imagePath);
            AaruConsole.DebugWriteLine("Create sidecar command", "--tape={0}", tape);
            AaruConsole.DebugWriteLine("Create sidecar command", "--verbose={0}", verbose);

            Encoding encodingClass = null;

            if (encodingName != null)
            {
                try
                {
                    encodingClass = Claunia.Encoding.Encoding.GetEncoding(encodingName);

                    if (verbose)
                    {
                        AaruConsole.VerboseWriteLine("Using encoding for {0}.", encodingClass.EncodingName);
                    }
                }
                catch (ArgumentException)
                {
                    AaruConsole.ErrorWriteLine("Specified encoding is not supported.");

                    return((int)ErrorNumber.EncodingUnknown);
                }
            }

            if (File.Exists(imagePath))
            {
                if (tape)
                {
                    AaruConsole.ErrorWriteLine("You cannot use --tape option when input is a file.");

                    return((int)ErrorNumber.ExpectedDirectory);
                }

                var     filtersList = new FiltersList();
                IFilter inputFilter = filtersList.GetFilter(imagePath);

                if (inputFilter == null)
                {
                    AaruConsole.ErrorWriteLine("Cannot open specified file.");

                    return((int)ErrorNumber.CannotOpenFile);
                }

                try
                {
                    IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                    if (imageFormat == null)
                    {
                        AaruConsole.WriteLine("Image format not identified, not proceeding with analysis.");

                        return((int)ErrorNumber.UnrecognizedFormat);
                    }

                    if (verbose)
                    {
                        AaruConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
                                                     imageFormat.Id);
                    }
                    else
                    {
                        AaruConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
                    }

                    try
                    {
                        if (!imageFormat.Open(inputFilter))
                        {
                            AaruConsole.WriteLine("Unable to open image format");
                            AaruConsole.WriteLine("No error given");

                            return((int)ErrorNumber.CannotOpenFormat);
                        }

                        AaruConsole.DebugWriteLine("Analyze command", "Correctly opened image file.");
                    }
                    catch (Exception ex)
                    {
                        AaruConsole.ErrorWriteLine("Unable to open image format");
                        AaruConsole.ErrorWriteLine("Error: {0}", ex.Message);

                        return((int)ErrorNumber.CannotOpenFormat);
                    }

                    Statistics.AddMediaFormat(imageFormat.Format);
                    Statistics.AddFilter(inputFilter.Name);

                    var sidecarClass = new Sidecar(imageFormat, imagePath, inputFilter.Id, encodingClass);
                    sidecarClass.InitProgressEvent    += Progress.InitProgress;
                    sidecarClass.UpdateProgressEvent  += Progress.UpdateProgress;
                    sidecarClass.EndProgressEvent     += Progress.EndProgress;
                    sidecarClass.InitProgressEvent2   += Progress.InitProgress2;
                    sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
                    sidecarClass.EndProgressEvent2    += Progress.EndProgress2;
                    sidecarClass.UpdateStatusEvent    += Progress.UpdateStatus;

                    System.Console.CancelKeyPress += (sender, e) =>
                    {
                        e.Cancel = true;
                        sidecarClass.Abort();
                    };

                    CICMMetadataType sidecar = sidecarClass.Create();

                    AaruConsole.WriteLine("Writing metadata sidecar");

                    var xmlFs =
                        new
                        FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"),
                                   FileMode.CreateNew);

                    var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
                    xmlSer.Serialize(xmlFs, sidecar);
                    xmlFs.Close();
                }
                catch (Exception ex)
                {
                    AaruConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                    AaruConsole.DebugWriteLine("Analyze command", ex.StackTrace);

                    return((int)ErrorNumber.UnexpectedException);
                }
            }
            else if (Directory.Exists(imagePath))
            {
                if (!tape)
                {
                    AaruConsole.ErrorWriteLine("Cannot create a sidecar from a directory.");

                    return((int)ErrorNumber.ExpectedFile);
                }

                string[]      contents = Directory.GetFiles(imagePath, "*", SearchOption.TopDirectoryOnly);
                List <string> files    = contents.Where(file => new FileInfo(file).Length % blockSize == 0).ToList();

                files.Sort(StringComparer.CurrentCultureIgnoreCase);

                var sidecarClass = new Sidecar();
                sidecarClass.InitProgressEvent    += Progress.InitProgress;
                sidecarClass.UpdateProgressEvent  += Progress.UpdateProgress;
                sidecarClass.EndProgressEvent     += Progress.EndProgress;
                sidecarClass.InitProgressEvent2   += Progress.InitProgress2;
                sidecarClass.UpdateProgressEvent2 += Progress.UpdateProgress2;
                sidecarClass.EndProgressEvent2    += Progress.EndProgress2;
                sidecarClass.UpdateStatusEvent    += Progress.UpdateStatus;
                CICMMetadataType sidecar = sidecarClass.BlockTape(Path.GetFileName(imagePath), files, blockSize);

                AaruConsole.WriteLine("Writing metadata sidecar");

                var xmlFs =
                    new
                    FileStream(Path.Combine(Path.GetDirectoryName(imagePath) ?? throw new InvalidOperationException(), Path.GetFileNameWithoutExtension(imagePath) + ".cicm.xml"),
                               FileMode.CreateNew);

                var xmlSer = new XmlSerializer(typeof(CICMMetadataType));
                xmlSer.Serialize(xmlFs, sidecar);
                xmlFs.Close();
            }
            else
            {
                AaruConsole.ErrorWriteLine("The specified input file cannot be found.");
            }

            return((int)ErrorNumber.NoError);
        }
Exemple #21
0
        internal static void Menu(string devPath, Device dev)
        {
            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Send a CHS ATA command to the device:");
                AaruConsole.WriteLine("1.- Send IDENTIFY DEVICE command.");
                AaruConsole.WriteLine("2.- Send READ DMA command.");
                AaruConsole.WriteLine("3.- Send READ DMA WITH RETRIES command.");
                AaruConsole.WriteLine("4.- Send READ LONG command.");
                AaruConsole.WriteLine("5.- Send READ LONG WITH RETRIES command.");
                AaruConsole.WriteLine("6.- Send READ MULTIPLE command.");
                AaruConsole.WriteLine("7.- Send READ SECTORS command.");
                AaruConsole.WriteLine("8.- Send READ SECTORS WITH RETRIES command.");
                AaruConsole.WriteLine("9.- Send SEEK command.");
                AaruConsole.WriteLine("10.- Send SET FEATURES command.");
                AaruConsole.WriteLine("0.- Return to ATA commands menu.");
                AaruConsole.Write("Choose: ");

                string strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out int item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to ATA commands menu...");

                    return;

                case 1:
                    Identify(devPath, dev);

                    continue;

                case 2:
                    ReadDma(devPath, dev, false);

                    continue;

                case 3:
                    ReadDma(devPath, dev, true);

                    continue;

                case 4:
                    ReadLong(devPath, dev, false);

                    continue;

                case 5:
                    ReadLong(devPath, dev, true);

                    continue;

                case 6:
                    ReadMultiple(devPath, dev);

                    continue;

                case 7:
                    ReadSectors(devPath, dev, false);

                    continue;

                case 8:
                    ReadSectors(devPath, dev, true);

                    continue;

                case 9:
                    Seek(devPath, dev);

                    continue;

                case 10:
                    SetFeatures(devPath, dev);

                    continue;

                default:
                    AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }
            }
        }
Exemple #22
0
        static void ExecuteOfflineImmediate(string devPath, Device dev)
        {
            byte   subcommand = 0;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for EXECUTE OFF-LINE IMMEDIATE command:");
                AaruConsole.WriteLine("Subcommand: {0}", subcommand);
                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to S.M.A.R.T. commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to S.M.A.R.T. commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("Subcommand?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out subcommand))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        subcommand = 0;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();

            bool sense = dev.SmartExecuteOffLineImmediate(out AtaErrorRegistersLba28 errorRegisters, subcommand,
                                                          dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending EXECUTE OFF-LINE IMMEDIATE to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("EXECUTE OFF-LINE IMMEDIATE status registers:");
            AaruConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters));
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Send command again.");
            AaruConsole.WriteLine("2.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to Media Card Pass Through commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to S.M.A.R.T. commands menu...");

                return;

            case 1: goto start;

            case 2: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #23
0
        static void Seek(string devPath, Device dev)
        {
            ushort cylinder = 0;
            byte   head     = 0;
            byte   sector   = 1;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for SEEK command:");
                AaruConsole.WriteLine("Cylinder: {0}", cylinder);
                AaruConsole.WriteLine("Head: {0}", head);
                AaruConsole.WriteLine("Sector: {0}", sector);
                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to CHS ATA commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to CHS ATA commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("What cylinder?: ");
                    strDev = System.Console.ReadLine();

                    if (!ushort.TryParse(strDev, out cylinder))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        cylinder = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    AaruConsole.Write("What head?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out head))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        head = 0;
                        System.Console.ReadKey();

                        continue;
                    }

                    if (head > 15)
                    {
                        AaruConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15...");
                        head = 15;
                    }

                    AaruConsole.Write("What sector?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out sector))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        sector = 0;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();

            bool sense = dev.Seek(out AtaErrorRegistersChs errorRegisters, cylinder, head, sector, dev.Timeout,
                                  out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending SEEK to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Decode error registers.");
            AaruConsole.WriteLine("2.- Send command again.");
            AaruConsole.WriteLine("3.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to CHS ATA commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to CHS ATA commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("SEEK status registers:");
                AaruConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters));
                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2: goto start;

            case 3: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #24
0
        internal static void Menu(string devPath, Device dev)
        {
            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Send a S.M.A.R.T. command to the device:");
                AaruConsole.WriteLine("1.- Send DISABLE ATTRIBUTE AUTOSAVE command.");
                AaruConsole.WriteLine("2.- Send DISABLE OPERATIONS command.");
                AaruConsole.WriteLine("3.- Send ENABLE ATTRIBUTE AUTOSAVE command.");
                AaruConsole.WriteLine("4.- Send ENABLE OPERATIONS command.");
                AaruConsole.WriteLine("5.- Send EXECUTE OFF-LINE IMMEDIATE command.");
                AaruConsole.WriteLine("6.- Send READ DATA command.");
                AaruConsole.WriteLine("7.- Send READ LOG command.");
                AaruConsole.WriteLine("8.- Send RETURN STATUS command.");
                AaruConsole.WriteLine("0.- Return to ATA commands menu.");
                AaruConsole.Write("Choose: ");

                string strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out int item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to ATA commands menu...");

                    return;

                case 1:
                    DisableAttributeAutosave(devPath, dev);

                    continue;

                case 2:
                    DisableOperations(devPath, dev);

                    continue;

                case 3:
                    EnableAttributeAutosave(devPath, dev);

                    continue;

                case 4:
                    EnableOperations(devPath, dev);

                    continue;

                case 5:
                    ExecuteOfflineImmediate(devPath, dev);

                    continue;

                case 6:
                    ReadData(devPath, dev);

                    continue;

                case 7:
                    ReadLog(devPath, dev);

                    continue;

                case 8:
                    ReturnStatus(devPath, dev);

                    continue;

                default:
                    AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }
            }
        }
Exemple #25
0
        bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError,
                            out bool blankCheck)
        {
            bool sense;

            byte[] senseBuf;
            buffer         = null;
            duration       = 0;
            recoveredError = false;
            blankCheck     = false;

            if (CanReadRaw)
            {
                if (_readLong16)
                {
                    sense = _dev.ReadLong16(out buffer, out senseBuf, false, block, LongBlockSize, _timeout,
                                            out duration);
                }
                else if (_readLong10)
                {
                    sense = _dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)LongBlockSize,
                                            _timeout, out duration);
                }
                else if (_syqReadLong10)
                {
                    sense = _dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout,
                                                   out duration);
                }
                else if (_syqReadLong6)
                {
                    sense = _dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout,
                                                  out duration);
                }
                else if (_hldtstReadRaw)
                {
                    sense = _dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout,
                                                  out duration);
                }
                else if (_plextorReadRaw)
                {
                    sense = _dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout,
                                                   out duration);
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                if (_read6)
                {
                    sense = _dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, _timeout,
                                       out duration);
                }
                else if (_read10)
                {
                    sense = _dev.Read10(out buffer, out senseBuf, 0, false, false, false, false, (uint)block,
                                        LogicalBlockSize, 0, (ushort)count, _timeout, out duration);
                }
                else if (_read12)
                {
                    sense = _dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block,
                                        LogicalBlockSize, 0, count, false, _timeout, out duration);
                }
                else if (_read16)
                {
                    sense = _dev.Read16(out buffer, out senseBuf, 0, false, false, false, block, LogicalBlockSize, 0,
                                        count, false, _timeout, out duration);
                }
                else
                {
                    return(true);
                }
            }

            if (sense || _dev.Error)
            {
                _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, senseBuf);
            }

            if (!sense &&
                !_dev.Error)
            {
                return(false);
            }

            recoveredError = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.RecoveredError ||
                             Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.RecoveredError;

            blankCheck = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.BlankCheck ||
                         Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.BlankCheck;

            AaruConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));

            return(sense);
        }
Exemple #26
0
        static void ReadLog(string devPath, Device dev)
        {
            byte   address = 0;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for READ LOG command:");
                AaruConsole.WriteLine("Log address: {0}", address);
                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to S.M.A.R.T. commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to S.M.A.R.T. commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("Log address?: ");
                    strDev = System.Console.ReadLine();

                    if (!byte.TryParse(strDev, out address))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        address = 0;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();

            bool sense = dev.SmartReadLog(out byte[] buffer, out AtaErrorRegistersLba28 errorRegisters, address,
                                          dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending READ LOG to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer));
            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Print buffer.");
            AaruConsole.WriteLine("2.- Decode error registers.");
            AaruConsole.WriteLine("3.- Send command again.");
            AaruConsole.WriteLine("4.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to S.M.A.R.T. commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to S.M.A.R.T. commands menu...");

                return;

            case 1:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ LOG response:");

                if (buffer != null)
                {
                    PrintHex.PrintHexArray(buffer, 64);
                }

                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 2:
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("READ LOG status registers:");
                AaruConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters));
                AaruConsole.WriteLine("Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);

                goto menu;

            case 3: goto start;

            case 4: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #27
0
        internal static void Menu(string devPath, Device dev)
        {
            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Send a MultiMediaCard command to the device:");
                AaruConsole.WriteLine("1.- Send READ_MULTIPLE_BLOCK command.");
                AaruConsole.WriteLine("2.- Send READ_SINGLE_BLOCK command.");
                AaruConsole.WriteLine("3.- Send SEND_CID command.");
                AaruConsole.WriteLine("4.- Send SEND_CSD command.");
                AaruConsole.WriteLine("5.- Send SEND_EXT_CSD command.");
                AaruConsole.WriteLine("6.- Send SEND_OP_COND command.");
                AaruConsole.WriteLine("7.- Send SEND_STATUS command.");
                AaruConsole.WriteLine("8.- Send SET_BLOCKLEN command.");
                AaruConsole.WriteLine("0.- Return to SecureDigital/MultiMediaCard commands menu.");
                AaruConsole.Write("Choose: ");

                string strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out int item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to SecureDigital/MultiMediaCard commands menu...");

                    return;

                case 1:
                    Read(devPath, dev, true);

                    continue;

                case 2:
                    Read(devPath, dev, false);

                    continue;

                case 3:
                    SendCid(devPath, dev);

                    continue;

                case 4:
                    SendCsd(devPath, dev);

                    continue;

                case 5:
                    SendExtendedCsd(devPath, dev);

                    continue;

                case 6:
                    SendOpCond(devPath, dev);

                    continue;

                case 7:
                    Status(devPath, dev);

                    continue;

                case 8:
                    SetBlockLength(devPath, dev);

                    continue;

                default:
                    AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }
            }
        }
Exemple #28
0
        public static void Main()
        {
            AaruConsole.WriteLineEvent        += System.Console.WriteLine;
            AaruConsole.WriteEvent            += System.Console.Write;
            AaruConsole.ErrorWriteLineEvent   += System.Console.Error.WriteLine;
            AaruConsole.DebugWriteLineEvent   += System.Console.Error.WriteLine;
            AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;

            DeviceInfo[] devices = Aaru.Devices.Device.ListDevices();

            if (devices == null ||
                devices.Length == 0)
            {
                AaruConsole.WriteLine("No known devices attached.");

                return;
            }

            devices = devices.OrderBy(d => d.Path).ToArray();

            while (true)
            {
                System.Console.Clear();

                AaruConsole.WriteLine("DiscImageChef device handling tests");

                AaruConsole.WriteLine("{6,-8}|{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", "Path", "Vendor",
                                      "Model", "Serial", "Bus", "Supported?", "Number");

                AaruConsole.WriteLine("{6,-8}|{0,-22}+{1,-16}+{2,-24}+{3,-24}+{4,-10}+{5,-10}",
                                      "----------------------", "----------------", "------------------------",
                                      "------------------------", "----------", "----------", "--------");

                for (int i = 0; i < devices.Length; i++)
                {
                    AaruConsole.WriteLine("{6,-8}|{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", devices[i].Path,
                                          devices[i].Vendor, devices[i].Model, devices[i].Serial, devices[i].Bus,
                                          devices[i].Supported, i + 1);
                }

                AaruConsole.Write("Please choose which drive to test (0 to exit): ");
                string strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out int item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                if (item == 0)
                {
                    AaruConsole.WriteLine("Exiting...");

                    return;
                }

                if (item > devices.Length)
                {
                    AaruConsole.WriteLine("No such device. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                Device(devices[item - 1].Path);
            }
        }
Exemple #29
0
        static void SetBlockLength(string devPath, Device dev)
        {
            uint   blockSize = 512;
            string strDev;
            int    item;

parameters:

            while (true)
            {
                System.Console.Clear();
                AaruConsole.WriteLine("Device: {0}", devPath);
                AaruConsole.WriteLine("Parameters for SET_BLOCKLEN command:");
                AaruConsole.WriteLine("Set block length to: {0} bytes", blockSize);
                AaruConsole.WriteLine();
                AaruConsole.WriteLine("Choose what to do:");
                AaruConsole.WriteLine("1.- Change parameters.");
                AaruConsole.WriteLine("2.- Send command with these parameters.");
                AaruConsole.WriteLine("0.- Return to MultiMediaCard commands menu.");

                strDev = System.Console.ReadLine();

                if (!int.TryParse(strDev, out item))
                {
                    AaruConsole.WriteLine("Not a number. Press any key to continue...");
                    System.Console.ReadKey();

                    continue;
                }

                switch (item)
                {
                case 0:
                    AaruConsole.WriteLine("Returning to MultiMediaCard commands menu...");

                    return;

                case 1:
                    AaruConsole.Write("Set block length to?");
                    strDev = System.Console.ReadLine();

                    if (!uint.TryParse(strDev, out blockSize))
                    {
                        AaruConsole.WriteLine("Not a number. Press any key to continue...");
                        blockSize = 512;
                        System.Console.ReadKey();
                    }

                    break;

                case 2: goto start;
                }
            }

start:
            System.Console.Clear();
            bool sense = dev.SetBlockLength(blockSize, out uint[] response, dev.Timeout, out double duration);

menu:
            AaruConsole.WriteLine("Device: {0}", devPath);
            AaruConsole.WriteLine("Sending SET_BLOCKLEN to the device:");
            AaruConsole.WriteLine("Command took {0} ms.", duration);
            AaruConsole.WriteLine("Sense is {0}.", sense);
            AaruConsole.WriteLine("Response has {0} elements.", response?.Length.ToString() ?? "null");
            AaruConsole.WriteLine("SET_BLOCKLEN response:");

            if (response != null)
            {
                foreach (uint res in response)
                {
                    AaruConsole.Write("0x{0:x8} ", res);
                }

                AaruConsole.WriteLine();
            }

            AaruConsole.WriteLine();
            AaruConsole.WriteLine("Choose what to do:");
            AaruConsole.WriteLine("1.- Send command again.");
            AaruConsole.WriteLine("2.- Change parameters.");
            AaruConsole.WriteLine("0.- Return to MultiMediaCard commands menu.");
            AaruConsole.Write("Choose: ");

            strDev = System.Console.ReadLine();

            if (!int.TryParse(strDev, out item))
            {
                AaruConsole.WriteLine("Not a number. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }

            switch (item)
            {
            case 0:
                AaruConsole.WriteLine("Returning to MultiMediaCard commands menu...");

                return;

            case 1: goto start;

            case 2: goto parameters;

            default:
                AaruConsole.WriteLine("Incorrect option. Press any key to continue...");
                System.Console.ReadKey();
                System.Console.Clear();

                goto menu;
            }
        }
Exemple #30
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            var  type = (DiskType)stream.ReadByte();
            byte tracks;

            switch (type)
            {
            case DiskType.MD1DD8:
            case DiskType.MD1DD:
            case DiskType.MD2DD8:
            case DiskType.MD2DD:
                tracks = 80;

                break;

            case DiskType.MF2DD:
            case DiskType.MD2HD:
            case DiskType.MF2HD:
                tracks = 160;

                break;

            default: throw new ImageNotSupportedException($"Incorrect disk type {(byte)type}");
            }

            byte[] trackBytes = new byte[tracks];
            stream.Read(trackBytes, 0, tracks);

            var cmpr = (Compression)stream.ReadByte();

            if (cmpr != Compression.None)
            {
                throw new FeatureSupportedButNotImplementedImageException("Compressed images are not supported.");
            }

            int tracksize = 0;

            switch (type)
            {
            case DiskType.MD1DD8:
            case DiskType.MD2DD8:
                tracksize = 8 * 512;

                break;

            case DiskType.MD1DD:
            case DiskType.MD2DD:
            case DiskType.MF2DD:
                tracksize = 9 * 512;

                break;

            case DiskType.MD2HD:
                tracksize = 15 * 512;

                break;

            case DiskType.MF2HD:
                tracksize = 18 * 512;

                break;
            }

            int headstep = 1;

            if (type == DiskType.MD1DD ||
                type == DiskType.MD1DD8)
            {
                headstep = 2;
            }

            var decodedImage = new MemoryStream();

            for (int i = 0; i < tracks; i += headstep)
            {
                byte[] track = new byte[tracksize];

                if ((TrackType)trackBytes[i] == TrackType.Copied)
                {
                    stream.Read(track, 0, tracksize);
                }
                else
                {
                    ArrayHelpers.ArrayFill(track, (byte)0xF6);
                }

                decodedImage.Write(track, 0, tracksize);
            }

            imageInfo.Application          = "CisCopy";
            imageInfo.CreationTime         = imageFilter.GetCreationTime();
            imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
            imageInfo.MediaTitle           = imageFilter.GetFilename();
            imageInfo.ImageSize            = (ulong)(stream.Length - 2 - trackBytes.Length);
            imageInfo.SectorSize           = 512;

            switch (type)
            {
            case DiskType.MD1DD8:
                imageInfo.MediaType       = MediaType.DOS_525_SS_DD_8;
                imageInfo.Sectors         = 40 * 1 * 8;
                imageInfo.Heads           = 1;
                imageInfo.Cylinders       = 40;
                imageInfo.SectorsPerTrack = 8;

                break;

            case DiskType.MD2DD8:
                imageInfo.MediaType       = MediaType.DOS_525_DS_DD_8;
                imageInfo.Sectors         = 40 * 2 * 8;
                imageInfo.Heads           = 2;
                imageInfo.Cylinders       = 40;
                imageInfo.SectorsPerTrack = 8;

                break;

            case DiskType.MD1DD:
                imageInfo.MediaType       = MediaType.DOS_525_SS_DD_9;
                imageInfo.Sectors         = 40 * 1 * 9;
                imageInfo.Heads           = 1;
                imageInfo.Cylinders       = 40;
                imageInfo.SectorsPerTrack = 9;

                break;

            case DiskType.MD2DD:
                imageInfo.MediaType       = MediaType.DOS_525_DS_DD_9;
                imageInfo.Sectors         = 40 * 2 * 9;
                imageInfo.Heads           = 2;
                imageInfo.Cylinders       = 40;
                imageInfo.SectorsPerTrack = 9;

                break;

            case DiskType.MF2DD:
                imageInfo.MediaType       = MediaType.DOS_35_DS_DD_9;
                imageInfo.Sectors         = 80 * 2 * 9;
                imageInfo.Heads           = 2;
                imageInfo.Cylinders       = 80;
                imageInfo.SectorsPerTrack = 9;

                break;

            case DiskType.MD2HD:
                imageInfo.MediaType       = MediaType.DOS_525_HD;
                imageInfo.Sectors         = 80 * 2 * 15;
                imageInfo.Heads           = 2;
                imageInfo.Cylinders       = 80;
                imageInfo.SectorsPerTrack = 15;

                break;

            case DiskType.MF2HD:
                imageInfo.MediaType       = MediaType.DOS_35_HD;
                imageInfo.Sectors         = 80 * 2 * 18;
                imageInfo.Heads           = 2;
                imageInfo.Cylinders       = 80;
                imageInfo.SectorsPerTrack = 18;

                break;
            }

            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            decodedDisk            = decodedImage.ToArray();

            decodedImage.Close();

            AaruConsole.VerboseWriteLine("CisCopy image contains a disk of type {0}", imageInfo.MediaType);

            return(true);
        }