Files
Aaru/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs

408 lines
24 KiB
C#
Raw Normal View History

// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Helpers.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// 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
{
/// <summary>
/// Checks for media tags that may contain metadata and sets it up if not already set
/// </summary>
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: 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);
}
}
}
}