mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Split SBC dumping code in several files.
This commit is contained in:
20
.idea/.idea.Aaru/.idea/contentModel.xml
generated
20
.idea/.idea.Aaru/.idea/contentModel.xml
generated
@@ -3,9 +3,6 @@
|
||||
<component name="ContentModelStore">
|
||||
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
|
||||
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_Aaru.232757112.00" t="ExcludeRecursive" />
|
||||
<e p="$APPLICATION_CONFIG_DIR$/consoles/db" t="IncludeRecursive" />
|
||||
<e p="$APPLICATION_CONFIG_DIR$/extensions" t="IncludeRecursive" />
|
||||
<e p="$APPLICATION_CONFIG_DIR$/scratches" t="IncludeRecursive" />
|
||||
<e p="$USER_HOME$/.config/git/ignore" t="IncludeRecursive" />
|
||||
<e p="$APPLICATION_PLUGINS_DIR$/puppet/lib/stubs" t="IncludeRecursive" />
|
||||
<e p="$USER_HOME$/.nuget/packages/microsoft.net.test.sdk/16.4.0/build/netcoreapp2.1" t="Include">
|
||||
@@ -16,16 +13,6 @@
|
||||
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.api.dll" t="Include" />
|
||||
<e p="$USER_HOME$/.nuget/packages/nunit3testadapter/3.15.1/build/netcoreapp2.0/nunit.engine.dll" t="Include" />
|
||||
<e p="$PROJECT_DIR$" t="IncludeFlat">
|
||||
<e p=".git/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.Checksums/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.CommonTypes/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.Console/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.Decoders/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.Dto/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/Aaru.Helpers/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/CICMMetadata/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/cuetools.net/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".git/modules/cuetoolsnet/info/exclude" t="IncludeRecursive" />
|
||||
<e p=".github/CODE_OF_CONDUCT.md" t="Include" />
|
||||
<e p=".github/ISSUE_TEMPLATE.md" t="Include" />
|
||||
<e p=".github/PULL_REQUEST_TEMPLATE.md" t="Include" />
|
||||
@@ -284,9 +271,14 @@
|
||||
<e p="UMD.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ResumeSupport.cs" t="Include" />
|
||||
<e p="SBC.cs" t="Include" />
|
||||
<e p="SCSI.cs" t="Include" />
|
||||
<e p="SSC.cs" t="Include" />
|
||||
<e p="Sbc" t="Include">
|
||||
<e p="Data.cs" t="Include" />
|
||||
<e p="Dump.cs" t="Include" />
|
||||
<e p="Error.cs" t="Include" />
|
||||
<e p="Trim.cs" t="Include" />
|
||||
</e>
|
||||
<e p="SecureDigital.cs" t="Include" />
|
||||
<e p="XGD.cs" t="Include" />
|
||||
</e>
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
<Compile Include="Devices\Dumping\PlayStationPortable\MemoryStick.cs" />
|
||||
<Compile Include="Devices\Dumping\PlayStationPortable\PlayStationPortable.cs" />
|
||||
<Compile Include="Devices\Dumping\PlayStationPortable\UMD.cs" />
|
||||
<Compile Include="Devices\Dumping\Sbc\Data.cs" />
|
||||
<Compile Include="Devices\Dumping\Sbc\Error.cs" />
|
||||
<Compile Include="Devices\Dumping\Sbc\Dump.cs" />
|
||||
<Compile Include="Devices\Dumping\Sbc\Trim.cs" />
|
||||
<Compile Include="Devices\Info\DeviceInfo.cs" />
|
||||
<Compile Include="Devices\Info\Plextor.cs" />
|
||||
<Compile Include="Devices\Info\Properties.cs" />
|
||||
@@ -116,7 +120,6 @@
|
||||
<Compile Include="Devices\ReaderSCSI.cs" />
|
||||
<Compile Include="Devices\Dumping\SSC.cs" />
|
||||
<Compile Include="Devices\Dumping\MMC.cs" />
|
||||
<Compile Include="Devices\Dumping\SBC.cs" />
|
||||
<Compile Include="Devices\Dumping\XGD.cs" />
|
||||
<Compile Include="Devices\Dumping\ResumeSupport.cs" />
|
||||
<Compile Include="Partitions.cs" />
|
||||
|
||||
143
Aaru.Core/Devices/Dumping/Sbc/Data.cs
Normal file
143
Aaru.Core/Devices/Dumping/Sbc/Data.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Data.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2020 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using Aaru.CommonTypes.Extents;
|
||||
using Aaru.Core.Logging;
|
||||
using Schemas;
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
// ReSharper disable InlineOutVariableDeclaration
|
||||
// ReSharper disable TooWideLocalVariableScope
|
||||
|
||||
namespace Aaru.Core.Devices.Dumping
|
||||
{
|
||||
partial class Dump
|
||||
{
|
||||
void ReadSbcData(in ulong blocks, in uint maxBlocksToRead, in uint blockSize, DumpHardwareType currentTry,
|
||||
ExtentsULong extents, ref double currentSpeed, ref double minSpeed, ref double maxSpeed,
|
||||
ref double totalDuration, Reader scsiReader, MhddLog mhddLog, IbgLog ibgLog,
|
||||
ref double imageWriteDuration, ref bool newTrim)
|
||||
{
|
||||
ulong sectorSpeedStart = 0;
|
||||
bool sense;
|
||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||
byte[] buffer;
|
||||
uint blocksToRead = maxBlocksToRead;
|
||||
|
||||
for(ulong i = _resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
|
||||
if(currentSpeed > maxSpeed &&
|
||||
currentSpeed > 0)
|
||||
maxSpeed = currentSpeed;
|
||||
|
||||
if(currentSpeed < minSpeed &&
|
||||
currentSpeed > 0)
|
||||
minSpeed = currentSpeed;
|
||||
|
||||
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
|
||||
(long)blocks);
|
||||
|
||||
sense = scsiReader.ReadBlocks(out buffer, i, blocksToRead, out double cmdDuration, out _);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if(!sense &&
|
||||
!_dev.Error)
|
||||
{
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
DateTime writeStart = DateTime.Now;
|
||||
_outputPlugin.WriteSectors(buffer, i, blocksToRead);
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
extents.Add(i, blocksToRead, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_dev.Manufacturer.ToLowerInvariant() == "insite")
|
||||
{
|
||||
_resume.BadBlocks.Add(i);
|
||||
_resume.NextBlock++;
|
||||
_aborted = true;
|
||||
|
||||
_dumpLog?.
|
||||
WriteLine("INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke("INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Reset device after X errors
|
||||
if(_stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
|
||||
if(i + _skip > blocks)
|
||||
_skip = (uint)(blocks - i);
|
||||
|
||||
// Write empty data
|
||||
DateTime writeStart = DateTime.Now;
|
||||
_outputPlugin.WriteSectors(new byte[blockSize * _skip], i, _skip);
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
|
||||
for(ulong b = i; b < i + _skip; b++)
|
||||
_resume.BadBlocks.Add(b);
|
||||
|
||||
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
_dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", _skip, i);
|
||||
i += _skip - blocksToRead;
|
||||
newTrim = true;
|
||||
}
|
||||
|
||||
sectorSpeedStart += blocksToRead;
|
||||
_resume.NextBlock = i + blocksToRead;
|
||||
|
||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||
|
||||
if(elapsed < 1)
|
||||
continue;
|
||||
|
||||
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||
sectorSpeedStart = 0;
|
||||
timeSpeedStart = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,6 @@ namespace Aaru.Core.Devices.Dumping
|
||||
byte[] readBuffer;
|
||||
Modes.DecodedMode? decMode = null;
|
||||
bool ret;
|
||||
bool recoveredError;
|
||||
|
||||
if(opticalDisc)
|
||||
switch(dskType)
|
||||
@@ -592,101 +591,12 @@ namespace Aaru.Core.Devices.Dumping
|
||||
_dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _);
|
||||
}
|
||||
|
||||
bool newTrim = false;
|
||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||
ulong sectorSpeedStart = 0;
|
||||
bool newTrim = false;
|
||||
InitProgress?.Invoke();
|
||||
|
||||
for(ulong i = _resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
|
||||
if(currentSpeed > maxSpeed &&
|
||||
currentSpeed > 0)
|
||||
maxSpeed = currentSpeed;
|
||||
|
||||
if(currentSpeed < minSpeed &&
|
||||
currentSpeed > 0)
|
||||
minSpeed = currentSpeed;
|
||||
|
||||
UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", (long)i,
|
||||
(long)blocks);
|
||||
|
||||
sense = scsiReader.ReadBlocks(out readBuffer, i, blocksToRead, out double cmdDuration, out _);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if(!sense &&
|
||||
!_dev.Error)
|
||||
{
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
DateTime writeStart = DateTime.Now;
|
||||
_outputPlugin.WriteSectors(readBuffer, i, blocksToRead);
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
extents.Add(i, blocksToRead, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_dev.Manufacturer.ToLowerInvariant() == "insite")
|
||||
{
|
||||
_resume.BadBlocks.Add(i);
|
||||
_resume.NextBlock++;
|
||||
_aborted = true;
|
||||
|
||||
_dumpLog?.
|
||||
WriteLine("INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately.");
|
||||
|
||||
UpdateStatus?.
|
||||
Invoke("INSITE floptical drives get crazy on the SCSI bus when an error is found, stopping so you can reboot the computer or reset the scsi bus appropriately");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Reset device after X errors
|
||||
if(_stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
|
||||
if(i + _skip > blocks)
|
||||
_skip = (uint)(blocks - i);
|
||||
|
||||
// Write empty data
|
||||
DateTime writeStart = DateTime.Now;
|
||||
_outputPlugin.WriteSectors(new byte[blockSize * _skip], i, _skip);
|
||||
imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds;
|
||||
|
||||
for(ulong b = i; b < i + _skip; b++)
|
||||
_resume.BadBlocks.Add(b);
|
||||
|
||||
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
_dumpLog.WriteLine("Skipping {0} blocks from errored block {1}.", _skip, i);
|
||||
i += _skip - blocksToRead;
|
||||
newTrim = true;
|
||||
}
|
||||
|
||||
sectorSpeedStart += blocksToRead;
|
||||
_resume.NextBlock = i + blocksToRead;
|
||||
|
||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||
|
||||
if(elapsed < 1)
|
||||
continue;
|
||||
|
||||
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||
sectorSpeedStart = 0;
|
||||
timeSpeedStart = DateTime.UtcNow;
|
||||
}
|
||||
ReadSbcData(blocks, blocksToRead, blockSize, currentTry, extents, ref currentSpeed, ref minSpeed,
|
||||
ref maxSpeed, ref totalDuration, scsiReader, mhddLog, ibgLog, ref imageWriteDuration,
|
||||
ref newTrim);
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
EndProgress?.Invoke();
|
||||
@@ -721,32 +631,9 @@ namespace Aaru.Core.Devices.Dumping
|
||||
UpdateStatus?.Invoke("Trimming skipped sectors");
|
||||
_dumpLog.WriteLine("Trimming skipped sectors");
|
||||
|
||||
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||
InitProgress?.Invoke();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
||||
|
||||
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double _, out recoveredError);
|
||||
|
||||
if((sense || _dev.Error) &&
|
||||
!recoveredError)
|
||||
continue;
|
||||
|
||||
_resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
_outputPlugin.WriteSector(readBuffer, badSector);
|
||||
}
|
||||
TrimSbcData(scsiReader, extents, currentTry);
|
||||
|
||||
EndProgress?.Invoke();
|
||||
end = DateTime.UtcNow;
|
||||
@@ -759,248 +646,7 @@ namespace Aaru.Core.Devices.Dumping
|
||||
if(_resume.BadBlocks.Count > 0 &&
|
||||
!_aborted &&
|
||||
_retryPasses > 0)
|
||||
{
|
||||
int pass = 1;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
Modes.ModePage? currentModePage = null;
|
||||
byte[] md6;
|
||||
byte[] md10;
|
||||
|
||||
if(_persistent)
|
||||
{
|
||||
Modes.ModePage_01_MMC pgMmc;
|
||||
Modes.ModePage_01 pg;
|
||||
|
||||
sense = _dev.ModeSense6(out readBuffer, out _, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
_dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
{
|
||||
sense = _dev.ModeSense10(out readBuffer, out _, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
_dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
Modes.DecodedMode? dcMode10 = Modes.DecodeMode10(readBuffer, _dev.ScsiType);
|
||||
|
||||
if(dcMode10?.Pages != null)
|
||||
foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage =>
|
||||
modePage.Page == 0x01 && modePage.Subpage == 0x00))
|
||||
currentModePage = modePage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(readBuffer, _dev.ScsiType);
|
||||
|
||||
if(dcMode6?.Pages != null)
|
||||
foreach(Modes.ModePage modePage in dcMode6.Value.Pages.Where(modePage =>
|
||||
modePage.Page == 0x01 && modePage.Subpage == 0x00))
|
||||
currentModePage = modePage;
|
||||
}
|
||||
|
||||
if(currentModePage == null)
|
||||
{
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
pgMmc = new Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 32,
|
||||
Parameter = 0x00
|
||||
};
|
||||
|
||||
currentModePage = new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
pg = new Modes.ModePage_01
|
||||
{
|
||||
PS = false,
|
||||
AWRE = true,
|
||||
ARRE = true,
|
||||
TB = false,
|
||||
RC = false,
|
||||
EER = true,
|
||||
PER = false,
|
||||
DTE = true,
|
||||
DCR = false,
|
||||
ReadRetryCount = 32
|
||||
};
|
||||
|
||||
currentModePage = new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01(pg)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
pgMmc = new Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
}
|
||||
else
|
||||
{
|
||||
pg = new Modes.ModePage_01
|
||||
{
|
||||
PS = false,
|
||||
AWRE = false,
|
||||
ARRE = false,
|
||||
TB = true,
|
||||
RC = false,
|
||||
EER = true,
|
||||
PER = false,
|
||||
DTE = false,
|
||||
DCR = false,
|
||||
ReadRetryCount = 255
|
||||
};
|
||||
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01(pg)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke("Sending MODE SELECT to drive (return damaged blocks).");
|
||||
_dumpLog.WriteLine("Sending MODE SELECT to drive (return damaged blocks).");
|
||||
sense = _dev.ModeSelect(md6, out byte[] senseBuf, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
sense = _dev.ModeSelect10(md10, out senseBuf, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
{
|
||||
UpdateStatus?.
|
||||
Invoke("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");
|
||||
|
||||
AaruConsole.DebugWriteLine("Error: {0}", Sense.PrettifySense(senseBuf));
|
||||
|
||||
_dumpLog.
|
||||
WriteLine("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");
|
||||
}
|
||||
else
|
||||
{
|
||||
runningPersistent = true;
|
||||
}
|
||||
}
|
||||
|
||||
InitProgress?.Invoke();
|
||||
repeatRetry:
|
||||
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PulseProgress?.Invoke(string.Format("Retrying sector {0}, pass {1}, {3}{2}", badSector, pass,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : ""));
|
||||
|
||||
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration, out recoveredError);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if((!sense && !_dev.Error) || recoveredError)
|
||||
{
|
||||
_resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
_outputPlugin.WriteSector(readBuffer, badSector);
|
||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||
_dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
{
|
||||
_outputPlugin.WriteSector(readBuffer, badSector);
|
||||
}
|
||||
}
|
||||
|
||||
if(pass < _retryPasses &&
|
||||
!_aborted &&
|
||||
_resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
_resume.BadBlocks.Sort();
|
||||
|
||||
if(!forward)
|
||||
_resume.BadBlocks.Reverse();
|
||||
|
||||
goto repeatRetry;
|
||||
}
|
||||
|
||||
if(runningPersistent && currentModePage.HasValue)
|
||||
{
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
currentModePage.Value
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
|
||||
UpdateStatus?.Invoke("Sending MODE SELECT to drive (return device to previous status).");
|
||||
_dumpLog.WriteLine("Sending MODE SELECT to drive (return device to previous status).");
|
||||
sense = _dev.ModeSelect(md6, out _, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
_dev.ModeSelect10(md10, out _, true, false, _dev.Timeout, out _);
|
||||
}
|
||||
|
||||
EndProgress?.Invoke();
|
||||
}
|
||||
RetrySbcData(scsiReader, currentTry, extents, ref totalDuration);
|
||||
#endregion Error handling
|
||||
|
||||
if(!_aborted)
|
||||
@@ -1352,8 +998,6 @@ namespace Aaru.Core.Devices.Dumping
|
||||
sense = _dev.ModeSense10(out cmdBuf, out _, false, true,
|
||||
ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out _);
|
||||
|
||||
decMode = null;
|
||||
|
||||
if(!sense &&
|
||||
!_dev.Error)
|
||||
if(Modes.DecodeMode10(cmdBuf, _dev.ScsiType).HasValue)
|
||||
290
Aaru.Core/Devices/Dumping/Sbc/Error.cs
Normal file
290
Aaru.Core/Devices/Dumping/Sbc/Error.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Error.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2020 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.Extents;
|
||||
using Aaru.CommonTypes.Structs.Devices.SCSI;
|
||||
using Aaru.Console;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Devices;
|
||||
using Schemas;
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
// ReSharper disable InlineOutVariableDeclaration
|
||||
// ReSharper disable TooWideLocalVariableScope
|
||||
|
||||
namespace Aaru.Core.Devices.Dumping
|
||||
{
|
||||
partial class Dump
|
||||
{
|
||||
void RetrySbcData(Reader scsiReader, DumpHardwareType currentTry, ExtentsULong extents,
|
||||
ref double totalDuration)
|
||||
{
|
||||
int pass = 1;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
bool sense;
|
||||
byte[] buffer;
|
||||
bool recoveredError;
|
||||
|
||||
Modes.ModePage? currentModePage = null;
|
||||
byte[] md6;
|
||||
byte[] md10;
|
||||
|
||||
if(_persistent)
|
||||
{
|
||||
Modes.ModePage_01_MMC pgMmc;
|
||||
Modes.ModePage_01 pg;
|
||||
|
||||
sense = _dev.ModeSense6(out buffer, out _, false, ScsiModeSensePageControl.Current, 0x01, _dev.Timeout,
|
||||
out _);
|
||||
|
||||
if(sense)
|
||||
{
|
||||
sense = _dev.ModeSense10(out buffer, out _, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
_dev.Timeout, out _);
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
Modes.DecodedMode? dcMode10 = Modes.DecodeMode10(buffer, _dev.ScsiType);
|
||||
|
||||
if(dcMode10?.Pages != null)
|
||||
foreach(Modes.ModePage modePage in dcMode10.Value.Pages.Where(modePage =>
|
||||
modePage.Page == 0x01 && modePage.Subpage == 0x00))
|
||||
currentModePage = modePage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(buffer, _dev.ScsiType);
|
||||
|
||||
if(dcMode6?.Pages != null)
|
||||
foreach(Modes.ModePage modePage in dcMode6.Value.Pages.Where(modePage =>
|
||||
modePage.Page == 0x01 && modePage.Subpage == 0x00))
|
||||
currentModePage = modePage;
|
||||
}
|
||||
|
||||
if(currentModePage == null)
|
||||
{
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
pgMmc = new Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 32,
|
||||
Parameter = 0x00
|
||||
};
|
||||
|
||||
currentModePage = new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
pg = new Modes.ModePage_01
|
||||
{
|
||||
PS = false,
|
||||
AWRE = true,
|
||||
ARRE = true,
|
||||
TB = false,
|
||||
RC = false,
|
||||
EER = true,
|
||||
PER = false,
|
||||
DTE = true,
|
||||
DCR = false,
|
||||
ReadRetryCount = 32
|
||||
};
|
||||
|
||||
currentModePage = new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01(pg)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
pgMmc = new Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01_MMC(pgMmc)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
}
|
||||
else
|
||||
{
|
||||
pg = new Modes.ModePage_01
|
||||
{
|
||||
PS = false,
|
||||
AWRE = false,
|
||||
ARRE = false,
|
||||
TB = true,
|
||||
RC = false,
|
||||
EER = true,
|
||||
PER = false,
|
||||
DTE = false,
|
||||
DCR = false,
|
||||
ReadRetryCount = 255
|
||||
};
|
||||
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
new Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Modes.EncodeModePage_01(pg)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke("Sending MODE SELECT to drive (return damaged blocks).");
|
||||
_dumpLog.WriteLine("Sending MODE SELECT to drive (return damaged blocks).");
|
||||
sense = _dev.ModeSelect(md6, out byte[] senseBuf, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
sense = _dev.ModeSelect10(md10, out senseBuf, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
{
|
||||
UpdateStatus?.
|
||||
Invoke("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");
|
||||
|
||||
AaruConsole.DebugWriteLine("Error: {0}", Sense.PrettifySense(senseBuf));
|
||||
|
||||
_dumpLog.WriteLine("Drive did not accept MODE SELECT command for persistent error reading, try another drive.");
|
||||
}
|
||||
else
|
||||
{
|
||||
runningPersistent = true;
|
||||
}
|
||||
}
|
||||
|
||||
InitProgress?.Invoke();
|
||||
repeatRetry:
|
||||
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PulseProgress?.Invoke(string.Format("Retrying sector {0}, pass {1}, {3}{2}", badSector, pass,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : ""));
|
||||
|
||||
sense = scsiReader.ReadBlock(out buffer, badSector, out double cmdDuration, out recoveredError);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if((!sense && !_dev.Error) || recoveredError)
|
||||
{
|
||||
_resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
_outputPlugin.WriteSector(buffer, badSector);
|
||||
UpdateStatus?.Invoke($"Correctly retried block {badSector} in pass {pass}.");
|
||||
_dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
{
|
||||
_outputPlugin.WriteSector(buffer, badSector);
|
||||
}
|
||||
}
|
||||
|
||||
if(pass < _retryPasses &&
|
||||
!_aborted &&
|
||||
_resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
_resume.BadBlocks.Sort();
|
||||
|
||||
if(!forward)
|
||||
_resume.BadBlocks.Reverse();
|
||||
|
||||
goto repeatRetry;
|
||||
}
|
||||
|
||||
if(runningPersistent && currentModePage.HasValue)
|
||||
{
|
||||
var md = new Modes.DecodedMode
|
||||
{
|
||||
Header = new Modes.ModeHeader(),
|
||||
Pages = new[]
|
||||
{
|
||||
currentModePage.Value
|
||||
}
|
||||
};
|
||||
|
||||
md6 = Modes.EncodeMode6(md, _dev.ScsiType);
|
||||
md10 = Modes.EncodeMode10(md, _dev.ScsiType);
|
||||
|
||||
UpdateStatus?.Invoke("Sending MODE SELECT to drive (return device to previous status).");
|
||||
_dumpLog.WriteLine("Sending MODE SELECT to drive (return device to previous status).");
|
||||
sense = _dev.ModeSelect(md6, out _, true, false, _dev.Timeout, out _);
|
||||
|
||||
if(sense)
|
||||
_dev.ModeSelect10(md10, out _, true, false, _dev.Timeout, out _);
|
||||
}
|
||||
|
||||
EndProgress?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Aaru.Core/Devices/Dumping/Sbc/Trim.cs
Normal file
70
Aaru.Core/Devices/Dumping/Sbc/Trim.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Trim.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2020 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using Aaru.CommonTypes.Extents;
|
||||
using Schemas;
|
||||
|
||||
// ReSharper disable JoinDeclarationAndInitializer
|
||||
// ReSharper disable InlineOutVariableDeclaration
|
||||
// ReSharper disable TooWideLocalVariableScope
|
||||
|
||||
namespace Aaru.Core.Devices.Dumping
|
||||
{
|
||||
partial class Dump
|
||||
{
|
||||
void TrimSbcData(Reader scsiReader, ExtentsULong extents, DumpHardwareType currentTry)
|
||||
{
|
||||
ulong[] tmpArray = _resume.BadBlocks.ToArray();
|
||||
bool sense;
|
||||
bool recoveredError;
|
||||
byte[] buffer;
|
||||
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(_aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
UpdateStatus?.Invoke("Aborted!");
|
||||
_dumpLog.WriteLine("Aborted!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PulseProgress?.Invoke($"Trimming sector {badSector}");
|
||||
|
||||
sense = scsiReader.ReadBlock(out buffer, badSector, out double _, out recoveredError);
|
||||
|
||||
if((sense || _dev.Error) &&
|
||||
!recoveredError)
|
||||
continue;
|
||||
|
||||
_resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
_outputPlugin.WriteSector(buffer, badSector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user