Skip to content

Commit

Permalink
[Dumping] [CompactDisc] When trimming or retrying using scrambled mod…
Browse files Browse the repository at this point in the history
…e, fix offset and check validity of data sectors because drive can report no error but return errored data. Fixes #390
  • Loading branch information
claunia committed Apr 28, 2024
1 parent 99adb55 commit 97827d9
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 15 deletions.
6 changes: 0 additions & 6 deletions Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,12 +1119,6 @@ void CompactDisc()
}
}

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

Expand Down
76 changes: 72 additions & 4 deletions Aaru.Core/Devices/Dumping/CompactDisc/Error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -304,12 +305,79 @@ void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardware cur
// 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;
}
}
}
}
}
Expand Down
78 changes: 73 additions & 5 deletions Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -183,14 +184,81 @@ void TrimCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardware curr
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;
}
}
}
}
}
Expand Down

0 comments on commit 97827d9

Please sign in to comment.