// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Helpers.cs // Author(s) : Natalia Portillo // // Component : Disk image plugins. // // --[ Description ] ---------------------------------------------------------- // // Contains helpers for Aaru 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-2025 Natalia Portillo // ****************************************************************************/ using System; using Aaru.CommonTypes; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Structs.Devices.ATA; using Aaru.CommonTypes.Structs.Devices.SCSI; using Aaru.Decoders.SecureDigital; using Aaru.Helpers; namespace Aaru.Images; public sealed partial class AaruFormat { /// 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? nullableInquiry = Inquiry.Decode(scsiInquiry); if(nullableInquiry.HasValue) { Inquiry 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 = CommonTypes.Structs.Devices.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[^1]; } } if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) _imageInfo.DriveFirmwareRevision = identify.FirmwareRevision; if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) _imageInfo.DriveSerialNumber = identify.SerialNumber; } // Get the Aaru Metadata media type from Aaru media type static MetadataMediaType GetMetadataMediaType(MediaType type) { return type switch { MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG or MediaType.CDI or MediaType.CDIREADY or MediaType.CDROM or MediaType.CDROMXA or MediaType.CDPLUS or MediaType.CDMO or MediaType.CDR or MediaType.CDRW or MediaType.CDMRW or MediaType.VCD or MediaType.SVCD or MediaType.PCD or MediaType.SACD or MediaType.DDCD or MediaType.DDCDR or MediaType.DDCDRW or MediaType.DTSCD or MediaType.CDMIDI or MediaType.CDV or MediaType.DVDROM or MediaType.DVDR or MediaType.DVDRW or MediaType.DVDPR or MediaType.DVDPRW or MediaType.DVDPRWDL or MediaType.DVDRDL or MediaType.DVDPRDL or MediaType.DVDRAM or MediaType.DVDRWDL or MediaType.DVDDownload or MediaType.HDDVDROM or MediaType.HDDVDRAM or MediaType.HDDVDR or MediaType.HDDVDRW or MediaType.HDDVDRDL or MediaType.HDDVDRWDL or MediaType.BDROM or MediaType.UHDBD or MediaType.BDR or MediaType.BDRE or MediaType.BDRXL or MediaType.BDREXL or MediaType.EVD or MediaType.FVD or MediaType.HVD or MediaType.CBHD or MediaType.HDVMD or MediaType.VCDHD or MediaType.SVOD or MediaType.FDDVD or MediaType.LD or MediaType.LDROM or MediaType.CRVdisc or MediaType.LDROM2 or MediaType.LVROM or MediaType.MegaLD or MediaType.PS1CD or MediaType.PS2CD or MediaType.PS2DVD or MediaType.PS3DVD or MediaType.PS3BD or MediaType.PS4BD or MediaType.PS5BD or MediaType.UMD or MediaType.XGD or MediaType.XGD2 or MediaType.XGD3 or MediaType.XGD4 or MediaType.MEGACD or MediaType.SATURNCD or MediaType.GDROM or MediaType.GDR or MediaType.SuperCDROM2 or MediaType.JaguarCD or MediaType.ThreeDO or MediaType.PCFX or MediaType.NeoGeoCD or MediaType.GOD or MediaType.WOD or MediaType.WUOD or MediaType.CDTV or MediaType.CD32 or MediaType.Nuon or MediaType.Playdia or MediaType.Pippin or MediaType.FMTOWNS or MediaType.MilCD or MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp or MediaType.CVD => MetadataMediaType.OpticalDisc, _ => MetadataMediaType.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(); _imageStream.Position += (long)(sectorAddress * sizeof(ulong)); var temp = new byte[sizeof(ulong)]; _imageStream.EnsureRead(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) { if(IsTape) _tapeDdt[sectorAddress] = pointer; else _userDataDdt[sectorAddress] = pointer; return; } long oldPosition = _imageStream.Position; _imageStream.Position = _outMemoryDdtPosition + Marshal.SizeOf(); _imageStream.Position += (long)(sectorAddress * sizeof(ulong)); _imageStream.Write(BitConverter.GetBytes(pointer), 0, sizeof(ulong)); _imageStream.Position = oldPosition; } // Converts between image data type and Aaru media tag type static MediaTagType GetMediaTagTypeForDataType(DataType type) => type switch { DataType.CompactDiscPartialToc => MediaTagType .CD_TOC, DataType.CompactDiscSessionInfo => MediaTagType .CD_SessionInfo, DataType.CompactDiscToc => MediaTagType .CD_FullTOC, DataType.CompactDiscPma => MediaTagType.CD_PMA, DataType.CompactDiscAtip => MediaTagType .CD_ATIP, DataType.CompactDiscLeadInCdText => MediaTagType.CD_TEXT, DataType.DvdPfi => MediaTagType.DVD_PFI, DataType.DvdLeadInCmi => MediaTagType.DVD_CMI, DataType.DvdDiscKey => MediaTagType.DVD_DiscKey, DataType.DvdBca => MediaTagType.DVD_BCA, DataType.DvdDmi => MediaTagType.DVD_DMI, DataType.DvdMediaIdentifier => MediaTagType .DVD_MediaIdentifier, DataType.DvdMediaKeyBlock => MediaTagType .DVD_MKB, DataType.DvdRamDds => MediaTagType.DVDRAM_DDS, DataType.DvdRamMediumStatus => MediaTagType .DVDRAM_MediumStatus, DataType.DvdRamSpareArea => MediaTagType .DVDRAM_SpareArea, DataType.DvdRRmd => MediaTagType.DVDR_RMD, DataType.DvdRPrerecordedInfo => MediaTagType .DVDR_PreRecordedInfo, DataType.DvdRMediaIdentifier => MediaTagType .DVDR_MediaIdentifier, DataType.DvdRPfi => MediaTagType.DVDR_PFI, DataType.DvdAdip => MediaTagType.DVD_ADIP, DataType.HdDvdCpi => MediaTagType.HDDVD_CPI, DataType.HdDvdMediumStatus => MediaTagType .HDDVD_MediumStatus, DataType.DvdDlLayerCapacity => MediaTagType .DVDDL_LayerCapacity, DataType.DvdDlMiddleZoneAddress => MediaTagType .DVDDL_MiddleZoneAddress, DataType.DvdDlJumpIntervalSize => MediaTagType .DVDDL_JumpIntervalSize, DataType.DvdDlManualLayerJumpLba => MediaTagType.DVDDL_ManualLayerJumpLBA, DataType.BlurayDi => MediaTagType.BD_DI, DataType.BlurayBca => MediaTagType.BD_BCA, DataType.BlurayDds => MediaTagType.BD_DDS, DataType.BlurayCartridgeStatus => MediaTagType .BD_CartridgeStatus, DataType.BluraySpareArea => MediaTagType .BD_SpareArea, DataType.AacsVolumeIdentifier => MediaTagType .AACS_VolumeIdentifier, DataType.AacsSerialNumber => MediaTagType .AACS_SerialNumber, DataType.AacsMediaIdentifier => MediaTagType .AACS_MediaIdentifier, DataType.AacsMediaKeyBlock => MediaTagType .AACS_MKB, DataType.AacsDataKeys => MediaTagType .AACS_DataKeys, DataType.AacsLbaExtents => MediaTagType .AACS_LBAExtents, DataType.CprmMediaKeyBlock => MediaTagType .AACS_CPRM_MKB, DataType.HybridRecognizedLayers => MediaTagType .Hybrid_RecognizedLayers, DataType.ScsiMmcWriteProtection => MediaTagType .MMC_WriteProtection, DataType.ScsiMmcDiscInformation => MediaTagType .MMC_DiscInformation, DataType.ScsiMmcTrackResourcesInformation => MediaTagType.MMC_TrackResourcesInformation, DataType.ScsiMmcPowResourcesInformation => MediaTagType.MMC_POWResourcesInformation, DataType.ScsiInquiry => MediaTagType .SCSI_INQUIRY, DataType.ScsiModePage2A => MediaTagType .SCSI_MODEPAGE_2A, DataType.AtaIdentify => MediaTagType .ATA_IDENTIFY, DataType.AtapiIdentify => MediaTagType .ATAPI_IDENTIFY, DataType.PcmciaCis => MediaTagType.PCMCIA_CIS, DataType.SecureDigitalCid => MediaTagType .SD_CID, DataType.SecureDigitalCsd => MediaTagType .SD_CSD, DataType.SecureDigitalScr => MediaTagType .SD_SCR, DataType.SecureDigitalOcr => MediaTagType .SD_OCR, DataType.MultiMediaCardCid => MediaTagType .MMC_CID, DataType.MultiMediaCardCsd => MediaTagType .MMC_CSD, DataType.MultiMediaCardOcr => MediaTagType .MMC_OCR, DataType.MultiMediaCardExtendedCsd => MediaTagType.MMC_ExtendedCSD, DataType.XboxSecuritySector => MediaTagType .Xbox_SecuritySector, DataType.FloppyLeadOut => MediaTagType .Floppy_LeadOut, DataType.DvdDiscControlBlock => MediaTagType .DCB, DataType.CompactDiscFirstTrackPregap => MediaTagType.CD_FirstTrackPregap, DataType.CompactDiscLeadOut => MediaTagType .CD_LeadOut, DataType.ScsiModeSense6 => MediaTagType .SCSI_MODESENSE_6, DataType.ScsiModeSense10 => MediaTagType .SCSI_MODESENSE_10, DataType.UsbDescriptors => MediaTagType .USB_Descriptors, DataType.XboxDmi => MediaTagType.Xbox_DMI, DataType.XboxPfi => MediaTagType.Xbox_PFI, DataType.CompactDiscMediaCatalogueNumber => MediaTagType.CD_MCN, DataType.CompactDiscLeadIn => MediaTagType .CD_LeadIn, DataType.DvdDiscKeyDecrypted => MediaTagType .DVD_DiscKey_Decrypted, _ => throw new ArgumentOutOfRangeException() }; // Converts between Aaru media tag type and image data type static DataType GetDataTypeForMediaTag(MediaTagType tag) => tag switch { MediaTagType.CD_TOC => DataType .CompactDiscPartialToc, MediaTagType.CD_SessionInfo => DataType .CompactDiscSessionInfo, MediaTagType.CD_FullTOC => DataType.CompactDiscToc, MediaTagType.CD_PMA => DataType.CompactDiscPma, MediaTagType.CD_ATIP => DataType.CompactDiscAtip, MediaTagType.CD_TEXT => DataType .CompactDiscLeadInCdText, MediaTagType.DVD_PFI => DataType.DvdPfi, MediaTagType.DVD_CMI => DataType.DvdLeadInCmi, MediaTagType.DVD_DiscKey => DataType.DvdDiscKey, MediaTagType.DVD_BCA => DataType.DvdBca, MediaTagType.DVD_DMI => DataType.DvdDmi, MediaTagType.DVD_MediaIdentifier => DataType .DvdMediaIdentifier, MediaTagType.DVD_MKB => DataType.DvdMediaKeyBlock, MediaTagType.DVDRAM_DDS => DataType.DvdRamDds, MediaTagType.DVDRAM_MediumStatus => DataType .DvdRamMediumStatus, MediaTagType.DVDRAM_SpareArea => DataType .DvdRamSpareArea, MediaTagType.DVDR_RMD => DataType.DvdRRmd, MediaTagType.DVDR_PreRecordedInfo => DataType .DvdRPrerecordedInfo, MediaTagType.DVDR_MediaIdentifier => DataType .DvdRMediaIdentifier, MediaTagType.DVDR_PFI => DataType.DvdRPfi, MediaTagType.DVD_ADIP => DataType.DvdAdip, MediaTagType.HDDVD_CPI => DataType.HdDvdCpi, MediaTagType.HDDVD_MediumStatus => DataType .HdDvdMediumStatus, MediaTagType.DVDDL_LayerCapacity => DataType .DvdDlLayerCapacity, MediaTagType.DVDDL_MiddleZoneAddress => DataType .DvdDlMiddleZoneAddress, MediaTagType.DVDDL_JumpIntervalSize => DataType .DvdDlJumpIntervalSize, MediaTagType.DVDDL_ManualLayerJumpLBA => DataType .DvdDlManualLayerJumpLba, MediaTagType.BD_DI => DataType.BlurayDi, MediaTagType.BD_BCA => DataType.BlurayBca, MediaTagType.BD_DDS => DataType.BlurayDds, MediaTagType.BD_CartridgeStatus => DataType .BlurayCartridgeStatus, MediaTagType.BD_SpareArea => DataType .BluraySpareArea, MediaTagType.AACS_VolumeIdentifier => DataType .AacsVolumeIdentifier, MediaTagType.AACS_SerialNumber => DataType .AacsSerialNumber, MediaTagType.AACS_MediaIdentifier => DataType .AacsMediaIdentifier, MediaTagType.AACS_MKB => DataType.AacsMediaKeyBlock, MediaTagType.AACS_DataKeys => DataType.AacsDataKeys, MediaTagType.AACS_LBAExtents => DataType .AacsLbaExtents, MediaTagType.AACS_CPRM_MKB => DataType .CprmMediaKeyBlock, MediaTagType.Hybrid_RecognizedLayers => DataType .HybridRecognizedLayers, MediaTagType.MMC_WriteProtection => DataType .ScsiMmcWriteProtection, MediaTagType.MMC_DiscInformation => DataType .ScsiMmcDiscInformation, MediaTagType.MMC_TrackResourcesInformation => DataType.ScsiMmcTrackResourcesInformation, MediaTagType.MMC_POWResourcesInformation => DataType .ScsiMmcPowResourcesInformation, MediaTagType.SCSI_INQUIRY => DataType.ScsiInquiry, MediaTagType.SCSI_MODEPAGE_2A => DataType .ScsiModePage2A, MediaTagType.ATA_IDENTIFY => DataType.AtaIdentify, MediaTagType.ATAPI_IDENTIFY => DataType .AtapiIdentify, MediaTagType.PCMCIA_CIS => DataType.PcmciaCis, MediaTagType.SD_CID => DataType.SecureDigitalCid, MediaTagType.SD_CSD => DataType.SecureDigitalCsd, MediaTagType.SD_SCR => DataType.SecureDigitalScr, MediaTagType.SD_OCR => DataType.SecureDigitalOcr, MediaTagType.MMC_CID => DataType.MultiMediaCardCid, MediaTagType.MMC_CSD => DataType.MultiMediaCardCsd, MediaTagType.MMC_OCR => DataType.MultiMediaCardOcr, MediaTagType.MMC_ExtendedCSD => DataType .MultiMediaCardExtendedCsd, MediaTagType.Xbox_SecuritySector => DataType .XboxSecuritySector, MediaTagType.Floppy_LeadOut => DataType .FloppyLeadOut, MediaTagType.DCB => DataType.DvdDiscControlBlock, MediaTagType.CD_FirstTrackPregap => DataType .CompactDiscFirstTrackPregap, MediaTagType.CD_LeadOut => DataType .CompactDiscLeadOut, MediaTagType.SCSI_MODESENSE_6 => DataType .ScsiModeSense6, MediaTagType.SCSI_MODESENSE_10 => DataType .ScsiModeSense10, MediaTagType.USB_Descriptors => DataType .UsbDescriptors, MediaTagType.Xbox_DMI => DataType.XboxDmi, MediaTagType.Xbox_PFI => DataType.XboxPfi, MediaTagType.CD_MCN => DataType .CompactDiscMediaCatalogueNumber, MediaTagType.CD_LeadIn => DataType.CompactDiscLeadIn, MediaTagType.DVD_DiscKey_Decrypted => DataType .DvdDiscKeyDecrypted, _ => throw new ArgumentOutOfRangeException(nameof(tag), tag, null) }; }