// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : Helpers.cs // Author(s) : Natalia Portillo // // Component : Disk image plugins. // // --[ Description ] ---------------------------------------------------------- // // Contains helpers for DiscImageChef format disk images. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2018 Natalia Portillo // ****************************************************************************/ using System; using System.Runtime.InteropServices; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SecureDigital; using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString; namespace DiscImageChef.DiscImages { public partial class DiscImageChef { /// /// Checks for media tags that may contain metadata and sets it up if not already set /// void SetMetadataFromTags() { // Search for SecureDigital CID if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid)) { CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid); if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer); if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName; if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; } // Search for MultiMediaCard CID if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid)) { Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid); if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer); if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName; if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; } // Search for SCSI INQUIRY if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry)) { Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry); if(nullableInquiry.HasValue) { Inquiry.SCSIInquiry inquiry = nullableInquiry.Value; if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim(); if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim(); if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim(); } } // Search for ATA or ATAPI IDENTIFY if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) && !mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return; Identify.IdentifyDevice? nullableIdentify = Decoders.ATA.Identify.Decode(ataIdentify); if(!nullableIdentify.HasValue) return; Identify.IdentifyDevice identify = nullableIdentify.Value; string[] separated = identify.Model.Split(' '); if(separated.Length == 1) if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[0]; else { if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = separated[0]; if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[separated.Length - 1]; } if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = identify.FirmwareRevision; if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = identify.SerialNumber; } // Get the CICM XML media type from DIC media type static XmlMediaType GetXmlMediaType(MediaType type) { switch(type) { case MediaType.CD: case MediaType.CDDA: case MediaType.CDG: case MediaType.CDEG: case MediaType.CDI: case MediaType.CDIREADY: case MediaType.CDROM: case MediaType.CDROMXA: case MediaType.CDPLUS: case MediaType.CDMO: case MediaType.CDR: case MediaType.CDRW: case MediaType.CDMRW: case MediaType.VCD: case MediaType.SVCD: case MediaType.PCD: case MediaType.SACD: case MediaType.DDCD: case MediaType.DDCDR: case MediaType.DDCDRW: case MediaType.DTSCD: case MediaType.CDMIDI: case MediaType.CDV: case MediaType.DVDROM: case MediaType.DVDR: case MediaType.DVDRW: case MediaType.DVDPR: case MediaType.DVDPRW: case MediaType.DVDPRWDL: case MediaType.DVDRDL: case MediaType.DVDPRDL: case MediaType.DVDRAM: case MediaType.DVDRWDL: case MediaType.DVDDownload: case MediaType.HDDVDROM: case MediaType.HDDVDRAM: case MediaType.HDDVDR: case MediaType.HDDVDRW: case MediaType.HDDVDRDL: case MediaType.HDDVDRWDL: case MediaType.BDROM: case MediaType.BDR: case MediaType.BDRE: case MediaType.BDRXL: case MediaType.BDREXL: case MediaType.EVD: case MediaType.FVD: case MediaType.HVD: case MediaType.CBHD: case MediaType.HDVMD: case MediaType.VCDHD: case MediaType.SVOD: case MediaType.FDDVD: case MediaType.LD: case MediaType.LDROM: case MediaType.LDROM2: case MediaType.LVROM: case MediaType.MegaLD: case MediaType.PS1CD: case MediaType.PS2CD: case MediaType.PS2DVD: case MediaType.PS3DVD: case MediaType.PS3BD: case MediaType.PS4BD: case MediaType.UMD: case MediaType.XGD: case MediaType.XGD2: case MediaType.XGD3: case MediaType.XGD4: case MediaType.MEGACD: case MediaType.SATURNCD: case MediaType.GDROM: case MediaType.GDR: case MediaType.SuperCDROM2: case MediaType.JaguarCD: case MediaType.ThreeDO: case MediaType.PCFX: case MediaType.NeoGeoCD: case MediaType.GOD: case MediaType.WOD: case MediaType.WUOD: case MediaType.CDTV: case MediaType.CD32: case MediaType.Nuon: case MediaType.Playdia: case MediaType.Pippin: return XmlMediaType.OpticalDisc; default: return XmlMediaType.BlockMedia; } } // Gets a DDT entry ulong GetDdtEntry(ulong sectorAddress) { if(inMemoryDdt) return userDataDdt[sectorAddress]; if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) return entry; long oldPosition = imageStream.Position; imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf(typeof(DdtHeader)); imageStream.Position += (long)(sectorAddress * sizeof(ulong)); byte[] temp = new byte[sizeof(ulong)]; imageStream.Read(temp, 0, sizeof(ulong)); imageStream.Position = oldPosition; entry = BitConverter.ToUInt64(temp, 0); if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) ddtEntryCache.Clear(); ddtEntryCache.Add(sectorAddress, entry); return entry; } // Sets a DDT entry void SetDdtEntry(ulong sectorAddress, ulong pointer) { if(inMemoryDdt) { userDataDdt[sectorAddress] = pointer; return; } long oldPosition = imageStream.Position; imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf(typeof(DdtHeader)); imageStream.Position += (long)(sectorAddress * sizeof(ulong)); imageStream.Write(BitConverter.GetBytes(pointer), 0, sizeof(ulong)); imageStream.Position = oldPosition; } // Converts between image data type and dic media tag type static MediaTagType GetMediaTagTypeForDataType(DataType type) { switch(type) { case DataType.CompactDiscPartialToc: return MediaTagType.CD_TOC; case DataType.CompactDiscSessionInfo: return MediaTagType.CD_SessionInfo; case DataType.CompactDiscToc: return MediaTagType.CD_FullTOC; case DataType.CompactDiscPma: return MediaTagType.CD_PMA; case DataType.CompactDiscAtip: return MediaTagType.CD_ATIP; case DataType.CompactDiscLeadInCdText: return MediaTagType.CD_TEXT; case DataType.DvdPfi: return MediaTagType.DVD_PFI; case DataType.DvdLeadInCmi: return MediaTagType.DVD_CMI; case DataType.DvdDiscKey: return MediaTagType.DVD_DiscKey; case DataType.DvdBca: return MediaTagType.DVD_BCA; case DataType.DvdDmi: return MediaTagType.DVD_DMI; case DataType.DvdMediaIdentifier: return MediaTagType.DVD_MediaIdentifier; case DataType.DvdMediaKeyBlock: return MediaTagType.DVD_MKB; case DataType.DvdRamDds: return MediaTagType.DVDRAM_DDS; case DataType.DvdRamMediumStatus: return MediaTagType.DVDRAM_MediumStatus; case DataType.DvdRamSpareArea: return MediaTagType.DVDRAM_SpareArea; case DataType.DvdRRmd: return MediaTagType.DVDR_RMD; case DataType.DvdRPrerecordedInfo: return MediaTagType.DVDR_PreRecordedInfo; case DataType.DvdRMediaIdentifier: return MediaTagType.DVDR_MediaIdentifier; case DataType.DvdRPfi: return MediaTagType.DVDR_PFI; case DataType.DvdAdip: return MediaTagType.DVD_ADIP; case DataType.HdDvdCpi: return MediaTagType.HDDVD_CPI; case DataType.HdDvdMediumStatus: return MediaTagType.HDDVD_MediumStatus; case DataType.DvdDlLayerCapacity: return MediaTagType.DVDDL_LayerCapacity; case DataType.DvdDlMiddleZoneAddress: return MediaTagType.DVDDL_MiddleZoneAddress; case DataType.DvdDlJumpIntervalSize: return MediaTagType.DVDDL_JumpIntervalSize; case DataType.DvdDlManualLayerJumpLba: return MediaTagType.DVDDL_ManualLayerJumpLBA; case DataType.BlurayDi: return MediaTagType.BD_DI; case DataType.BlurayBca: return MediaTagType.BD_BCA; case DataType.BlurayDds: return MediaTagType.BD_DDS; case DataType.BlurayCartridgeStatus: return MediaTagType.BD_CartridgeStatus; case DataType.BluraySpareArea: return MediaTagType.BD_SpareArea; case DataType.AacsVolumeIdentifier: return MediaTagType.AACS_VolumeIdentifier; case DataType.AacsSerialNumber: return MediaTagType.AACS_SerialNumber; case DataType.AacsMediaIdentifier: return MediaTagType.AACS_MediaIdentifier; case DataType.AacsMediaKeyBlock: return MediaTagType.AACS_MKB; case DataType.AacsDataKeys: return MediaTagType.AACS_DataKeys; case DataType.AacsLbaExtents: return MediaTagType.AACS_LBAExtents; case DataType.CprmMediaKeyBlock: return MediaTagType.AACS_CPRM_MKB; case DataType.HybridRecognizedLayers: return MediaTagType.Hybrid_RecognizedLayers; case DataType.ScsiMmcWriteProtection: return MediaTagType.MMC_WriteProtection; case DataType.ScsiMmcDiscInformation: return MediaTagType.MMC_DiscInformation; case DataType.ScsiMmcTrackResourcesInformation: return MediaTagType.MMC_TrackResourcesInformation; case DataType.ScsiMmcPowResourcesInformation: return MediaTagType.MMC_POWResourcesInformation; case DataType.ScsiInquiry: return MediaTagType.SCSI_INQUIRY; case DataType.ScsiModePage2A: return MediaTagType.SCSI_MODEPAGE_2A; case DataType.AtaIdentify: return MediaTagType.ATA_IDENTIFY; case DataType.AtapiIdentify: return MediaTagType.ATAPI_IDENTIFY; case DataType.PcmciaCis: return MediaTagType.PCMCIA_CIS; case DataType.SecureDigitalCid: return MediaTagType.SD_CID; case DataType.SecureDigitalCsd: return MediaTagType.SD_CSD; case DataType.SecureDigitalScr: return MediaTagType.SD_SCR; case DataType.SecureDigitalOcr: return MediaTagType.SD_OCR; case DataType.MultiMediaCardCid: return MediaTagType.MMC_CID; case DataType.MultiMediaCardCsd: return MediaTagType.MMC_CSD; case DataType.MultiMediaCardOcr: return MediaTagType.MMC_OCR; case DataType.MultiMediaCardExtendedCsd: return MediaTagType.MMC_ExtendedCSD; case DataType.XboxSecuritySector: return MediaTagType.Xbox_SecuritySector; case DataType.FloppyLeadOut: return MediaTagType.Floppy_LeadOut; case DataType.DvdDiscControlBlock: return MediaTagType.DCB; case DataType.CompactDiscLeadIn: return MediaTagType.CD_LeadIn; case DataType.CompactDiscLeadOut: return MediaTagType.CD_LeadOut; case DataType.ScsiModeSense6: return MediaTagType.SCSI_MODESENSE_6; case DataType.ScsiModeSense10: return MediaTagType.SCSI_MODESENSE_10; case DataType.UsbDescriptors: return MediaTagType.USB_Descriptors; case DataType.XboxDmi: return MediaTagType.Xbox_DMI; case DataType.XboxPfi: return MediaTagType.Xbox_PFI; case DataType.CompactDiscMediaCatalogueNumber: return MediaTagType.CD_MCN; default: throw new ArgumentOutOfRangeException(); } } // Converts between dic media tag type and image data type static DataType GetDataTypeForMediaTag(MediaTagType tag) { switch(tag) { case MediaTagType.CD_TOC: return DataType.CompactDiscPartialToc; case MediaTagType.CD_SessionInfo: return DataType.CompactDiscSessionInfo; case MediaTagType.CD_FullTOC: return DataType.CompactDiscToc; case MediaTagType.CD_PMA: return DataType.CompactDiscPma; case MediaTagType.CD_ATIP: return DataType.CompactDiscAtip; case MediaTagType.CD_TEXT: return DataType.CompactDiscLeadInCdText; case MediaTagType.DVD_PFI: return DataType.DvdPfi; case MediaTagType.DVD_CMI: return DataType.DvdLeadInCmi; case MediaTagType.DVD_DiscKey: return DataType.DvdDiscKey; case MediaTagType.DVD_BCA: return DataType.DvdBca; case MediaTagType.DVD_DMI: return DataType.DvdDmi; case MediaTagType.DVD_MediaIdentifier: return DataType.DvdMediaIdentifier; case MediaTagType.DVD_MKB: return DataType.DvdMediaKeyBlock; case MediaTagType.DVDRAM_DDS: return DataType.DvdRamDds; case MediaTagType.DVDRAM_MediumStatus: return DataType.DvdRamMediumStatus; case MediaTagType.DVDRAM_SpareArea: return DataType.DvdRamSpareArea; case MediaTagType.DVDR_RMD: return DataType.DvdRRmd; case MediaTagType.DVDR_PreRecordedInfo: return DataType.DvdRPrerecordedInfo; case MediaTagType.DVDR_MediaIdentifier: return DataType.DvdRMediaIdentifier; case MediaTagType.DVDR_PFI: return DataType.DvdRPfi; case MediaTagType.DVD_ADIP: return DataType.DvdAdip; case MediaTagType.HDDVD_CPI: return DataType.HdDvdCpi; case MediaTagType.HDDVD_MediumStatus: return DataType.HdDvdMediumStatus; case MediaTagType.DVDDL_LayerCapacity: return DataType.DvdDlLayerCapacity; case MediaTagType.DVDDL_MiddleZoneAddress: return DataType.DvdDlMiddleZoneAddress; case MediaTagType.DVDDL_JumpIntervalSize: return DataType.DvdDlJumpIntervalSize; case MediaTagType.DVDDL_ManualLayerJumpLBA: return DataType.DvdDlManualLayerJumpLba; case MediaTagType.BD_DI: return DataType.BlurayDi; case MediaTagType.BD_BCA: return DataType.BlurayBca; case MediaTagType.BD_DDS: return DataType.BlurayDds; case MediaTagType.BD_CartridgeStatus: return DataType.BlurayCartridgeStatus; case MediaTagType.BD_SpareArea: return DataType.BluraySpareArea; case MediaTagType.AACS_VolumeIdentifier: return DataType.AacsVolumeIdentifier; case MediaTagType.AACS_SerialNumber: return DataType.AacsSerialNumber; case MediaTagType.AACS_MediaIdentifier: return DataType.AacsMediaIdentifier; case MediaTagType.AACS_MKB: return DataType.AacsMediaKeyBlock; case MediaTagType.AACS_DataKeys: return DataType.AacsDataKeys; case MediaTagType.AACS_LBAExtents: return DataType.AacsLbaExtents; case MediaTagType.AACS_CPRM_MKB: return DataType.CprmMediaKeyBlock; case MediaTagType.Hybrid_RecognizedLayers: return DataType.HybridRecognizedLayers; case MediaTagType.MMC_WriteProtection: return DataType.ScsiMmcWriteProtection; case MediaTagType.MMC_DiscInformation: return DataType.ScsiMmcDiscInformation; case MediaTagType.MMC_TrackResourcesInformation: return DataType.ScsiMmcTrackResourcesInformation; case MediaTagType.MMC_POWResourcesInformation: return DataType.ScsiMmcPowResourcesInformation; case MediaTagType.SCSI_INQUIRY: return DataType.ScsiInquiry; case MediaTagType.SCSI_MODEPAGE_2A: return DataType.ScsiModePage2A; case MediaTagType.ATA_IDENTIFY: return DataType.AtaIdentify; case MediaTagType.ATAPI_IDENTIFY: return DataType.AtapiIdentify; case MediaTagType.PCMCIA_CIS: return DataType.PcmciaCis; case MediaTagType.SD_CID: return DataType.SecureDigitalCid; case MediaTagType.SD_CSD: return DataType.SecureDigitalCsd; case MediaTagType.SD_SCR: return DataType.SecureDigitalScr; case MediaTagType.SD_OCR: return DataType.SecureDigitalOcr; case MediaTagType.MMC_CID: return DataType.MultiMediaCardCid; case MediaTagType.MMC_CSD: return DataType.MultiMediaCardCsd; case MediaTagType.MMC_OCR: return DataType.MultiMediaCardOcr; case MediaTagType.MMC_ExtendedCSD: return DataType.MultiMediaCardExtendedCsd; case MediaTagType.Xbox_SecuritySector: return DataType.XboxSecuritySector; case MediaTagType.Floppy_LeadOut: return DataType.FloppyLeadOut; case MediaTagType.DCB: return DataType.DvdDiscControlBlock; case MediaTagType.CD_LeadIn: return DataType.CompactDiscLeadIn; case MediaTagType.CD_LeadOut: return DataType.CompactDiscLeadOut; case MediaTagType.SCSI_MODESENSE_6: return DataType.ScsiModeSense6; case MediaTagType.SCSI_MODESENSE_10: return DataType.ScsiModeSense10; case MediaTagType.USB_Descriptors: return DataType.UsbDescriptors; case MediaTagType.Xbox_DMI: return DataType.XboxDmi; case MediaTagType.Xbox_PFI: return DataType.XboxPfi; case MediaTagType.CD_MCN: return DataType.CompactDiscMediaCatalogueNumber; default: throw new ArgumentOutOfRangeException(nameof(tag), tag, null); } } } }