示例#1
0
        internal static byte[] ClearInquiry(byte[] inquiry)
        {
            Inquiry?decodedNullable = Inquiry.Decode(inquiry);

            if (!decodedNullable.HasValue)
            {
                return(inquiry);
            }

            Inquiry decoded = decodedNullable.Value;

            if (!decoded.SeagatePresent ||
                StringHandlers.CToString(decoded.VendorIdentification)?.Trim().ToLowerInvariant() != "seagate")
            {
                return(inquiry);
            }

            // Clear Seagate serial number
            for (int i = 36; i <= 43; i++)
            {
                inquiry[i] = 0;
            }

            return(inquiry);
        }
示例#2
0
        public Scsi ReportScsiInquiry()
        {
            AaruConsole.WriteLine("Querying SCSI INQUIRY...");
            bool sense = _dev.ScsiInquiry(out byte[] buffer, out _);

            var report = new Scsi();

            if (sense)
            {
                return(null);
            }

            Inquiry?decodedNullable = Inquiry.Decode(buffer);

            if (!decodedNullable.HasValue)
            {
                return(null);
            }

            report.InquiryData = ClearInquiry(buffer);

            return(report);
        }
示例#3
0
        public DeviceInfo(Device dev)
        {
            Type                  = dev.Type;
            Manufacturer          = dev.Manufacturer;
            Model                 = dev.Model;
            FirmwareRevision      = dev.FirmwareRevision;
            Serial                = dev.Serial;
            ScsiType              = dev.ScsiType;
            IsRemovable           = dev.IsRemovable;
            IsUsb                 = dev.IsUsb;
            UsbVendorId           = dev.UsbVendorId;
            UsbProductId          = dev.UsbProductId;
            UsbDescriptors        = dev.UsbDescriptors;
            UsbManufacturerString = dev.UsbManufacturerString;
            UsbProductString      = dev.UsbProductString;
            UsbSerialString       = dev.UsbSerialString;
            IsFireWire            = dev.IsFireWire;
            FireWireGuid          = dev.FireWireGuid;
            FireWireModel         = dev.FireWireModel;
            FireWireModelName     = dev.FireWireModelName;
            FireWireVendor        = dev.FireWireVendor;
            FireWireVendorName    = dev.FireWireVendorName;
            IsCompactFlash        = dev.IsCompactFlash;
            IsPcmcia              = dev.IsPcmcia;
            Cis = dev.Cis;

            switch (dev.Type)
            {
            case DeviceType.ATA:
            {
                bool sense = dev.AtaIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters);

                if (sense)
                {
                    AaruConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status);
                    AaruConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error);

                    AaruConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}",
                                               errorRegisters.SectorCount);

                    AaruConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector);

                    AaruConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}",
                                               errorRegisters.CylinderHigh);

                    AaruConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}",
                                               errorRegisters.CylinderLow);

                    AaruConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}",
                                               errorRegisters.DeviceHead);

                    AaruConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError);

                    break;
                }

                if (dev.Error)
                {
                    AaruConsole.ErrorWriteLine("Error {0} querying ATA IDENTIFY", dev.LastError);

                    break;
                }

                AtaIdentify = ataBuf;

                dev.EnableMediaCardPassThrough(out errorRegisters, dev.Timeout, out _);

                if (errorRegisters.Sector == 0xAA &&
                    errorRegisters.SectorCount == 0x55)
                {
                    AtaMcptError = errorRegisters;
                }

                break;
            }

            case DeviceType.ATAPI:
            {
                bool sense = dev.AtapiIdentify(out byte[] ataBuf, out AtaErrorRegistersChs errorRegisters);

                if (sense)
                {
                    AaruConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.Status);
                    AaruConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.Error);

                    AaruConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}",
                                               errorRegisters.SectorCount);

                    AaruConsole.DebugWriteLine("Device-Info command", "SECTOR = 0x{0:X2}", errorRegisters.Sector);

                    AaruConsole.DebugWriteLine("Device-Info command", "CYLHIGH = 0x{0:X2}",
                                               errorRegisters.CylinderHigh);

                    AaruConsole.DebugWriteLine("Device-Info command", "CYLLOW = 0x{0:X2}",
                                               errorRegisters.CylinderLow);

                    AaruConsole.DebugWriteLine("Device-Info command", "DEVICE = 0x{0:X2}",
                                               errorRegisters.DeviceHead);

                    AaruConsole.DebugWriteLine("Device-Info command", "Error code = {0}", dev.LastError);

                    break;
                }

                if (!dev.Error)
                {
                    AtapiIdentify = ataBuf;
                }
                else
                {
                    AaruConsole.ErrorWriteLine("Error {0} querying ATA PACKET IDENTIFY", dev.LastError);
                }

                // ATAPI devices are also SCSI devices
                goto case DeviceType.SCSI;
            }

            case DeviceType.SCSI:
            {
                bool sense = dev.ScsiInquiry(out byte[] inqBuf, out byte[] senseBuf);

                if (sense)
                {
                    AaruConsole.ErrorWriteLine("SCSI error:\n{0}", Sense.PrettifySense(senseBuf));

                    break;
                }

                ScsiInquiryData = inqBuf;
                ScsiInquiry     = Inquiry.Decode(inqBuf);

                sense = dev.ScsiInquiry(out inqBuf, out senseBuf, 0x00);

                if (!sense)
                {
                    ScsiEvpdPages = new Dictionary <byte, byte[]>();

                    byte[] pages = EVPD.DecodePage00(inqBuf);

                    if (pages != null)
                    {
                        foreach (byte page in pages)
                        {
                            sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page);

                            if (sense)
                            {
                                continue;
                            }

                            ScsiEvpdPages.Add(page, inqBuf);
                        }
                    }
                }

                var devType = (PeripheralDeviceTypes)ScsiInquiry.Value.PeripheralDeviceType;

                sense = dev.ModeSense10(out byte[] modeBuf, out senseBuf, false, true,
                                        ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out _);

                if (!sense &&
                    !dev.Error)
                {
                    ScsiModeSense10 = modeBuf;
                }

                if (sense || dev.Error)
                {
                    sense = dev.ModeSense10(out modeBuf, out senseBuf, false, true,
                                            ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        ScsiModeSense10 = modeBuf;
                    }
                }

                if (!sense &&
                    !dev.Error)
                {
                    ScsiMode = Modes.DecodeMode10(modeBuf, devType);
                }

                bool useMode10 = !(sense || dev.Error || !ScsiMode.HasValue);

                sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F,
                                       0xFF, 5, out _);

                if (!sense &&
                    !dev.Error)
                {
                    ScsiModeSense6 = modeBuf;
                }

                if (sense || dev.Error)
                {
                    sense = dev.ModeSense6(out modeBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F,
                                           0x00, 5, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        ScsiModeSense6 = modeBuf;
                    }
                }

                if (sense || dev.Error)
                {
                    sense = dev.ModeSense(out modeBuf, out senseBuf, 5, out _);

                    if (!sense &&
                        !dev.Error)
                    {
                        ScsiModeSense6 = modeBuf;
                    }
                }

                if (!sense &&
                    !dev.Error &&
                    !useMode10)
                {
                    ScsiMode = Modes.DecodeMode6(modeBuf, devType);
                }

                switch (devType)
                {
                case PeripheralDeviceTypes.MultiMediaDevice:
                {
                    sense = dev.GetConfiguration(out byte[] confBuf, out senseBuf, dev.Timeout, out _);

                    if (!sense)
                    {
                        MmcConfiguration = confBuf;
                    }

                    // TODO: DVD drives respond correctly to BD status.
                    // While specification says if no medium is present
                    // it should inform all possible capabilities,
                    // testing drives show only supported media capabilities.

                    /*
                     * byte[] strBuf;
                     * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _);
                     *
                     * if (!sense)
                     * {
                     *  Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf);
                     *  if (caps != null)
                     *  {
                     *      foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps)
                     *      {
                     *          if (cap.SDS && cap.RDS)
                     *              AaruConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *          else if (cap.SDS)
                     *              AaruConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *          else if (cap.RDS)
                     *              AaruConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *      }
                     *  }
                     * }
                     *
                     * sense = dev.ReadDiscStructure(out strBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.CapabilityList, 0, dev.Timeout, out _);
                     *
                     * if (!sense)
                     * {
                     *  Decoders.SCSI.DiscStructureCapabilities.Capability[] caps = Decoders.SCSI.DiscStructureCapabilities.Decode(strBuf);
                     *  if (caps != null)
                     *  {
                     *      foreach (Decoders.SCSI.DiscStructureCapabilities.Capability cap in caps)
                     *      {
                     *          if (cap.SDS && cap.RDS)
                     *              AaruConsole.WriteLine("Drive can READ/SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *          else if (cap.SDS)
                     *              AaruConsole.WriteLine("Drive can SEND DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *          else if (cap.RDS)
                     *              AaruConsole.WriteLine("Drive can READ DISC STRUCTURE format {0:X2}h", cap.FormatCode);
                     *      }
                     *  }
                     * }
                     */

                    #region Plextor
                    if (dev.Manufacturer == "PLEXTOR")
                    {
                        bool   plxtSense = true;
                        bool   plxtDvd   = false;
                        byte[] plxtBuf   = null;

                        switch (dev.Model)
                        {
                        case "DVDR   PX-708A":
                        case "DVDR   PX-708A2":
                        case "DVDR   PX-712A":
                            plxtDvd = true;

                            plxtSense = dev.PlextorReadEeprom(out plxtBuf, out senseBuf, dev.Timeout,
                                                              out _);

                            break;

                        case "DVDR   PX-714A":
                        case "DVDR   PX-716A":
                        case "DVDR   PX-716AL":
                        case "DVDR   PX-755A":
                        case "DVDR   PX-760A":
                        {
                            plxtBuf = new byte[256 * 4];

                            for (byte i = 0; i < 4; i++)
                            {
                                plxtSense = dev.PlextorReadEepromBlock(out byte[] plxtBufSmall,
                                                                       out senseBuf, i, 256, dev.Timeout,
                                                                       out _);

                                if (plxtSense)
                                {
                                    break;
                                }

                                Array.Copy(plxtBufSmall, 0, plxtBuf, i * 256, 256);
                            }

                            plxtDvd = true;

                            break;
                        }

                        default:
                        {
                            if (dev.Model.StartsWith("CD-R   ", StringComparison.Ordinal))
                            {
                                plxtSense = dev.PlextorReadEepromCdr(out plxtBuf, out senseBuf, dev.Timeout,
                                                                     out _);
                            }

                            break;
                        }
                        }

                        PlextorFeatures = new Plextor
                        {
                            IsDvd = plxtDvd
                        };

                        if (!plxtSense)
                        {
                            PlextorFeatures.Eeprom = plxtBuf;

                            if (plxtDvd)
                            {
                                PlextorFeatures.Discs        = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0120);
                                PlextorFeatures.CdReadTime   = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0122);
                                PlextorFeatures.CdWriteTime  = BigEndianBitConverter.ToUInt32(plxtBuf, 0x0126);
                                PlextorFeatures.DvdReadTime  = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012A);
                                PlextorFeatures.DvdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x012E);
                            }
                            else
                            {
                                PlextorFeatures.Discs       = BigEndianBitConverter.ToUInt16(plxtBuf, 0x0078);
                                PlextorFeatures.CdReadTime  = BigEndianBitConverter.ToUInt32(plxtBuf, 0x006C);
                                PlextorFeatures.CdWriteTime = BigEndianBitConverter.ToUInt32(plxtBuf, 0x007A);
                            }
                        }

                        plxtSense = dev.PlextorGetPoweRec(out senseBuf, out bool plxtPwrRecEnabled,
                                                          out ushort plxtPwrRecSpeed, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.PoweRec = true;

                            if (plxtPwrRecEnabled)
                            {
                                PlextorFeatures.PoweRecEnabled          = true;
                                PlextorFeatures.PoweRecRecommendedSpeed = plxtPwrRecSpeed;

                                plxtSense = dev.PlextorGetSpeeds(out senseBuf, out ushort plxtPwrRecSelected,
                                                                 out ushort plxtPwrRecMax,
                                                                 out ushort plxtPwrRecLast, dev.Timeout, out _);

                                if (!plxtSense)
                                {
                                    PlextorFeatures.PoweRecSelected = plxtPwrRecSelected;
                                    PlextorFeatures.PoweRecMax      = plxtPwrRecMax;
                                    PlextorFeatures.PoweRecLast     = plxtPwrRecLast;
                                }
                            }
                        }

                        // TODO: Check it with a drive
                        plxtSense = dev.PlextorGetSilentMode(out plxtBuf, out senseBuf, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            if (plxtBuf[0] == 1)
                            {
                                PlextorFeatures.SilentModeEnabled = true;
                                PlextorFeatures.AccessTimeLimit   = plxtBuf[1];

                                PlextorFeatures.CdReadSpeedLimit  = plxtBuf[2];
                                PlextorFeatures.DvdReadSpeedLimit = plxtBuf[3];
                                PlextorFeatures.CdWriteSpeedLimit = plxtBuf[4];

                                // TODO: Check which one is each one

                                /*
                                 *  if(plxtBuf[6] > 0)
                                 *      AaruConsole.WriteLine("\tTray eject speed limited to {0}",
                                 *                           -(plxtBuf[6] + 48));
                                 *  if(plxtBuf[7] > 0)
                                 *      AaruConsole.WriteLine("\tTray eject speed limited to {0}",
                                 *                           plxtBuf[7] - 47);
                                 */
                            }
                        }

                        plxtSense = dev.PlextorGetGigaRec(out plxtBuf, out senseBuf, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.GigaRec = true;
                        }

                        plxtSense = dev.PlextorGetSecuRec(out plxtBuf, out senseBuf, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.SecuRec = true;
                        }

                        plxtSense = dev.PlextorGetSpeedRead(out plxtBuf, out senseBuf, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.SpeedRead = true;

                            if ((plxtBuf[2] & 0x01) == 0x01)
                            {
                                PlextorFeatures.SpeedReadEnabled = true;
                            }
                        }

                        plxtSense = dev.PlextorGetHiding(out plxtBuf, out senseBuf, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.Hiding = true;

                            if ((plxtBuf[2] & 0x02) == 0x02)
                            {
                                PlextorFeatures.HidesRecordables = true;
                            }

                            if ((plxtBuf[2] & 0x01) == 0x01)
                            {
                                PlextorFeatures.HidesSessions = true;
                            }
                        }

                        plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, false, dev.Timeout, out _);

                        if (!plxtSense)
                        {
                            PlextorFeatures.VariRec = true;
                        }

                        if (plxtDvd)
                        {
                            plxtSense = dev.PlextorGetVariRec(out plxtBuf, out senseBuf, true, dev.Timeout,
                                                              out _);

                            if (!plxtSense)
                            {
                                PlextorFeatures.VariRecDvd = true;
                            }

                            plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, false, dev.Timeout,
                                                                 out _);

                            if (!plxtSense)
                            {
                                PlextorFeatures.BitSetting = true;
                            }

                            plxtSense = dev.PlextorGetBitsetting(out plxtBuf, out senseBuf, true, dev.Timeout,
                                                                 out _);

                            if (!plxtSense)
                            {
                                PlextorFeatures.BitSettingDl = true;
                            }

                            plxtSense = dev.PlextorGetTestWriteDvdPlus(out plxtBuf, out senseBuf, dev.Timeout,
                                                                       out _);

                            if (!plxtSense)
                            {
                                PlextorFeatures.DvdPlusWriteTest = true;
                            }
                        }
                    }
                    #endregion Plextor

                    if (ScsiInquiry.Value.KreonPresent)
                    {
                        if (!dev.KreonGetFeatureList(out senseBuf, out KreonFeatures krFeatures, dev.Timeout,
                                                     out _))
                        {
                            KreonFeatures = krFeatures;
                        }
                    }

                    break;
                }

                case PeripheralDeviceTypes.SequentialAccess:
                {
                    sense = dev.ReadBlockLimits(out byte[] seqBuf, out senseBuf, dev.Timeout, out _);

                    if (sense)
                    {
                        AaruConsole.ErrorWriteLine("READ BLOCK LIMITS:\n{0}", Sense.PrettifySense(senseBuf));
                    }
                    else
                    {
                        BlockLimits = seqBuf;
                    }

                    sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, dev.Timeout, out _);

                    if (sense)
                    {
                        AaruConsole.ErrorWriteLine("REPORT DENSITY SUPPORT:\n{0}",
                                                   Sense.PrettifySense(senseBuf));
                    }
                    else
                    {
                        DensitySupport       = seqBuf;
                        DensitySupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(seqBuf);
                    }

                    sense = dev.ReportDensitySupport(out seqBuf, out senseBuf, true, false, dev.Timeout, out _);

                    if (sense)
                    {
                        AaruConsole.ErrorWriteLine("REPORT DENSITY SUPPORT (MEDIUM):\n{0}",
                                                   Sense.PrettifySense(senseBuf));
                    }
                    else
                    {
                        MediumDensitySupport   = seqBuf;
                        MediaTypeSupportHeader = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(seqBuf);
                    }

                    break;
                }
                }

                break;
            }

            case DeviceType.MMC:
            {
                bool sense = dev.ReadCid(out byte[] mmcBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    CID = mmcBuf;
                }

                sense = dev.ReadCsd(out mmcBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    CSD = mmcBuf;
                }

                sense = dev.ReadOcr(out mmcBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    OCR = mmcBuf;
                }

                sense = dev.ReadExtendedCsd(out mmcBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    ExtendedCSD = mmcBuf;
                }
            }

            break;

            case DeviceType.SecureDigital:
            {
                bool sense = dev.ReadCid(out byte[] sdBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    CID = sdBuf;
                }

                sense = dev.ReadCsd(out sdBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    CSD = sdBuf;
                }

                sense = dev.ReadSdocr(out sdBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    OCR = sdBuf;
                }

                sense = dev.ReadScr(out sdBuf, out _, dev.Timeout, out _);

                if (!sense)
                {
                    SCR = sdBuf;
                }
            }

            break;

            default:
                AaruConsole.ErrorWriteLine("Unknown device type {0}, cannot get information.", dev.Type);

                break;
            }
        }
