From 97827d9bfe0750dbcb028416ef4cd80b26c4fb60 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 28 Apr 2024 20:28:48 +0100 Subject: [PATCH] [Dumping] [CompactDisc] When trimming or retrying using scrambled mode, fix offset and check validity of data sectors because drive can report no error but return errored data. Fixes #390 --- Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs | 6 -- .../Devices/Dumping/CompactDisc/Error.cs | 76 +++++++++++++++++- Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs | 78 +++++++++++++++++-- 3 files changed, 145 insertions(+), 15 deletions(-) diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index 07d2a37a7..833e12f1c 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -1119,12 +1119,6 @@ sealed partial class Dump } } - if(!_fixOffset || tracks.All(t => t.Type != TrackType.Audio)) - { - offsetBytes = 0; - sectorsForOffset = 0; - } - mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, _maximumReadable, _private, _dimensions); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs index 9a8085ff4..1b7d3d8c6 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs @@ -37,6 +37,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Aaru.Checksums; using Aaru.CommonTypes.AaruMetadata; using Aaru.CommonTypes.Extents; using Aaru.CommonTypes.Interfaces; @@ -304,12 +305,79 @@ partial class Dump // Try to workaround firmware if(decSense is { ASC: 0x11, ASCQ: 0x05 } || decSense?.ASC == 0x64) { - sense = _dev.ReadCd(out cmdBuf, out _, badSectorToReRead, blockSize, sectorsToReRead, - MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, - false, MmcErrorField.None, supportedSubchannel, _dev.Timeout, - out double cmdDuration2); + byte scrambledSectorsToReRead = sectorsToReRead; + uint scrambledBadSectorToReRead = badSectorToReRead; + + // Contrary to normal read, this must always be offset fixed, because it's data not audio + if(offsetBytes != 0) + { + if(offsetBytes < 0) + { + if(scrambledBadSectorToReRead == 0) + scrambledBadSectorToReRead = uint.MaxValue - (uint)(sectorsForOffset - 1); // -1 + else + scrambledBadSectorToReRead -= (uint)sectorsForOffset; + } + + scrambledSectorsToReRead += (byte)sectorsForOffset; + } + + sense = _dev.ReadCd(out cmdBuf, out _, scrambledBadSectorToReRead, blockSize, + scrambledSectorsToReRead, MmcSectorTypes.Cdda, false, false, false, + MmcHeaderCodes.None, true, false, MmcErrorField.None, + supportedSubchannel, _dev.Timeout, out double cmdDuration2); cmdDuration += cmdDuration2; + + if(!sense) + { + uint scrambledBlocksToReRead = scrambledSectorsToReRead; + FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, + ref scrambledBlocksToReRead, subSize, ref cmdBuf, blockSize, false); + + // Descramble + cmdBuf = Sector.Scramble(cmdBuf); + + // Check valid sector + CdChecksums.CheckCdSector(cmdBuf, out bool? correctEccP, out bool? correctEccQ, + out bool? correctEdc); + + // Check mode, set sense if EDC/ECC validity is not correct + switch(cmdBuf[15] & 0x03) + { + case 0: + + for(var c = 16; c < 2352; c++) + { + if(cmdBuf[c] == 0x00) + continue; + + sense = true; + + break; + } + + break; + case 1: + sense = correctEdc != true || correctEccP != true || correctEccQ != true; + + break; + case 2: + if((cmdBuf[18] & 0x20) != 0x20) + { + if(correctEccP != true) + sense = true; + + if(correctEccQ != true) + sense = true; + } + + if(correctEdc != true) + sense = true; + + break; + } + } } } } diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs index a324681f5..f119e6c3c 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs @@ -37,6 +37,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Aaru.Checksums; using Aaru.CommonTypes.AaruMetadata; using Aaru.CommonTypes.Extents; using Aaru.CommonTypes.Interfaces; @@ -183,14 +184,81 @@ partial class Dump DecodedSense? decSense = Sense.Decode(senseBuf); // Try to workaround firmware - if(decSense?.ASC == 0x64) + if(decSense is { ASC: 0x11, ASCQ: 0x05 } || decSense?.ASC == 0x64) { - sense = _dev.ReadCd(out cmdBuf, out _, badSectorToRead, blockSize, sectorsToTrim, - MmcSectorTypes.Cdda, false, false, false, MmcHeaderCodes.None, true, - false, MmcErrorField.None, supportedSubchannel, _dev.Timeout, - out double cmdDuration2); + byte scrambledSectorsToTrim = sectorsToTrim; + uint scrambledBadSectorToRead = badSectorToRead; + + // Contrary to normal read, this must always be offset fixed, because it's data not audio + if(offsetBytes != 0) + { + if(offsetBytes < 0) + { + if(scrambledBadSectorToRead == 0) + scrambledBadSectorToRead = uint.MaxValue - (uint)(sectorsForOffset - 1); // -1 + else + scrambledBadSectorToRead -= (uint)sectorsForOffset; + } + + scrambledSectorsToTrim += (byte)sectorsForOffset; + } + + sense = _dev.ReadCd(out cmdBuf, out _, scrambledBadSectorToRead, blockSize, + scrambledSectorsToTrim, MmcSectorTypes.Cdda, false, false, false, + MmcHeaderCodes.None, true, false, MmcErrorField.None, + supportedSubchannel, _dev.Timeout, out double cmdDuration2); cmdDuration += cmdDuration2; + + if(!sense) + { + uint scrambledBlocksToRead = scrambledSectorsToTrim; + FixOffsetData(offsetBytes, sectorSize, sectorsForOffset, supportedSubchannel, + ref scrambledBlocksToRead, subSize, ref cmdBuf, blockSize, false); + + // Descramble + cmdBuf = Sector.Scramble(cmdBuf); + + // Check valid sector + CdChecksums.CheckCdSector(cmdBuf, out bool? correctEccP, out bool? correctEccQ, + out bool? correctEdc); + + // Check mode, set sense if EDC/ECC validity is not correct + switch(cmdBuf[15] & 0x03) + { + case 0: + + for(var c = 16; c < 2352; c++) + { + if(cmdBuf[c] == 0x00) + continue; + + sense = true; + + break; + } + + break; + case 1: + sense = correctEdc != true || correctEccP != true || correctEccQ != true; + + break; + case 2: + if((cmdBuf[18] & 0x20) != 0x20) + { + if(correctEccP != true) + sense = true; + + if(correctEccQ != true) + sense = true; + } + + if(correctEdc != true) + sense = true; + + break; + } + } } } }