Initial OmniDrive DVD read

This commit is contained in:
Rebecca Wallander
2026-02-21 19:31:09 +01:00
parent 915e99958c
commit 92e3aa38b3
10 changed files with 162 additions and 11 deletions

View File

@@ -324,6 +324,7 @@ partial class Dump
scsiReader.otp = decodedPfi is { Layers: 1, TrackPath: false };
if(scsiReader.HldtstReadRaw) blocksToRead = 1;
if(scsiReader.OmniDriveReadRaw) blocksToRead = 31;
UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_raw_bytes_1_cooked_bytes_per_sector,
longBlockSize,
@@ -804,9 +805,9 @@ partial class Dump
{
mediaTags.TryGetValue(MediaTagType.DVD_DiscKey_Decrypted, out byte[] discKey);
if(scsiReader.HldtstReadRaw || scsiReader.ReadBuffer3CReadRaw)
if(scsiReader.HldtstReadRaw || scsiReader.ReadBuffer3CReadRaw || scsiReader.OmniDriveReadRaw)
{
ReadCacheData(blocks,
ReadRawDvdData(blocks,
blocksToRead,
blockSize,
currentTry,
@@ -905,6 +906,7 @@ partial class Dump
// Unnecessary since keys are already in raw data
!scsiReader.ReadBuffer3CReadRaw &&
!scsiReader.OmniDriveReadRaw &&
!scsiReader.HldtstReadRaw &&
mediaTag is not null)
RetryTitleKeys(dvdDecrypt, mediaTag, ref totalDuration);

View File

@@ -306,7 +306,7 @@ partial class Dump
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
if(scsiReader.ReadBuffer3CReadRaw || scsiReader.HldtstReadRaw)
if(scsiReader.ReadBuffer3CReadRaw || scsiReader.OmniDriveReadRaw || scsiReader.HldtstReadRaw)
{
var cmi = new byte[1];

View File

@@ -2,7 +2,7 @@
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Cache.cs
// Filename : RawDvd.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
@@ -44,8 +44,8 @@ namespace Aaru.Core.Devices.Dumping;
partial class Dump
{
/// <summary>
/// Dumps data when dumping from a SCSI Block Commands compliant device,
/// and reads the data from the device cache
/// Dumps raw DVD sectors (2064-byte frames) when dumping from a SCSI Block Commands compliant device.
/// Supports HL-DT-ST, ReadBuffer 3C, and OmniDrive raw reading methods.
/// </summary>
/// <param name="blocks">Media blocks</param>
/// <param name="maxBlocksToRead">Maximum number of blocks to read in a single command</param>
@@ -62,7 +62,7 @@ partial class Dump
/// <param name="imageWriteDuration">Total time spent writing to image</param>
/// <param name="newTrim">Set if we need to start a trim</param>
/// <param name="discKey">The DVD disc key</param>
void ReadCacheData(in ulong blocks, in uint maxBlocksToRead, in uint blockSize, DumpHardware currentTry,
void ReadRawDvdData(in ulong blocks, in uint maxBlocksToRead, in uint blockSize, DumpHardware 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, byte[] discKey)
@@ -216,4 +216,4 @@ partial class Dump
EndProgress?.Invoke();
}
}
}

View File

@@ -99,7 +99,7 @@ partial class Dump
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
if(scsiReader.ReadBuffer3CReadRaw || scsiReader.HldtstReadRaw)
if(scsiReader.ReadBuffer3CReadRaw || scsiReader.OmniDriveReadRaw || scsiReader.HldtstReadRaw)
{
var cmi = new byte[1];

View File

@@ -55,6 +55,7 @@ sealed partial class Reader
// TODO: Raw reading
public bool HldtstReadRaw;
public uint layerbreak;
public bool OmniDriveReadRaw;
public bool ReadBuffer3CReadRaw;
public bool otp;
@@ -587,7 +588,14 @@ sealed partial class Reader
ReadBuffer3CReadRaw =
!_dev.ReadBuffer3CRawDvd(out _, out senseBuf, 0, 1, _timeout, out _, layerbreak, otp);
if(HldtstReadRaw || _plextorReadRaw || ReadBuffer3CReadRaw)
// Try OmniDrive on drives with OmniDrive firmware
if(_dev.IsOmniDriveFirmware())
{
OmniDriveReadRaw =
!_dev.OmniDriveReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _);
}
if(HldtstReadRaw || _plextorReadRaw || ReadBuffer3CReadRaw || OmniDriveReadRaw)
{
CanReadRaw = true;
LongBlockSize = 2064;
@@ -622,6 +630,8 @@ sealed partial class Reader
AaruLogging.WriteLine($"[slateblue1]{Localization.Core.Using_HL_DT_ST_raw_DVD_reading}[/]");
else if(_plextorReadRaw)
AaruLogging.WriteLine($"[slateblue1]{Localization.Core.Using_Plextor_raw_DVD_reading}[/]");
else if(OmniDriveReadRaw)
AaruLogging.WriteLine($"[slateblue1]{Localization.Core.Using_OmniDrive_raw_DVD_reading}[/]");
else if(ReadBuffer3CReadRaw)
AaruLogging.WriteLine($"[slateblue1]{Localization.Core.Using_ReadBuffer_3C_raw_DVD_reading}[/]");
}
@@ -687,6 +697,8 @@ sealed partial class Reader
{
if(HldtstReadRaw || ReadBuffer3CReadRaw)
BlocksToRead = 1;
else if(OmniDriveReadRaw)
BlocksToRead = (uint)Math.Min(31, startWithBlocks);
else if(_read6)
{
_dev.Read6(out _, out _, 0, LogicalBlockSize, (byte)BlocksToRead, _timeout, out _);
@@ -833,6 +845,15 @@ sealed partial class Reader
_timeout,
out duration);
}
else if(OmniDriveReadRaw)
{
sense = _dev.OmniDriveReadRawDvd(out buffer,
out senseBuf,
(uint)block,
count,
_timeout,
out duration);
}
else if(ReadBuffer3CReadRaw)
{
sense = _dev.ReadBuffer3CRawDvd(out buffer,

View File

@@ -0,0 +1,109 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : OmniDrive.cs
// Author(s) : Rebecca Wallander <sakcheen@gmail.com>
//
// Component : OmniDrive firmware vendor commands.
//
// --[ Description ] ----------------------------------------------------------
//
// Contains vendor commands for OmniDrive firmware. OmniDrive is custom
// firmware that adds SCSI command 0xC0 to read raw DVD sectors (2064 bytes)
// directly by LBA.
//
// --[ 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-2026 Rebecca Wallander
// ****************************************************************************/
using System;
using Aaru.CommonTypes.Structs.Devices.SCSI;
using Aaru.Logging;
namespace Aaru.Devices;
public partial class Device
{
/// <summary>
/// Checks if the drive has OmniDrive firmware by inspecting INQUIRY Reserved5 (bytes 74+) for "OmniDrive",
/// matching redumper's is_omnidrive_firmware behaviour.
/// </summary>
/// <returns><c>true</c> if Reserved5 starts with "OmniDrive" and has at least 11 bytes (8 + 3 for version).</returns>
public bool IsOmniDriveFirmware()
{
bool sense = ScsiInquiry(out byte[] buffer, out _, Timeout, out _);
if(sense || buffer == null) return false;
Inquiry? inquiry = Inquiry.Decode(buffer);
if(!inquiry.HasValue || inquiry.Value.Reserved5 == null || inquiry.Value.Reserved5.Length < 11)
return false;
byte[] reserved5 = inquiry.Value.Reserved5;
byte[] omnidrive = [0x4F, 0x6D, 0x6E, 0x69, 0x44, 0x72, 0x69, 0x76, 0x65]; // "OmniDrive"
if(reserved5.Length < omnidrive.Length) return false;
for(int i = 0; i < omnidrive.Length; i++)
if(reserved5[i] != omnidrive[i])
return false;
return true;
}
/// <summary>Reads raw DVD sectors (2064 bytes) directly by LBA on OmniDrive firmware.</summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
/// <param name="buffer">Buffer where the raw DataFrame response will be stored</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="lba">Start block address (LBA).</param>
/// <param name="transferLength">Number of 2064-byte sectors to read.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool OmniDriveReadRawDvd(out byte[] buffer, out ReadOnlySpan<byte> senseBuffer, uint lba, uint transferLength,
uint timeout, out double duration)
{
senseBuffer = SenseBuffer;
Span<byte> cdb = CdbBuffer[..12];
cdb.Clear();
buffer = new byte[2064 * transferLength];
cdb[0] = (byte)ScsiCommands.ReadOmniDrive;
cdb[1] = 0x11; // disc_type=1 (DVD), raw_addressing=0 (LBA), fua=0, descramble=1
cdb[2] = (byte)((lba >> 24) & 0xFF);
cdb[3] = (byte)((lba >> 16) & 0xFF);
cdb[4] = (byte)((lba >> 8) & 0xFF);
cdb[5] = (byte)(lba & 0xFF);
cdb[6] = (byte)((transferLength >> 24) & 0xFF);
cdb[7] = (byte)((transferLength >> 16) & 0xFF);
cdb[8] = (byte)((transferLength >> 8) & 0xFF);
cdb[9] = (byte)(transferLength & 0xFF);
cdb[10] = 0; // subchannels=NONE, c2=0
cdb[11] = 0; // control
LastError = SendScsiCommand(cdb, ref buffer, timeout, ScsiDirection.In, out duration, out bool sense);
Error = LastError != 0;
AaruLogging.Debug(SCSI_MODULE_NAME, "OmniDrive READ RAW DVD took {0} ms", duration);
return sense;
}
}

View File

@@ -1885,6 +1885,13 @@ public enum ScsiCommands : byte
#endregion HL-DT-ST vendor commands
#region OmniDrive vendor commands
/// <summary>Reads raw DVD sectors directly by LBA/PSN (OmniDrive firmware)</summary>
ReadOmniDrive = 0xC0,
#endregion OmniDrive vendor commands
#region NEC vendor commands
/// <summary>Reads CD-DA data</summary>

View File

@@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
@@ -6839,6 +6839,12 @@ namespace Aaru.Localization {
}
}
public static string Using_OmniDrive_raw_DVD_reading {
get {
return ResourceManager.GetString("Using_OmniDrive_raw_DVD_reading", resourceCulture);
}
}
public static string Using_ReadBuffer_3C_raw_DVD_reading {
get {
return ResourceManager.GetString("Using_ReadBuffer_3C_raw_DVD_reading", resourceCulture);

View File

@@ -3271,6 +3271,9 @@ No tiene sentido hacerlo y supondría demasiado esfuerzo para la cinta.</value>
<data name="Using_MMC_READ_CD_command" xml:space="preserve">
<value>[slateblue1]Usando comando [fuchsia]MMC READ CD[/].[/]</value>
</data>
<data name="Using_OmniDrive_raw_DVD_reading" xml:space="preserve">
<value>[slateblue1]Usando lectura de [fuchsia]DVD sin procesar de OmniDrive[/].[/]</value>
</data>
<data name="Using_Plextor_raw_DVD_reading" xml:space="preserve">
<value>[slateblue1]Usando lectura de [fuchsia]DVD sin procesar de Plextor[/].[/]</value>
</data>

View File

@@ -3490,6 +3490,9 @@ It has no sense to do it, and it will put too much strain on the tape.</value>
<data name="Using_Lite-On_raw_DVD_reading" xml:space="preserve">
<value>[slateblue1]Using [fuchsia]Lite-On raw DVD[/] reading[/]</value>
</data>
<data name="Using_OmniDrive_raw_DVD_reading" xml:space="preserve">
<value>[slateblue1]Using [fuchsia]OmniDrive[/] raw DVD reading[/]</value>
</data>
<data name="Using_ReadBuffer_3C_raw_DVD_reading" xml:space="preserve">
<value>[slateblue1]Using [fuchsia]ReadBuffer 3C raw DVD[/] reading[/]</value>
</data>