示例#4
0
        public ImageInfoViewModel(string imagePath, IFilter filter, IMediaImage imageFormat, Window view)

        {
            _imagePath   = imagePath;
            _filter      = filter;
            _imageFormat = imageFormat;
            _view        = view;
            IAssetLoader assets = AvaloniaLocator.Current.GetService <IAssetLoader>();

            MediaTagsList         = new ObservableCollection <string>();
            SectorTagsList        = new ObservableCollection <string>();
            Sessions              = new ObservableCollection <Session>();
            Tracks                = new ObservableCollection <Track>();
            DumpHardwareList      = new ObservableCollection <DumpHardwareModel>();
            EntropyCommand        = ReactiveCommand.Create(ExecuteEntropyCommand);
            VerifyCommand         = ReactiveCommand.Create(ExecuteVerifyCommand);
            ChecksumCommand       = ReactiveCommand.Create(ExecuteChecksumCommand);
            ConvertCommand        = ReactiveCommand.Create(ExecuteConvertCommand);
            CreateSidecarCommand  = ReactiveCommand.Create(ExecuteCreateSidecarCommand);
            ViewSectorsCommand    = ReactiveCommand.Create(ExecuteViewSectorsCommand);
            DecodeMediaTagCommand = ReactiveCommand.Create(ExecuteDecodeMediaTagCommand);

            var genericHddIcon =
                new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png")));

            var genericOpticalIcon =
                new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-optical.png")));

            var genericFolderIcon =
                new Bitmap(assets.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/inode-directory.png")));

            var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{imageFormat.Info.MediaType}.png");

            MediaLogo = assets.Exists(mediaResource)
                            ? new Bitmap(assets.Open(mediaResource))
                            : imageFormat.Info.XmlMediaType == XmlMediaType.BlockMedia
                                ? genericHddIcon
                                : imageFormat.Info.XmlMediaType == XmlMediaType.OpticalDisc
                                    ? genericOpticalIcon
                                    : genericFolderIcon;

            ImagePathText       = $"Path: {imagePath}";
            FilterText          = $"Filter: {filter.Name}";
            ImageIdentifiedText = $"Image format identified by {imageFormat.Name} ({imageFormat.Id}).";

            ImageFormatText = !string.IsNullOrWhiteSpace(imageFormat.Info.Version)
                                  ? $"Format: {imageFormat.Format} version {imageFormat.Info.Version}"
                                  : $"Format: {imageFormat.Format}";

            ImageSizeText = $"Image without headers is {imageFormat.Info.ImageSize} bytes long";

            SectorsText =
                $"Contains a media of {imageFormat.Info.Sectors} sectors with a maximum sector size of {imageFormat.Info.SectorSize} bytes (if all sectors are of the same size this would be {imageFormat.Info.Sectors * imageFormat.Info.SectorSize} bytes)";

            MediaTypeText =
                $"Contains a media of type {imageFormat.Info.MediaType} and XML type {imageFormat.Info.XmlMediaType}";

            HasPartitionsText = $"{(imageFormat.Info.HasPartitions ? "Has" : "Doesn't have")} partitions";
            HasSessionsText   = $"{(imageFormat.Info.HasSessions ? "Has" : "Doesn't have")} sessions";

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
            {
                ApplicationText = !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion)
                                      ? $"Was created with {imageFormat.Info.Application} version {imageFormat.Info.ApplicationVersion}"
                                      : $"Was created with {imageFormat.Info.Application}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
            {
                CreatorText = $"Created by: {imageFormat.Info.Creator}";
            }

            if (imageFormat.Info.CreationTime != DateTime.MinValue)
            {
                CreationTimeText = $"Created on {imageFormat.Info.CreationTime}";
            }

            if (imageFormat.Info.LastModificationTime != DateTime.MinValue)
            {
                LastModificationTimeText = $"Last modified on {imageFormat.Info.LastModificationTime}";
            }

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

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
            {
                MediaTitleText = $"Media title: {imageFormat.Info.MediaTitle}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
            {
                MediaManufacturerText = $"Media manufacturer: {imageFormat.Info.MediaManufacturer}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
            {
                MediaModelText = $"Media model: {imageFormat.Info.MediaModel}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
            {
                MediaSerialNumberText = $"Media serial number: {imageFormat.Info.MediaSerialNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
            {
                MediaBarcodeText = $"Media barcode: {imageFormat.Info.MediaBarcode}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
            {
                MediaPartNumberText = $"Media part number: {imageFormat.Info.MediaPartNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
            {
                DriveManufacturerText = $"Drive manufacturer: {imageFormat.Info.DriveManufacturer}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
            {
                DriveModelText = $"Drive model: {imageFormat.Info.DriveModel}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
            {
                DriveSerialNumberText = $"Drive serial number: {imageFormat.Info.DriveSerialNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
            {
                DriveFirmwareRevisionText = $"Drive firmware info: {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))
            {
                MediaGeometryText =
                    $"Media geometry: {imageFormat.Info.Cylinders} cylinders, {imageFormat.Info.Heads} heads, {imageFormat.Info.SectorsPerTrack} sectors per track";
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Count > 0)
            {
                foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
                {
                    MediaTagsList.Add(tag.ToString());
                }
            }

            if (imageFormat.Info.ReadableSectorTags != null &&
                imageFormat.Info.ReadableSectorTags.Count > 0)
            {
                foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
                {
                    SectorTagsList.Add(tag.ToString());
                }
            }

            PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;

            byte[]  scsiInquiryData = null;
            Inquiry?scsiInquiry     = null;

            Modes.DecodedMode?scsiMode        = null;
            byte[]            scsiModeSense6  = null;
            byte[]            scsiModeSense10 = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_INQUIRY))
            {
                scsiInquiryData = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);

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

                scsiInquiry = Inquiry.Decode(scsiInquiryData);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_6))
            {
                scsiModeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6);
                scsiMode       = Modes.DecodeMode6(scsiModeSense6, scsiDeviceType);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_10))
            {
                scsiModeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10);
                scsiMode        = Modes.DecodeMode10(scsiModeSense10, scsiDeviceType);
            }

            ScsiInfo = new ScsiInfo
            {
                DataContext = new ScsiInfoViewModel(scsiInquiryData, scsiInquiry, null, scsiMode, scsiDeviceType,
                                                    scsiModeSense6, scsiModeSense10, null, _view)
            };

            byte[] ataIdentify   = null;
            byte[] atapiIdentify = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
            {
                ataIdentify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATAPI_IDENTIFY))
            {
                atapiIdentify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY);
            }

            AtaInfo = new AtaInfo
            {
                DataContext = new AtaInfoViewModel(ataIdentify, atapiIdentify, null, _view)
            };

            byte[]                toc                  = null;
            TOC.CDTOC?            decodedToc           = null;
            byte[]                fullToc              = null;
            FullTOC.CDFullTOC?    decodedFullToc       = null;
            byte[]                pma                  = null;
            byte[]                atip                 = null;
            ATIP.CDATIP?          decodedAtip          = null;
            byte[]                cdtext               = null;
            CDTextOnLeadIn.CDText?decodedCdText        = null;
            string                mediaCatalogueNumber = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TOC))
            {
                toc = imageFormat.ReadDiskTag(MediaTagType.CD_TOC);

                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;
                    }

                    decodedToc = TOC.Decode(toc);
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_FullTOC))
            {
                fullToc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC);

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

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

                    decodedFullToc = FullTOC.Decode(fullToc);
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_PMA))
            {
                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;
                    }
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_ATIP))
            {
                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;
                }

                decodedAtip = ATIP.Decode(atip);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TEXT))
            {
                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;
                }

                decodedCdText = CDTextOnLeadIn.Decode(cdtext);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
            {
                byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN);

                mediaCatalogueNumber = Encoding.UTF8.GetString(mcn);
            }

            CompactDiscInfo = new CompactDiscInfo
            {
                DataContext = new CompactDiscInfoViewModel(toc, atip, null, null, fullToc, pma, cdtext, decodedToc,
                                                           decodedAtip, null, decodedFullToc, decodedCdText, null,
                                                           mediaCatalogueNumber, null, _view)
            };

            byte[] dvdPfi = null;
            byte[] dvdDmi = null;
            byte[] dvdCmi = null;
            byte[] hddvdCopyrightInformation = null;
            byte[] dvdBca = null;
            PFI.PhysicalFormatInformation?decodedPfi = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_PFI))
            {
                dvdPfi     = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI);
                decodedPfi = PFI.Decode(dvdPfi);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_DMI))
            {
                dvdDmi = imageFormat.ReadDiskTag(MediaTagType.DVD_DMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_CMI))
            {
                dvdCmi = imageFormat.ReadDiskTag(MediaTagType.DVD_CMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_CPI))
            {
                hddvdCopyrightInformation = imageFormat.ReadDiskTag(MediaTagType.HDDVD_CPI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_BCA))
            {
                dvdBca = imageFormat.ReadDiskTag(MediaTagType.DVD_BCA);
            }

            DvdInfo = new DvdInfo
            {
                DataContext = new DvdInfoViewModel(imageFormat.Info.MediaType, dvdPfi, dvdDmi, dvdCmi,
                                                   hddvdCopyrightInformation, dvdBca, null, decodedPfi, _view)
            };

            byte[] dvdRamDds                     = null;
            byte[] dvdRamCartridgeStatus         = null;
            byte[] dvdRamSpareArea               = null;
            byte[] lastBorderOutRmd              = null;
            byte[] dvdPreRecordedInfo            = null;
            byte[] dvdrMediaIdentifier           = null;
            byte[] dvdrPhysicalInformation       = null;
            byte[] hddvdrMediumStatus            = null;
            byte[] dvdrLayerCapacity             = null;
            byte[] dvdrDlMiddleZoneStart         = null;
            byte[] dvdrDlJumpIntervalSize        = null;
            byte[] dvdrDlManualLayerJumpStartLba = null;
            byte[] dvdPlusAdip                   = null;
            byte[] dvdPlusDcb                    = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_DDS))
            {
                dvdRamDds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_MediumStatus))
            {
                dvdRamCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_MediumStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_SpareArea))
            {
                dvdRamSpareArea = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_SpareArea);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_RMD))
            {
                lastBorderOutRmd = imageFormat.ReadDiskTag(MediaTagType.DVDR_RMD);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PreRecordedInfo))
            {
                dvdPreRecordedInfo = imageFormat.ReadDiskTag(MediaTagType.DVDR_PreRecordedInfo);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_MediaIdentifier))
            {
                dvdrMediaIdentifier = imageFormat.ReadDiskTag(MediaTagType.DVDR_MediaIdentifier);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PFI))
            {
                dvdrPhysicalInformation = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_MediumStatus))
            {
                hddvdrMediumStatus = imageFormat.ReadDiskTag(MediaTagType.HDDVD_MediumStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_LayerCapacity))
            {
                dvdrLayerCapacity = imageFormat.ReadDiskTag(MediaTagType.DVDDL_LayerCapacity);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_MiddleZoneAddress))
            {
                dvdrDlMiddleZoneStart = imageFormat.ReadDiskTag(MediaTagType.DVDDL_MiddleZoneAddress);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_JumpIntervalSize))
            {
                dvdrDlJumpIntervalSize = imageFormat.ReadDiskTag(MediaTagType.DVDDL_JumpIntervalSize);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_ManualLayerJumpLBA))
            {
                dvdrDlManualLayerJumpStartLba = imageFormat.ReadDiskTag(MediaTagType.DVDDL_ManualLayerJumpLBA);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_ADIP))
            {
                dvdPlusAdip = imageFormat.ReadDiskTag(MediaTagType.DVD_ADIP);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DCB))
            {
                dvdPlusDcb = imageFormat.ReadDiskTag(MediaTagType.DCB);
            }

            DvdWritableInfo = new DvdWritableInfo
            {
                DataContext = new DvdWritableInfoViewModel(imageFormat.Info.MediaType, dvdRamDds, dvdRamCartridgeStatus,
                                                           dvdRamSpareArea, lastBorderOutRmd, dvdPreRecordedInfo,
                                                           dvdrMediaIdentifier, dvdrPhysicalInformation,
                                                           hddvdrMediumStatus, null, dvdrLayerCapacity,
                                                           dvdrDlMiddleZoneStart, dvdrDlJumpIntervalSize,
                                                           dvdrDlManualLayerJumpStartLba, null, dvdPlusAdip, dvdPlusDcb,
                                                           _view)
            };

            byte[] blurayBurstCuttingArea = null;
            byte[] blurayCartridgeStatus  = null;
            byte[] blurayDds                  = null;
            byte[] blurayDiscInformation      = null;
            byte[] blurayPowResources         = null;
            byte[] bluraySpareAreaInformation = null;
            byte[] blurayTrackResources       = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_BCA))
            {
                blurayBurstCuttingArea = imageFormat.ReadDiskTag(MediaTagType.BD_BCA);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_CartridgeStatus))
            {
                blurayCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.BD_CartridgeStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DDS))
            {
                blurayDds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DI))
            {
                blurayDiscInformation = imageFormat.ReadDiskTag(MediaTagType.BD_DI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_POWResourcesInformation))
            {
                blurayPowResources = imageFormat.ReadDiskTag(MediaTagType.MMC_POWResourcesInformation);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_SpareArea))
            {
                bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.BD_SpareArea);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_TrackResourcesInformation))
            {
                bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.MMC_TrackResourcesInformation);
            }

            BlurayInfo = new BlurayInfo
            {
                DataContext = new BlurayInfoViewModel(blurayDiscInformation, blurayBurstCuttingArea, blurayDds,
                                                      blurayCartridgeStatus, bluraySpareAreaInformation,
                                                      blurayPowResources, blurayTrackResources, null, null, _view)
            };

            byte[]            xboxDmi                   = null;
            byte[]            xboxSecuritySector        = null;
            SS.SecuritySector?decodedXboxSecuritySector = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_DMI))
            {
                xboxDmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_SecuritySector))
            {
                xboxSecuritySector        = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector);
                decodedXboxSecuritySector = SS.Decode(xboxSecuritySector);
            }

            XboxInfo = new XboxInfo
            {
                DataContext = new XboxInfoViewModel(null, xboxDmi, xboxSecuritySector, decodedXboxSecuritySector, _view)
            };

            byte[] pcmciaCis = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS))
            {
                pcmciaCis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS);
            }

            PcmciaInfo = new PcmciaInfo
            {
                DataContext = new PcmciaInfoViewModel(pcmciaCis, _view)
            };

            DeviceType deviceType = DeviceType.Unknown;

            byte[] cid         = null;
            byte[] csd         = null;
            byte[] ocr         = null;
            byte[] extendedCsd = null;
            byte[] scr         = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CID))
            {
                cid        = imageFormat.ReadDiskTag(MediaTagType.SD_CID);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CSD))
            {
                csd        = imageFormat.ReadDiskTag(MediaTagType.SD_CSD);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_OCR))
            {
                ocr        = imageFormat.ReadDiskTag(MediaTagType.SD_OCR);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_SCR))
            {
                scr        = imageFormat.ReadDiskTag(MediaTagType.SD_SCR);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CID))
            {
                cid        = imageFormat.ReadDiskTag(MediaTagType.MMC_CID);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CSD))
            {
                csd        = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_OCR))
            {
                ocr        = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_ExtendedCSD))
            {
                extendedCsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD);
                deviceType  = DeviceType.MMC;
            }

            SdMmcInfo = new SdMmcInfo
            {
                DataContext = new SdMmcInfoViewModel(deviceType, cid, csd, ocr, extendedCsd, scr)
            };

            if (imageFormat is IOpticalMediaImage opticalMediaImage)
            {
                try
                {
                    if (opticalMediaImage.Sessions != null &&
                        opticalMediaImage.Sessions.Count > 0)
                    {
                        foreach (Session session in opticalMediaImage.Sessions)
                        {
                            Sessions.Add(session);
                        }
                    }
                }
                catch
                {
                    // ignored
                }

                try
                {
                    if (opticalMediaImage.Tracks != null &&
                        opticalMediaImage.Tracks.Count > 0)
                    {
                        foreach (Track track in opticalMediaImage.Tracks)
                        {
                            Tracks.Add(track);
                        }
                    }
                }
                catch
                {
                    // ignored
                }
            }

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

            foreach (DumpHardwareType dump in imageFormat.DumpHardware)
            {
                foreach (ExtentType extent in dump.Extents)
                {
                    DumpHardwareList.Add(new DumpHardwareModel
                    {
                        Manufacturer    = dump.Manufacturer, Model = dump.Model, Serial = dump.Serial,
                        SoftwareName    = dump.Software.Name, SoftwareVersion = dump.Software.Version,
                        OperatingSystem = dump.Software.OperatingSystem, Start = extent.Start, End = extent.End
                    });
                }
            }
        }
示例#5
0
        /// <summary>Dumps an optical disc</summary>
        void Mmc()
        {
            MediaType dskType = MediaType.Unknown;
            bool      sense;

            byte[]        tmpBuf;
            bool          compactDisc      = true;
            bool          gotConfiguration = false;
            bool          isXbox           = false;
            DVDDecryption dvdDecrypt       = null;

            _speedMultiplier = 1;

            // TODO: Log not only what is it reading, but if it was read correctly or not.
            sense = _dev.GetConfiguration(out byte[] cmdBuf, out _, 0, MmcGetConfigurationRt.Current, _dev.Timeout,
                                          out _);

            if (!sense)
            {
                gotConfiguration = true;
                Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
                _dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile);

                switch (ftr.CurrentProfile)
                {
                case 0x0001:
                    dskType          = MediaType.GENERIC_HDD;
                    _speedMultiplier = -1;
                    goto default;

                case 0x0002:
                    dskType          = MediaType.PD650;
                    _speedMultiplier = -1;
                    goto default;

                case 0x0005:
                    dskType = MediaType.CDMO;

                    break;

                case 0x0008:
                    dskType = MediaType.CD;

                    break;

                case 0x0009:
                    dskType = MediaType.CDR;

                    break;

                case 0x000A:
                    dskType = MediaType.CDRW;

                    break;

                case 0x0010:
                    dskType          = MediaType.DVDROM;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0011:
                    dskType          = MediaType.DVDR;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0012:
                    dskType          = MediaType.DVDRAM;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0013:
                case 0x0014:
                    dskType          = MediaType.DVDRW;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0015:
                case 0x0016:
                    dskType          = MediaType.DVDRDL;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0017:
                    dskType          = MediaType.DVDRWDL;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0018:
                    dskType          = MediaType.DVDDownload;
                    _speedMultiplier = 9;
                    goto default;

                case 0x001A:
                    dskType          = MediaType.DVDPRW;
                    _speedMultiplier = 9;
                    goto default;

                case 0x001B:
                    dskType          = MediaType.DVDPR;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0020:
                    dskType = MediaType.DDCD;
                    goto default;

                case 0x0021:
                    dskType = MediaType.DDCDR;
                    goto default;

                case 0x0022:
                    dskType = MediaType.DDCDRW;
                    goto default;

                case 0x002A:
                    dskType          = MediaType.DVDPRWDL;
                    _speedMultiplier = 9;
                    goto default;

                case 0x002B:
                    dskType          = MediaType.DVDPRDL;
                    _speedMultiplier = 9;
                    goto default;

                case 0x0040:
                    dskType          = MediaType.BDROM;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0041:
                case 0x0042:
                    dskType          = MediaType.BDR;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0043:
                    dskType          = MediaType.BDRE;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0050:
                    dskType          = MediaType.HDDVDROM;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0051:
                    dskType          = MediaType.HDDVDR;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0052:
                    dskType          = MediaType.HDDVDRAM;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0053:
                    dskType          = MediaType.HDDVDRW;
                    _speedMultiplier = 30;
                    goto default;

                case 0x0058:
                    dskType          = MediaType.HDDVDRDL;
                    _speedMultiplier = 30;
                    goto default;

                case 0x005A:
                    dskType          = MediaType.HDDVDRWDL;
                    _speedMultiplier = 30;
                    goto default;

                default:
                    compactDisc = false;

                    break;
                }
            }

            Modes.DecodedMode?decMode = null;

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

            if (sense || _dev.Error)
            {
                sense = _dev.ModeSense6(out cmdBuf, out _, false, ScsiModeSensePageControl.Current, 0x00, _dev.Timeout,
                                        out _);

                if (!sense &&
                    !_dev.Error)
                {
                    decMode = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
                }
            }
            else
            {
                decMode = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
            }

            if (decMode is null)
            {
                sense = _dev.ModeSense10(out cmdBuf, out _, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00,
                                         _dev.Timeout, out _);

                if (sense || _dev.Error)
                {
                    sense = _dev.ModeSense10(out cmdBuf, out _, false, false, ScsiModeSensePageControl.Current, 0x3F,
                                             0x00, _dev.Timeout, out _);

                    if (sense || _dev.Error)
                    {
                        sense = _dev.ModeSense10(out cmdBuf, out _, false, true, ScsiModeSensePageControl.Current, 0x00,
                                                 0x00, _dev.Timeout, out _);

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

                            if (!sense &&
                                !_dev.Error)
                            {
                                decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
                            }
                        }
                        else
                        {
                            decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
                        }
                    }
                    else
                    {
                        decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
                    }
                }
                else
                {
                    decMode = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice);
                }
            }

            if (decMode.HasValue &&
                _dev.IsUsb &&
                !gotConfiguration &&
                (decMode.Value.Header.MediumType == MediumTypes.UnknownBlockDevice ||
                 decMode.Value.Header.MediumType == MediumTypes.ReadOnlyBlockDevice ||
                 decMode.Value.Header.MediumType == MediumTypes.ReadWriteBlockDevice))
            {
                _speedMultiplier = -1;
                Sbc(null, MediaType.Unknown, false);

                return;
            }

            if (compactDisc)
            {
                _speedMultiplier *= 177;
                CompactDisc();

                return;
            }

            _speedMultiplier *= 150;

            var   scsiReader = new Reader(_dev, _dev.Timeout, null, _errorLog, _dumpRaw);
            ulong blocks     = scsiReader.GetDeviceBlocks();

            _dumpLog.WriteLine("Device reports disc has {0} blocks", blocks);
            Dictionary <MediaTagType, byte[]> mediaTags = new Dictionary <MediaTagType, byte[]>();

            if (dskType == MediaType.PD650)
            {
                switch (blocks + 1)
                {
                case 1281856:
                    dskType = MediaType.PD650_WORM;

                    break;

                case 58620544:
                    dskType = MediaType.REV120;

                    break;

                case 17090880:
                    dskType = MediaType.REV35;

                    break;

                case 34185728:
                    dskType = MediaType.REV70;

                    break;
                }
            }

            #region Nintendo
            switch (dskType)
            {
            case MediaType.Unknown when blocks > 0:
                _dumpLog.WriteLine("Reading Physical Format Information");

                sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
                                               MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _);

                if (!sense)
                {
                    PFI.PhysicalFormatInformation?nintendoPfi = PFI.Decode(cmdBuf);

                    if (nintendoPfi?.DiskCategory == DiskCategory.Nintendo &&
                        nintendoPfi.Value.PartVersion == 15)
                    {
                        _dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");

                        StoppingErrorMessage?.
                        Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented.");

                        return;
                    }
                }

                break;

            case MediaType.DVDDownload:
            case MediaType.DVDPR:
            case MediaType.DVDPRDL:
            case MediaType.DVDPRW:
            case MediaType.DVDPRWDL:
            case MediaType.DVDR:
            case MediaType.DVDRAM:
            case MediaType.DVDRDL:
            case MediaType.DVDROM:
            case MediaType.DVDRW:
            case MediaType.DVDRWDL:
            case MediaType.HDDVDR:
            case MediaType.HDDVDRAM:
            case MediaType.HDDVDRDL:
            case MediaType.HDDVDROM:
            case MediaType.HDDVDRW:
            case MediaType.HDDVDRWDL:
                _dumpLog.WriteLine("Reading Physical Format Information");

                sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
                                               MmcDiscStructureFormat.PhysicalInformation, 0, _dev.Timeout, out _);

                if (!sense)
                {
                    if (PFI.Decode(cmdBuf).HasValue)
                    {
                        tmpBuf = new byte[cmdBuf.Length - 4];
                        Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
                        mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf);

                        PFI.PhysicalFormatInformation decPfi = PFI.Decode(cmdBuf).Value;
                        UpdateStatus?.Invoke($"PFI:\n{PFI.Prettify(decPfi)}");

                        // False book types
                        switch (decPfi.DiskCategory)
                        {
                        case DiskCategory.DVDPR:
                            dskType = MediaType.DVDPR;

                            break;

                        case DiskCategory.DVDPRDL:
                            dskType = MediaType.DVDPRDL;

                            break;

                        case DiskCategory.DVDPRW:
                            dskType = MediaType.DVDPRW;

                            break;

                        case DiskCategory.DVDPRWDL:
                            dskType = MediaType.DVDPRWDL;

                            break;

                        case DiskCategory.DVDR:
                            dskType = decPfi.PartVersion >= 6 ? MediaType.DVDRDL : MediaType.DVDR;

                            break;

                        case DiskCategory.DVDRAM:
                            dskType = MediaType.DVDRAM;

                            break;

                        default:
                            dskType = MediaType.DVDROM;

                            break;

                        case DiskCategory.DVDRW:
                            dskType = decPfi.PartVersion >= 15 ? MediaType.DVDRWDL : MediaType.DVDRW;

                            break;

                        case DiskCategory.HDDVDR:
                            dskType = MediaType.HDDVDR;

                            break;

                        case DiskCategory.HDDVDRAM:
                            dskType = MediaType.HDDVDRAM;

                            break;

                        case DiskCategory.HDDVDROM:
                            dskType = MediaType.HDDVDROM;

                            break;

                        case DiskCategory.HDDVDRW:
                            dskType = MediaType.HDDVDRW;

                            break;

                        case DiskCategory.Nintendo:
                            dskType = decPfi.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD;

                            break;

                        case DiskCategory.UMD:
                            dskType = MediaType.UMD;

                            break;
                        }
                    }
                }

                _dumpLog.WriteLine("Reading Disc Manufacturing Information");

                sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
                                               MmcDiscStructureFormat.DiscManufacturingInformation, 0, _dev.Timeout,
                                               out _);

                if (!sense)
                {
                    if (DMI.IsXbox(cmdBuf) ||
                        DMI.IsXbox360(cmdBuf))
                    {
                        if (DMI.IsXbox(cmdBuf))
                        {
                            dskType = MediaType.XGD;
                        }
                        else if (DMI.IsXbox360(cmdBuf))
                        {
                            dskType = MediaType.XGD2;

                            // All XGD3 all have the same number of blocks
                            if (blocks + 1 == 25063 ||      // Locked (or non compatible drive)
                                blocks + 1 == 4229664 ||    // Xtreme unlock
                                blocks + 1 == 4246304)      // Wxripper unlock
                            {
                                dskType = MediaType.XGD3;
                            }
                        }

                        isXbox = true;

                        sense = _dev.ScsiInquiry(out byte[] inqBuf, out _);

                        if (sense ||
                            !Inquiry.Decode(inqBuf).HasValue ||
                            (Inquiry.Decode(inqBuf).HasValue&& !Inquiry.Decode(inqBuf).Value.KreonPresent))
                        {
                            _dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");

                            StoppingErrorMessage?.
                            Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware.");

                            if (!_force)
                            {
                                return;
                            }

                            isXbox = false;
                        }

                        if (_dumpRaw && !_force)
                        {
                            StoppingErrorMessage?.
                            Invoke("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");

                            // TODO: Exit more gracefully
                            return;
                        }
                    }

                    if (cmdBuf.Length == 2052)
                    {
                        tmpBuf = new byte[cmdBuf.Length - 4];
                        Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
                        mediaTags.Add(MediaTagType.DVD_DMI, tmpBuf);
                    }
                }

                break;
            }
            #endregion Nintendo

            #region All DVD and HD DVD types
            #endregion All DVD and HD DVD types

            #region DVD-ROM
            if (dskType == MediaType.DVDDownload ||
                dskType == MediaType.DVDROM)
            {
                _dumpLog.WriteLine("Reading Lead-in Copyright Information.");

                sense = _dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0,
                                               MmcDiscStructureFormat.CopyrightInformation, 0, _dev.Timeout, out _);

                if (!sense)
                {
                    if (CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
                    {
                        tmpBuf = new byte[cmdBuf.Length - 4];
                        Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
                        mediaTags.Add(MediaTagType.DVD_CMI, tmpBuf);

                        CSS_CPRM.LeadInCopyright?cmi = CSS_CPRM.DecodeLeadInCopyright(cmdBuf);

                        if (cmi !.Value.CopyrightType == CopyrightType.NoProtection)
                        {
                            UpdateStatus?.Invoke("Drive reports no copy protection on disc.");
                        }
                        else
                        {
                            if (!Settings.Settings.Current.EnableDecryption)
                            {
                                UpdateStatus?.Invoke("Drive reports the disc uses copy protection. " +
                                                     "The dump will be incorrect unless decryption is enabled.");
                            }
                            else
                            {
                                if (cmi !.Value.CopyrightType == CopyrightType.CSS)
                                {
                                    UpdateStatus?.Invoke("Drive reports disc uses CSS copy protection.");

                                    dvdDecrypt = new DVDDecryption(_dev);

                                    sense = dvdDecrypt.ReadBusKey(out cmdBuf, out _,
                                                                  CSS_CPRM.DecodeLeadInCopyright(cmdBuf) !.Value.
                                                                  CopyrightType, _dev.Timeout, out _);

                                    if (!sense)
                                    {
                                        byte[] busKey = cmdBuf;

                                        UpdateStatus?.Invoke("Reading disc key.");
                                        sense = dvdDecrypt.ReadDiscKey(out cmdBuf, out _, _dev.Timeout, out _);

                                        if (!sense)
                                        {
                                            CSS_CPRM.DiscKey?decodedDiscKey = CSS.DecodeDiscKey(cmdBuf, busKey);

                                            sense = dvdDecrypt.ReadAsf(out cmdBuf, out _,
                                                                       DvdCssKeyClass.DvdCssCppmOrCprm, _dev.Timeout,
                                                                       out _);

                                            if (!sense)
                                            {
                                                if (cmdBuf[7] == 1)
                                                {
                                                    UpdateStatus?.Invoke("Disc and drive authentication succeeded.");

                                                    sense = dvdDecrypt.ReadRpc(out cmdBuf, out _,
                                                                               DvdCssKeyClass.DvdCssCppmOrCprm,
                                                                               _dev.Timeout, out _);

                                                    if (!sense)
                                                    {
                                                        CSS_CPRM.RegionalPlaybackControlState?rpc =
                                                            CSS_CPRM.DecodeRegionalPlaybackControlState(cmdBuf);

                                                        if (rpc.HasValue)
                                                        {
                                                            UpdateStatus?.Invoke(CSS.CheckRegion(rpc.Value, cmi.Value)
                                                                ? "Disc and drive regions match."
                                                                : "Disc and drive regions do not match. The dump will be incorrect");
                                                        }
                                                    }

                                                    if (decodedDiscKey.HasValue)
                                                    {
                                                        mediaTags.Add(MediaTagType.DVD_DiscKey,
                                                                      decodedDiscKey.Value.Key);

                                                        UpdateStatus?.Invoke("Decrypting disc key.");

                                                        CSS.DecryptDiscKey(decodedDiscKey.Value.Key,
                                                                           out byte[] discKey);

                                                        if (discKey != null)
                                                        {
                                                            UpdateStatus?.Invoke("Decryption of disc key succeeded.");
                                                            mediaTags.Add(MediaTagType.DVD_DiscKey_Decrypted, discKey);
                                                        }
                                                        else
                                                        {
                                                            UpdateStatus?.Invoke("Decryption of disc key failed.");
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    UpdateStatus?.
                                    Invoke($"Drive reports disc uses {CSS_CPRM.DecodeLeadInCopyright(cmdBuf)!.Value.CopyrightType.ToString()} copy protection. " +
                                           "This is not yet supported and the dump will be incorrect.");
                                }
                            }
                        }
示例#6
0
        public static byte[] Encode(Inquiry?inq)
        {
            if (inq is null)
            {
                return(null);
            }

            Inquiry decoded = inq.Value;

            byte[] buffer = new byte[512];
            byte   length = 0;

            buffer[0]  = (byte)(decoded.PeripheralQualifier << 5);
            buffer[0] += decoded.PeripheralDeviceType;

            if (decoded.RMB)
            {
                buffer[1] = 0x80;
            }

            buffer[1] += decoded.DeviceTypeModifier;

            buffer[2]  = (byte)(decoded.ISOVersion << 6);
            buffer[2] += (byte)(decoded.ECMAVersion << 3);
            buffer[2] += decoded.ANSIVersion;

            if (decoded.AERC)
            {
                buffer[3] = 0x80;
            }

            if (decoded.TrmTsk)
            {
                buffer[3] += 0x40;
            }

            if (decoded.NormACA)
            {
                buffer[3] += 0x20;
            }

            if (decoded.HiSup)
            {
                buffer[3] += 0x10;
            }

            buffer[3] += decoded.ResponseDataFormat;

            if (decoded.AdditionalLength > 0)
            {
                length    = 5;
                buffer[4] = decoded.AdditionalLength;
            }

            if (decoded.SCCS ||
                decoded.ACC ||
                decoded.TPGS > 0 ||
                decoded.ThreePC ||
                decoded.Reserved2 > 0 ||
                decoded.Protect)
            {
                length = 6;

                if (decoded.SCCS)
                {
                    buffer[5] = 0x80;
                }

                if (decoded.ACC)
                {
                    buffer[5] += 0x40;
                }

                buffer[5] += (byte)(decoded.TPGS << 4);

                if (decoded.ThreePC)
                {
                    buffer[5] += 0x08;
                }

                buffer[5] += (byte)(decoded.Reserved2 << 1);

                if (decoded.Protect)
                {
                    buffer[5] += 0x01;
                }
            }

            if (decoded.BQue ||
                decoded.EncServ ||
                decoded.VS1 ||
                decoded.MultiP ||
                decoded.MChngr ||
                decoded.ACKREQQ ||
                decoded.Addr32 ||
                decoded.Addr16)
            {
                length = 7;

                if (decoded.BQue)
                {
                    buffer[6] = 0x80;
                }

                if (decoded.EncServ)
                {
                    buffer[6] += 0x40;
                }

                if (decoded.VS1)
                {
                    buffer[6] += 0x20;
                }

                if (decoded.MultiP)
                {
                    buffer[6] += 0x10;
                }

                if (decoded.MChngr)
                {
                    buffer[6] += 0x08;
                }

                if (decoded.ACKREQQ)
                {
                    buffer[6] += 0x04;
                }

                if (decoded.Addr32)
                {
                    buffer[6] += 0x02;
                }

                if (decoded.Addr16)
                {
                    buffer[6] += 0x01;
                }
            }

            if (decoded.RelAddr ||
                decoded.WBus32 ||
                decoded.WBus16 ||
                decoded.Sync ||
                decoded.Linked ||
                decoded.TranDis ||
                decoded.CmdQue ||
                decoded.SftRe)

            {
                length = 8;

                if (decoded.RelAddr)
                {
                    buffer[7] = 0x80;
                }

                if (decoded.WBus32)
                {
                    buffer[7] += 0x40;
                }

                if (decoded.WBus16)
                {
                    buffer[7] += 0x20;
                }

                if (decoded.Sync)
                {
                    buffer[7] += 0x10;
                }

                if (decoded.Linked)
                {
                    buffer[7] += 0x08;
                }

                if (decoded.TranDis)
                {
                    buffer[7] += 0x04;
                }

                if (decoded.CmdQue)
                {
                    buffer[7] += 0x02;
                }

                if (decoded.SftRe)
                {
                    buffer[7] += 0x01;
                }
            }

            if (decoded.VendorIdentification != null)
            {
                length = 16;

                Array.Copy(decoded.VendorIdentification, 0, buffer, 8,
                           decoded.VendorIdentification.Length >= 8 ? 8 : decoded.VendorIdentification.Length);
            }

            if (decoded.ProductIdentification != null)
            {
                length = 32;

                Array.Copy(decoded.ProductIdentification, 0, buffer, 16,
                           decoded.ProductIdentification.Length >= 16 ? 16 : decoded.ProductIdentification.Length);
            }

            if (decoded.ProductRevisionLevel != null)
            {
                length = 36;

                Array.Copy(decoded.ProductRevisionLevel, 0, buffer, 32,
                           decoded.ProductRevisionLevel.Length >= 4 ? 4 : decoded.ProductRevisionLevel.Length);
            }

            if (decoded.Seagate_DriveSerialNumber != null)
            {
                length = 44;
                Array.Copy(decoded.Seagate_DriveSerialNumber, 0, buffer, 36, 8);
            }

            if (decoded.KreonIdentifier != null &&
                decoded.KreonVersion != null)
            {
                length = 46;
                Array.Copy(decoded.KreonIdentifier, 0, buffer, 36, 5);
                buffer[41] = decoded.KreonSpace;
                Array.Copy(decoded.KreonVersion, 0, buffer, 42, 5);
            }

            if (decoded.HP_WORM ||
                decoded.HP_WORMVersion > 0 ||
                decoded.HP_OBDR != null)
            {
                length = 49;

                if (decoded.HP_WORM)
                {
                    buffer[40] = 0x01;
                }

                buffer[40] += (byte)(decoded.HP_WORMVersion << 1);
                Array.Copy(decoded.HP_OBDR, 0, buffer, 43, 6);
            }

            if (decoded.IsHiMD)
            {
                length = 56;
                Array.Copy(HiMDSignatureContents, 0, buffer, 36, 8);

                if (decoded.HiMDSpecific != null)
                {
                    Array.Copy(decoded.HiMDSpecific, 0, buffer, 44, 12);
                }
            }

            if (decoded.VendorSpecific != null &&
                !decoded.IsHiMD)
            {
                length = 56;
                Array.Copy(decoded.VendorSpecific, 0, buffer, 36, 20);
            }

            if (decoded.Reserved3 > 0 ||
                decoded.Clocking > 0 ||
                decoded.QAS ||
                decoded.IUS)
            {
                length      = 57;
                buffer[56]  = (byte)(decoded.Reserved3 << 4);
                buffer[56] += (byte)(decoded.Clocking << 2);

                if (decoded.QAS)
                {
                    buffer[56] += 0x02;
                }

                if (decoded.IUS)
                {
                    buffer[56] += 0x01;
                }
            }

            if (decoded.Reserved4 != 0)
            {
                length     = 58;
                buffer[57] = decoded.Reserved4;
            }

            if (decoded.VersionDescriptors != null)
            {
                length = (byte)(58 + (decoded.VersionDescriptors.Length * 2));

                for (int i = 0; i < decoded.VersionDescriptors.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes(decoded.VersionDescriptors[i]), 0, buffer, 56 + (i * 2), 2);
                }
            }

            if (decoded.Reserved5 != null)
            {
                length = (byte)(74 + decoded.Reserved5.Length);
                Array.Copy(decoded.Reserved5, 0, buffer, 74, decoded.Reserved5.Length);
            }

            if (decoded.VendorSpecific2 != null)
            {
                length = (byte)(96 + decoded.VendorSpecific2.Length);
                Array.Copy(decoded.VendorSpecific2, 0, buffer, 96, decoded.VendorSpecific2.Length);
            }

            if (decoded.Seagate_Copyright != null)
            {
                length = 144;
                Array.Copy(decoded.Seagate_Copyright, 0, buffer, 96, 48);
            }

            if (decoded.Seagate_ServoPROMPartNo != null)
            {
                length = 148;
                Array.Copy(decoded.Seagate_ServoPROMPartNo, 0, buffer, 144, 4);
            }

            buffer[4] = length;
            byte[] dest = new byte[length];
            Array.Copy(buffer, 0, dest, 0, length);

            return(dest);
        }
示例#7
0
        public static Inquiry?Decode(byte[] SCSIInquiryResponse)
        {
            if (SCSIInquiryResponse == null)
            {
                return(null);
            }

            if (SCSIInquiryResponse.Length < 36 &&
                SCSIInquiryResponse.Length != 5)
            {
                AaruConsole.DebugWriteLine("SCSI INQUIRY decoder",
                                           "INQUIRY response is {0} bytes, less than minimum of 36 bytes, decoded data can be incorrect, not decoding.",
                                           SCSIInquiryResponse.Length);

                return(null);
            }

            if (SCSIInquiryResponse.Length < SCSIInquiryResponse[4] + 4 &&
                SCSIInquiryResponse.Length != SCSIInquiryResponse[4])
            {
                AaruConsole.DebugWriteLine("SCSI INQUIRY decoder",
                                           "INQUIRY response length ({0} bytes) is different than specified in length field ({1} bytes), decoded data can be incorrect, not decoding.",
                                           SCSIInquiryResponse.Length, SCSIInquiryResponse[4] + 4);

                return(null);
            }

            var decoded = new Inquiry();

            if (SCSIInquiryResponse.Length >= 1)
            {
                decoded.PeripheralQualifier  = (byte)((SCSIInquiryResponse[0] & 0xE0) >> 5);
                decoded.PeripheralDeviceType = (byte)(SCSIInquiryResponse[0] & 0x1F);
            }

            if (SCSIInquiryResponse.Length >= 2)
            {
                decoded.RMB = Convert.ToBoolean(SCSIInquiryResponse[1] & 0x80);
                decoded.DeviceTypeModifier = (byte)(SCSIInquiryResponse[1] & 0x7F);
            }

            if (SCSIInquiryResponse.Length >= 3)
            {
                decoded.ISOVersion  = (byte)((SCSIInquiryResponse[2] & 0xC0) >> 6);
                decoded.ECMAVersion = (byte)((SCSIInquiryResponse[2] & 0x38) >> 3);
                decoded.ANSIVersion = (byte)(SCSIInquiryResponse[2] & 0x07);
            }

            if (SCSIInquiryResponse.Length >= 4)
            {
                decoded.AERC               = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x80);
                decoded.TrmTsk             = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x40);
                decoded.NormACA            = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x20);
                decoded.HiSup              = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x10);
                decoded.ResponseDataFormat = (byte)(SCSIInquiryResponse[3] & 0x07);
            }

            if (SCSIInquiryResponse.Length >= 5)
            {
                decoded.AdditionalLength = SCSIInquiryResponse[4];
            }

            if (SCSIInquiryResponse.Length >= 6)
            {
                decoded.SCCS      = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x80);
                decoded.ACC       = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x40);
                decoded.TPGS      = (byte)((SCSIInquiryResponse[5] & 0x30) >> 4);
                decoded.ThreePC   = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x08);
                decoded.Reserved2 = (byte)((SCSIInquiryResponse[5] & 0x06) >> 1);
                decoded.Protect   = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x01);
            }

            if (SCSIInquiryResponse.Length >= 7)
            {
                decoded.BQue    = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x80);
                decoded.EncServ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x40);
                decoded.VS1     = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x20);
                decoded.MultiP  = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x10);
                decoded.MChngr  = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x08);
                decoded.ACKREQQ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x04);
                decoded.Addr32  = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x02);
                decoded.Addr16  = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x01);
            }

            if (SCSIInquiryResponse.Length >= 8)
            {
                decoded.RelAddr = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x80);
                decoded.WBus32  = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x40);
                decoded.WBus16  = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x20);
                decoded.Sync    = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x10);
                decoded.Linked  = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x08);
                decoded.TranDis = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x04);
                decoded.CmdQue  = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x02);
                decoded.SftRe   = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x01);
            }

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

            if (SCSIInquiryResponse.Length >= 32)
            {
                decoded.ProductIdentification = new byte[16];
                Array.Copy(SCSIInquiryResponse, 16, decoded.ProductIdentification, 0, 16);
            }

            if (SCSIInquiryResponse.Length >= 36)
            {
                decoded.ProductRevisionLevel = new byte[4];
                Array.Copy(SCSIInquiryResponse, 32, decoded.ProductRevisionLevel, 0, 4);
            }

            if (SCSIInquiryResponse.Length >= 44)
            {
                // Seagate 1
                decoded.SeagatePresent            = true;
                decoded.Seagate_DriveSerialNumber = new byte[8];
                Array.Copy(SCSIInquiryResponse, 36, decoded.Seagate_DriveSerialNumber, 0, 8);

                // Hi-MD
                decoded.HiMDSignature = new byte[8];
                Array.Copy(SCSIInquiryResponse, 36, decoded.HiMDSignature, 0, 8);
                decoded.IsHiMD = HiMDSignatureContents.SequenceEqual(decoded.HiMDSignature);
            }

            if (SCSIInquiryResponse.Length >= 46)
            {
                // Kreon
                decoded.KreonIdentifier = new byte[5];
                Array.Copy(SCSIInquiryResponse, 36, decoded.KreonIdentifier, 0, 5);
                decoded.KreonSpace   = SCSIInquiryResponse[41];
                decoded.KreonVersion = new byte[5];
                Array.Copy(SCSIInquiryResponse, 42, decoded.KreonVersion, 0, 5);

                if (decoded.KreonSpace == 0x20 &&
                    decoded.KreonIdentifier.SequenceEqual(new byte[]
                {
                    0x4B, 0x52, 0x45, 0x4F, 0x4E
                }))
                {
                    decoded.KreonPresent = true;
                }
            }

            if (SCSIInquiryResponse.Length >= 49)
            {
                // HP
                decoded.HPPresent      = true;
                decoded.HP_WORM       |= (SCSIInquiryResponse[40] & 0x01) == 0x01;
                decoded.HP_WORMVersion = (byte)((SCSIInquiryResponse[40] & 0x7F) >> 1);
                decoded.HP_OBDR        = new byte[6];
                Array.Copy(SCSIInquiryResponse, 43, decoded.HP_OBDR, 0, 6);
            }

            if (SCSIInquiryResponse.Length >= 56)
            {
                if (decoded.IsHiMD)
                {
                    decoded.HiMDSpecific = new byte[12];
                    Array.Copy(SCSIInquiryResponse, 44, decoded.HiMDSpecific, 0, 12);
                }
                else
                {
                    decoded.VendorSpecific = new byte[20];
                    Array.Copy(SCSIInquiryResponse, 36, decoded.VendorSpecific, 0, 20);
                }

                // Quantum
                decoded.QuantumPresent                  = true;
                decoded.Qt_ProductFamily                = (byte)((SCSIInquiryResponse[36] & 0xF0) >> 4);
                decoded.Qt_ReleasedFirmware             = (byte)(SCSIInquiryResponse[36] & 0x0F);
                decoded.Qt_FirmwareMajorVersion         = SCSIInquiryResponse[37];
                decoded.Qt_FirmwareMinorVersion         = SCSIInquiryResponse[38];
                decoded.Qt_EEPROMFormatMajorVersion     = SCSIInquiryResponse[39];
                decoded.Qt_EEPROMFormatMinorVersion     = SCSIInquiryResponse[40];
                decoded.Qt_FirmwarePersonality          = SCSIInquiryResponse[41];
                decoded.Qt_FirmwareSubPersonality       = SCSIInquiryResponse[42];
                decoded.Qt_TapeDirectoryFormatVersion   = SCSIInquiryResponse[43];
                decoded.Qt_ControllerHardwareVersion    = SCSIInquiryResponse[44];
                decoded.Qt_DriveEEPROMVersion           = SCSIInquiryResponse[45];
                decoded.Qt_DriveHardwareVersion         = SCSIInquiryResponse[46];
                decoded.Qt_MediaLoaderFirmwareVersion   = SCSIInquiryResponse[47];
                decoded.Qt_MediaLoaderHardwareVersion   = SCSIInquiryResponse[48];
                decoded.Qt_MediaLoaderMechanicalVersion = SCSIInquiryResponse[49];
                decoded.Qt_MediaLoaderPresent           = SCSIInquiryResponse[50] > 0;
                decoded.Qt_LibraryPresent               = SCSIInquiryResponse[51] > 0;
                decoded.Qt_ModuleRevision               = new byte[4];
                Array.Copy(SCSIInquiryResponse, 52, decoded.Qt_ModuleRevision, 0, 4);

                // IBM
                decoded.IBMPresent           = true;
                decoded.IBM_AutDis          |= (SCSIInquiryResponse[36] & 0x01) == 0x01;
                decoded.IBM_PerformanceLimit = SCSIInquiryResponse[37];
                decoded.IBM_OEMSpecific      = SCSIInquiryResponse[41];
            }

            if (SCSIInquiryResponse.Length >= 57)
            {
                decoded.Reserved3 = (byte)((SCSIInquiryResponse[56] & 0xF0) >> 4);
                decoded.Clocking  = (byte)((SCSIInquiryResponse[56] & 0x0C) >> 2);
                decoded.QAS       = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x02);
                decoded.IUS       = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x01);
            }

            if (SCSIInquiryResponse.Length >= 58)
            {
                decoded.Reserved4 = SCSIInquiryResponse[57];
            }

            if (SCSIInquiryResponse.Length >= 60)
            {
                int descriptorsNo;

                if (SCSIInquiryResponse.Length >= 74)
                {
                    descriptorsNo = 8;
                }
                else
                {
                    descriptorsNo = (SCSIInquiryResponse.Length - 58) / 2;
                }

                decoded.VersionDescriptors = new ushort[descriptorsNo];

                for (int i = 0; i < descriptorsNo; i++)
                {
                    decoded.VersionDescriptors[i] = BitConverter.ToUInt16(SCSIInquiryResponse, 58 + (i * 2));
                }
            }

            if (SCSIInquiryResponse.Length >= 75 &&
                SCSIInquiryResponse.Length < 96)
            {
                decoded.Reserved5 = new byte[SCSIInquiryResponse.Length - 74];
                Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 74);
            }

            if (SCSIInquiryResponse.Length >= 96)
            {
                decoded.Reserved5 = new byte[22];
                Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, 22);
            }

            if (SCSIInquiryResponse.Length > 96)
            {
                decoded.VendorSpecific2 = new byte[SCSIInquiryResponse.Length - 96];
                Array.Copy(SCSIInquiryResponse, 96, decoded.VendorSpecific2, 0, SCSIInquiryResponse.Length - 96);
            }

            if (SCSIInquiryResponse.Length >= 144)
            {
                // Seagate 2
                decoded.Seagate2Present   = true;
                decoded.Seagate_Copyright = new byte[48];
                Array.Copy(SCSIInquiryResponse, 96, decoded.Seagate_Copyright, 0, 48);
            }

            if (SCSIInquiryResponse.Length < 148)
            {
                return(decoded);
            }

            // Seagate 2
            decoded.Seagate3Present         = true;
            decoded.Seagate_ServoPROMPartNo = new byte[4];
            Array.Copy(SCSIInquiryResponse, 144, decoded.Seagate_ServoPROMPartNo, 0, 4);

            return(decoded);
        }
        public pnlImageInfo(string imagePath, IFilter filter, IMediaImage imageFormat)
        {
            this.imagePath   = imagePath;
            this.filter      = filter;
            this.imageFormat = imageFormat;
            XamlReader.Load(this);

            Stream logo =
                ResourceHandler.GetResourceStream($"Aaru.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.svg");

            /*            if(logo != null)
             *          {
             *              svgMediaLogo.SvgStream = logo;
             *              svgMediaLogo.Visible   = true;
             *          }
             *          else
             *          {*/
            logo = ResourceHandler.GetResourceStream($"Aaru.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.png");

            if (logo != null)
            {
                imgMediaLogo.Image   = new Bitmap(logo);
                imgMediaLogo.Visible = true;
            }

            //}

            lblImagePath.Text   = $"Path: {imagePath}";
            lblFilter.Text      = $"Filter: {filter.Name}";
            lblImageFormat.Text = $"Image format identified by {imageFormat.Name} ({imageFormat.Id}).";

            lblImageFormat.Text = !string.IsNullOrWhiteSpace(imageFormat.Info.Version)
                                      ? $"Format: {imageFormat.Format} version {imageFormat.Info.Version}"
                                      : $"Format: {imageFormat.Format}";

            lblImageSize.Text = $"Image without headers is {imageFormat.Info.ImageSize} bytes long";

            lblSectors.Text =
                $"Contains a media of {imageFormat.Info.Sectors} sectors with a maximum sector size of {imageFormat.Info.SectorSize} bytes (if all sectors are of the same size this would be {imageFormat.Info.Sectors * imageFormat.Info.SectorSize} bytes)";

            lblMediaType.Text =
                $"Contains a media of type {imageFormat.Info.MediaType} and XML type {imageFormat.Info.XmlMediaType}";

            lblHasPartitions.Text = $"{(imageFormat.Info.HasPartitions ? "Has" : "Doesn't have")} partitions";
            lblHasSessions.Text   = $"{(imageFormat.Info.HasSessions ? "Has" : "Doesn't have")} sessions";

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
            {
                lblApplication.Visible = true;

                lblApplication.Text = !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion)
                                          ? $"Was created with {imageFormat.Info.Application} version {imageFormat.Info.ApplicationVersion}"
                                          : $"Was created with {imageFormat.Info.Application}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
            {
                lblCreator.Visible = true;
                lblCreator.Text    = $"Created by: {imageFormat.Info.Creator}";
            }

            if (imageFormat.Info.CreationTime != DateTime.MinValue)
            {
                lblCreationTime.Visible = true;
                lblCreationTime.Text    = $"Created on {imageFormat.Info.CreationTime}";
            }

            if (imageFormat.Info.LastModificationTime != DateTime.MinValue)
            {
                lblLastModificationTime.Visible = true;
                lblLastModificationTime.Text    = $"Last modified on {imageFormat.Info.LastModificationTime}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.Comments))
            {
                grpComments.Visible = true;
                txtComments.Text    = imageFormat.Info.Comments;
            }

            if (imageFormat.Info.MediaSequence != 0 &&
                imageFormat.Info.LastMediaSequence != 0)
            {
                lblMediaSequence.Visible = true;

                lblMediaSequence.Text =
                    $"Media is number {imageFormat.Info.MediaSequence} on a set of {imageFormat.Info.LastMediaSequence} medias";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
            {
                lblMediaTitle.Visible = true;
                lblMediaTitle.Text    = $"Media title: {imageFormat.Info.MediaTitle}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
            {
                lblMediaManufacturer.Visible = true;
                lblMediaManufacturer.Text    = $"Media manufacturer: {imageFormat.Info.MediaManufacturer}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
            {
                lblMediaModel.Visible = true;
                lblMediaModel.Text    = $"Media model: {imageFormat.Info.MediaModel}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
            {
                lblMediaSerialNumber.Visible = true;
                lblMediaSerialNumber.Text    = $"Media serial number: {imageFormat.Info.MediaSerialNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
            {
                lblMediaBarcode.Visible = true;
                lblMediaBarcode.Text    = $"Media barcode: {imageFormat.Info.MediaBarcode}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
            {
                lblMediaPartNumber.Visible = true;
                lblMediaPartNumber.Text    = $"Media part number: {imageFormat.Info.MediaPartNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
            {
                lblDriveManufacturer.Visible = true;
                lblDriveManufacturer.Text    = $"Drive manufacturer: {imageFormat.Info.DriveManufacturer}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
            {
                lblDriveModel.Visible = true;
                lblDriveModel.Text    = $"Drive model: {imageFormat.Info.DriveModel}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
            {
                lblDriveSerialNumber.Visible = true;
                lblDriveSerialNumber.Text    = $"Drive serial number: {imageFormat.Info.DriveSerialNumber}";
            }

            if (!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
            {
                lblDriveFirmwareRevision.Visible = true;
                lblDriveFirmwareRevision.Text    = $"Drive firmware info: {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))
            {
                lblMediaGeometry.Visible = true;

                lblMediaGeometry.Text =
                    $"Media geometry: {imageFormat.Info.Cylinders} cylinders, {imageFormat.Info.Heads} heads, {imageFormat.Info.SectorsPerTrack} sectors per track";
            }

            grpMediaInfo.Visible = lblMediaSequence.Visible || lblMediaTitle.Visible ||
                                   lblMediaManufacturer.Visible ||
                                   lblMediaModel.Visible || lblMediaSerialNumber.Visible ||
                                   lblMediaBarcode.Visible ||
                                   lblMediaPartNumber.Visible;

            grpDriveInfo.Visible = lblDriveManufacturer.Visible || lblDriveModel.Visible ||
                                   lblDriveSerialNumber.Visible || lblDriveFirmwareRevision.Visible ||
                                   lblMediaGeometry.Visible;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Count > 0)
            {
                var mediaTagList = new TreeGridItemCollection();

                treeMediaTags.Columns.Add(new GridColumn
                {
                    HeaderText = "Tag", DataCell = new TextBoxCell(0)
                });

                treeMediaTags.AllowMultipleSelection = false;
                treeMediaTags.ShowHeader             = false;
                treeMediaTags.DataStore = mediaTagList;

                foreach (MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
                {
                    mediaTagList.Add(new TreeGridItem
                    {
                        Values = new object[]
                        {
                            tag.ToString()
                        }
                    });
                }

                grpMediaTags.Visible = true;
            }

            if (imageFormat.Info.ReadableSectorTags != null &&
                imageFormat.Info.ReadableSectorTags.Count > 0)
            {
                var sectorTagList = new TreeGridItemCollection();

                treeSectorTags.Columns.Add(new GridColumn
                {
                    HeaderText = "Tag", DataCell = new TextBoxCell(0)
                });

                treeSectorTags.AllowMultipleSelection = false;
                treeSectorTags.ShowHeader             = false;
                treeSectorTags.DataStore = sectorTagList;

                foreach (SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
                {
                    sectorTagList.Add(new TreeGridItem
                    {
                        Values = new object[]
                        {
                            tag.ToString()
                        }
                    });
                }

                grpSectorTags.Visible = true;
            }

            PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;

            byte[]  scsiInquiryData = null;
            Inquiry?scsiInquiry     = null;

            Modes.DecodedMode?scsiMode        = null;
            byte[]            scsiModeSense6  = null;
            byte[]            scsiModeSense10 = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_INQUIRY))
            {
                scsiInquiryData = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);

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

                scsiInquiry = Inquiry.Decode(scsiInquiryData);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_6))
            {
                scsiModeSense6 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6);
                scsiMode       = Modes.DecodeMode6(scsiModeSense6, scsiDeviceType);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SCSI_MODESENSE_10))
            {
                scsiModeSense10 = imageFormat.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10);
                scsiMode        = Modes.DecodeMode10(scsiModeSense10, scsiDeviceType);
            }

            var tabScsiInfo = new tabScsiInfo();

            tabScsiInfo.LoadData(scsiInquiryData, scsiInquiry, null, scsiMode, scsiDeviceType, scsiModeSense6,
                                 scsiModeSense10, null);

            tabInfos.Pages.Add(tabScsiInfo);

            byte[] ataIdentify   = null;
            byte[] atapiIdentify = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
            {
                ataIdentify = imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.ATAPI_IDENTIFY))
            {
                atapiIdentify = imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY);
            }

            var tabAtaInfo = new tabAtaInfo();

            tabAtaInfo.LoadData(ataIdentify, atapiIdentify, null);
            tabInfos.Pages.Add(tabAtaInfo);

            byte[]                toc                  = null;
            TOC.CDTOC?            decodedToc           = null;
            byte[]                fullToc              = null;
            FullTOC.CDFullTOC?    decodedFullToc       = null;
            byte[]                pma                  = null;
            byte[]                atip                 = null;
            ATIP.CDATIP?          decodedAtip          = null;
            byte[]                cdtext               = null;
            CDTextOnLeadIn.CDText?decodedCdText        = null;
            string                mediaCatalogueNumber = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TOC))
            {
                toc = imageFormat.ReadDiskTag(MediaTagType.CD_TOC);

                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;
                    }

                    decodedToc = TOC.Decode(toc);
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_FullTOC))
            {
                fullToc = imageFormat.ReadDiskTag(MediaTagType.CD_FullTOC);

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

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

                    decodedFullToc = FullTOC.Decode(fullToc);
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_PMA))
            {
                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;
                    }
                }
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_ATIP))
            {
                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;
                }

                decodedAtip = ATIP.Decode(atip);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_TEXT))
            {
                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;
                }

                decodedCdText = CDTextOnLeadIn.Decode(cdtext);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
            {
                byte[] mcn = imageFormat.ReadDiskTag(MediaTagType.CD_MCN);

                mediaCatalogueNumber = Encoding.UTF8.GetString(mcn);
            }

            var tabCompactDiscInfo = new tabCompactDiscInfo();

            tabCompactDiscInfo.LoadData(toc, atip, null, null, fullToc, pma, cdtext, decodedToc, decodedAtip, null,
                                        decodedFullToc, decodedCdText, null, mediaCatalogueNumber, null);

            tabInfos.Pages.Add(tabCompactDiscInfo);

            byte[] dvdPfi = null;
            byte[] dvdDmi = null;
            byte[] dvdCmi = null;
            byte[] hddvdCopyrightInformation = null;
            byte[] dvdBca = null;
            PFI.PhysicalFormatInformation?decodedPfi = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_PFI))
            {
                dvdPfi     = imageFormat.ReadDiskTag(MediaTagType.DVD_PFI);
                decodedPfi = PFI.Decode(dvdPfi);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_DMI))
            {
                dvdDmi = imageFormat.ReadDiskTag(MediaTagType.DVD_DMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_CMI))
            {
                dvdCmi = imageFormat.ReadDiskTag(MediaTagType.DVD_CMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_CPI))
            {
                hddvdCopyrightInformation = imageFormat.ReadDiskTag(MediaTagType.HDDVD_CPI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_BCA))
            {
                dvdBca = imageFormat.ReadDiskTag(MediaTagType.DVD_BCA);
            }

            var tabDvdInfo = new tabDvdInfo();

            tabDvdInfo.LoadData(imageFormat.Info.MediaType, dvdPfi, dvdDmi, dvdCmi, hddvdCopyrightInformation, dvdBca,
                                null, decodedPfi);

            tabInfos.Pages.Add(tabDvdInfo);

            byte[] dvdRamDds                     = null;
            byte[] dvdRamCartridgeStatus         = null;
            byte[] dvdRamSpareArea               = null;
            byte[] lastBorderOutRmd              = null;
            byte[] dvdPreRecordedInfo            = null;
            byte[] dvdrMediaIdentifier           = null;
            byte[] dvdrPhysicalInformation       = null;
            byte[] hddvdrMediumStatus            = null;
            byte[] dvdrLayerCapacity             = null;
            byte[] dvdrDlMiddleZoneStart         = null;
            byte[] dvdrDlJumpIntervalSize        = null;
            byte[] dvdrDlManualLayerJumpStartLba = null;
            byte[] dvdPlusAdip                   = null;
            byte[] dvdPlusDcb                    = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_DDS))
            {
                dvdRamDds = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_DDS);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_MediumStatus))
            {
                dvdRamCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_MediumStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDRAM_SpareArea))
            {
                dvdRamSpareArea = imageFormat.ReadDiskTag(MediaTagType.DVDRAM_SpareArea);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_RMD))
            {
                lastBorderOutRmd = imageFormat.ReadDiskTag(MediaTagType.DVDR_RMD);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PreRecordedInfo))
            {
                dvdPreRecordedInfo = imageFormat.ReadDiskTag(MediaTagType.DVDR_PreRecordedInfo);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_MediaIdentifier))
            {
                dvdrMediaIdentifier = imageFormat.ReadDiskTag(MediaTagType.DVDR_MediaIdentifier);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDR_PFI))
            {
                dvdrPhysicalInformation = imageFormat.ReadDiskTag(MediaTagType.DVDR_PFI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.HDDVD_MediumStatus))
            {
                hddvdrMediumStatus = imageFormat.ReadDiskTag(MediaTagType.HDDVD_MediumStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_LayerCapacity))
            {
                dvdrLayerCapacity = imageFormat.ReadDiskTag(MediaTagType.DVDDL_LayerCapacity);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_MiddleZoneAddress))
            {
                dvdrDlMiddleZoneStart = imageFormat.ReadDiskTag(MediaTagType.DVDDL_MiddleZoneAddress);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_JumpIntervalSize))
            {
                dvdrDlJumpIntervalSize = imageFormat.ReadDiskTag(MediaTagType.DVDDL_JumpIntervalSize);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVDDL_ManualLayerJumpLBA))
            {
                dvdrDlManualLayerJumpStartLba = imageFormat.ReadDiskTag(MediaTagType.DVDDL_ManualLayerJumpLBA);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DVD_ADIP))
            {
                dvdPlusAdip = imageFormat.ReadDiskTag(MediaTagType.DVD_ADIP);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.DCB))
            {
                dvdPlusDcb = imageFormat.ReadDiskTag(MediaTagType.DCB);
            }

            var tabDvdWritableInfo = new tabDvdWritableInfo();

            tabDvdWritableInfo.LoadData(imageFormat.Info.MediaType, dvdRamDds, dvdRamCartridgeStatus, dvdRamSpareArea,
                                        lastBorderOutRmd, dvdPreRecordedInfo, dvdrMediaIdentifier,
                                        dvdrPhysicalInformation, hddvdrMediumStatus, null, dvdrLayerCapacity,
                                        dvdrDlMiddleZoneStart, dvdrDlJumpIntervalSize, dvdrDlManualLayerJumpStartLba,
                                        null, dvdPlusAdip, dvdPlusDcb);

            tabInfos.Pages.Add(tabDvdWritableInfo);

            byte[] blurayBurstCuttingArea = null;
            byte[] blurayCartridgeStatus  = null;
            byte[] blurayDds                  = null;
            byte[] blurayDiscInformation      = null;
            byte[] blurayPowResources         = null;
            byte[] bluraySpareAreaInformation = null;
            byte[] blurayTrackResources       = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_BCA))
            {
                blurayBurstCuttingArea = imageFormat.ReadDiskTag(MediaTagType.BD_BCA);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_CartridgeStatus))
            {
                blurayCartridgeStatus = imageFormat.ReadDiskTag(MediaTagType.BD_CartridgeStatus);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DDS))
            {
                blurayDds = imageFormat.ReadDiskTag(MediaTagType.BD_DDS);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_DI))
            {
                blurayDiscInformation = imageFormat.ReadDiskTag(MediaTagType.BD_DI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_POWResourcesInformation))
            {
                blurayPowResources = imageFormat.ReadDiskTag(MediaTagType.MMC_POWResourcesInformation);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.BD_SpareArea))
            {
                bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.BD_SpareArea);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_TrackResourcesInformation))
            {
                bluraySpareAreaInformation = imageFormat.ReadDiskTag(MediaTagType.MMC_TrackResourcesInformation);
            }

            var tabBlurayInfo = new tabBlurayInfo();

            tabBlurayInfo.LoadData(blurayDiscInformation, blurayBurstCuttingArea, blurayDds, blurayCartridgeStatus,
                                   bluraySpareAreaInformation, blurayPowResources, blurayTrackResources, null, null);

            tabInfos.Pages.Add(tabBlurayInfo);

            byte[]            xboxDmi                   = null;
            byte[]            xboxSecuritySector        = null;
            SS.SecuritySector?decodedXboxSecuritySector = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_DMI))
            {
                xboxDmi = imageFormat.ReadDiskTag(MediaTagType.Xbox_DMI);
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.Xbox_SecuritySector))
            {
                xboxSecuritySector        = imageFormat.ReadDiskTag(MediaTagType.Xbox_SecuritySector);
                decodedXboxSecuritySector = SS.Decode(xboxSecuritySector);
            }

            var tabXboxInfo = new tabXboxInfo();

            tabXboxInfo.LoadData(null, xboxDmi, xboxSecuritySector, decodedXboxSecuritySector);
            tabInfos.Pages.Add(tabXboxInfo);

            byte[] pcmciaCis = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS))
            {
                pcmciaCis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS);
            }

            var tabPcmciaInfo = new tabPcmciaInfo();

            tabPcmciaInfo.LoadData(pcmciaCis);
            tabInfos.Pages.Add(tabPcmciaInfo);

            DeviceType deviceType = DeviceType.Unknown;

            byte[] cid         = null;
            byte[] csd         = null;
            byte[] ocr         = null;
            byte[] extendedCsd = null;
            byte[] scr         = null;

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CID))
            {
                cid        = imageFormat.ReadDiskTag(MediaTagType.SD_CID);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_CSD))
            {
                csd        = imageFormat.ReadDiskTag(MediaTagType.SD_CSD);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_OCR))
            {
                ocr        = imageFormat.ReadDiskTag(MediaTagType.SD_OCR);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.SD_SCR))
            {
                scr        = imageFormat.ReadDiskTag(MediaTagType.SD_SCR);
                deviceType = DeviceType.SecureDigital;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CID))
            {
                cid        = imageFormat.ReadDiskTag(MediaTagType.MMC_CID);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_CSD))
            {
                csd        = imageFormat.ReadDiskTag(MediaTagType.MMC_CSD);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_OCR))
            {
                ocr        = imageFormat.ReadDiskTag(MediaTagType.MMC_OCR);
                deviceType = DeviceType.MMC;
            }

            if (imageFormat.Info.ReadableMediaTags != null &&
                imageFormat.Info.ReadableMediaTags.Contains(MediaTagType.MMC_ExtendedCSD))
            {
                extendedCsd = imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD);
                deviceType  = DeviceType.MMC;
            }

            var tabSdMmcInfo = new tabSdMmcInfo();

            tabSdMmcInfo.LoadData(deviceType, cid, csd, ocr, extendedCsd, scr);
            tabInfos.Pages.Add(tabSdMmcInfo);

            if (imageFormat is IOpticalMediaImage opticalMediaImage)
            {
                try
                {
                    if (opticalMediaImage.Sessions != null &&
                        opticalMediaImage.Sessions.Count > 0)
                    {
                        var sessionList = new TreeGridItemCollection();

                        treeSessions.Columns.Add(new GridColumn
                        {
                            HeaderText = "Session", DataCell = new TextBoxCell(0)
                        });

                        treeSessions.Columns.Add(new GridColumn
                        {
                            HeaderText = "First track", DataCell = new TextBoxCell(1)
                        });

                        treeSessions.Columns.Add(new GridColumn
                        {
                            HeaderText = "Last track", DataCell = new TextBoxCell(2)
                        });

                        treeSessions.Columns.Add(new GridColumn
                        {
                            HeaderText = "Start", DataCell = new TextBoxCell(3)
                        });

                        treeSessions.Columns.Add(new GridColumn
                        {
                            HeaderText = "End", DataCell = new TextBoxCell(4)
                        });

                        treeSessions.AllowMultipleSelection = false;
                        treeSessions.ShowHeader             = true;
                        treeSessions.DataStore = sessionList;

                        foreach (Session session in opticalMediaImage.Sessions)
                        {
                            sessionList.Add(new TreeGridItem
                            {
                                Values = new object[]
                                {
                                    session.SessionSequence, session.StartTrack, session.EndTrack, session.StartSector,
                                    session.EndSector
                                }
                            });
                        }

                        tabSessions.Visible = true;
                    }
                }
                catch
                {
                    // ignored
                }

                try
                {
                    if (opticalMediaImage.Tracks != null &&
                        opticalMediaImage.Tracks.Count > 0)
                    {
                        var tracksList = new TreeGridItemCollection();

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Track", DataCell = new TextBoxCell(0)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Type", DataCell = new TextBoxCell(1)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Bps", DataCell = new TextBoxCell(2)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Raw bps", DataCell = new TextBoxCell(3)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Subchannel", DataCell = new TextBoxCell(4)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Pregap", DataCell = new TextBoxCell(5)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "Start", DataCell = new TextBoxCell(6)
                        });

                        treeTracks.Columns.Add(new GridColumn
                        {
                            HeaderText = "End", DataCell = new TextBoxCell(7)
                        });

                        treeTracks.AllowMultipleSelection = false;
                        treeTracks.ShowHeader             = true;
                        treeTracks.DataStore = tracksList;

                        foreach (Track track in opticalMediaImage.Tracks)
                        {
                            tracksList.Add(new TreeGridItem
                            {
                                Values = new object[]
                                {
                                    track.TrackSequence, track.TrackType, track.TrackBytesPerSector,
                                    track.TrackRawBytesPerSector, track.TrackSubchannelType, track.TrackPregap,
                                    track.TrackStartSector, track.TrackEndSector
                                }
                            });
                        }

                        tabTracks.Visible = true;
                    }
                }
                catch
                {
                    // ignored
                }
            }

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

            var dumpHardwareList = new TreeGridItemCollection();

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Manufacturer", DataCell = new TextBoxCell(0)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Model", DataCell = new TextBoxCell(1)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Serial", DataCell = new TextBoxCell(2)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Software", DataCell = new TextBoxCell(3)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Version", DataCell = new TextBoxCell(4)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Operating system", DataCell = new TextBoxCell(5)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "Start", DataCell = new TextBoxCell(6)
            });

            treeDumpHardware.Columns.Add(new GridColumn
            {
                HeaderText = "End", DataCell = new TextBoxCell(7)
            });

            treeDumpHardware.AllowMultipleSelection = false;
            treeDumpHardware.ShowHeader             = true;
            treeDumpHardware.DataStore = dumpHardwareList;

            foreach (DumpHardwareType dump in imageFormat.DumpHardware)
            {
                foreach (ExtentType extent in dump.Extents)
                {
                    dumpHardwareList.Add(new TreeGridItem
                    {
                        Values = new object[]
                        {
                            dump.Manufacturer, dump.Model, dump.Serial, dump.Software.Name, dump.Software.Version,
                            dump.Software.OperatingSystem, extent.Start, extent.End
                        }
                    });
                }
            }

            tabDumpHardware.Visible = true;
        }