From ac491f6f5c0bacf40a6b9a5aea24b247945941e7 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 19 Oct 2015 04:32:16 +0100 Subject: [PATCH] Implemented SCSI VPDs 0x00 to 0x80. --- DiscImageChef.Decoders/ChangeLog | 6 + .../DiscImageChef.Decoders.csproj | 1 + DiscImageChef.Decoders/SCSI/EVPD.cs | 115 ++++++++++++++ DiscImageChef.Devices/ChangeLog | 5 + DiscImageChef.Devices/Device/ScsiCommands.cs | 2 +- DiscImageChef/ChangeLog | 5 + DiscImageChef/Commands/DeviceInfo.cs | 140 ++++++++++++++---- 7 files changed, 242 insertions(+), 32 deletions(-) create mode 100644 DiscImageChef.Decoders/SCSI/EVPD.cs diff --git a/DiscImageChef.Decoders/ChangeLog b/DiscImageChef.Decoders/ChangeLog index 28a56bae..e12c5873 100644 --- a/DiscImageChef.Decoders/ChangeLog +++ b/DiscImageChef.Decoders/ChangeLog @@ -1,3 +1,9 @@ +2015-10-19 Natalia Portillo + + * SCSI/EVPD.cs: + * DiscImageChef.Decoders.csproj: + Implemented SCSI VPDs 0x00 to 0x80. + 2015-10-19 Natalia Portillo * ATA/Identify.cs: diff --git a/DiscImageChef.Decoders/DiscImageChef.Decoders.csproj b/DiscImageChef.Decoders/DiscImageChef.Decoders.csproj index 35bc7403..3dda09b5 100644 --- a/DiscImageChef.Decoders/DiscImageChef.Decoders.csproj +++ b/DiscImageChef.Decoders/DiscImageChef.Decoders.csproj @@ -78,6 +78,7 @@ + diff --git a/DiscImageChef.Decoders/SCSI/EVPD.cs b/DiscImageChef.Decoders/SCSI/EVPD.cs new file mode 100644 index 00000000..aec85cb2 --- /dev/null +++ b/DiscImageChef.Decoders/SCSI/EVPD.cs @@ -0,0 +1,115 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : EVPD.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ 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 . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using DiscImageChef; + +namespace DiscImageChef.Decoders.SCSI +{ + public static class EVPD + { + /// + /// Decodes VPD page 0x00: Supported VPD pages + /// + /// A byte array containing all supported VPD pages. + /// Page 0x00. + public static byte[] DecodePage00(byte[] page) + { + if (page == null) + return null; + + if (page[1] != 0) + return null; + + if (page.Length != page[3] + 4) + return null; + + byte[] decoded = new byte[page.Length - 4]; + + Array.Copy(page, 4, decoded, 0, page.Length - 4); + + return decoded; + } + + /// + /// Decides VPD pages 0x01 to 0x7F: ASCII Information + /// + /// An ASCII string with the contents of the page. + /// Page 0x01-0x7F. + public static string DecodeASCIIPage(byte[] page) + { + if (page == null) + return null; + + if (page[1] == 0 || page[1] > 0x7F) + return null; + + if (page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page[4]]; + + Array.Copy(page, 5, ascii, 0, page[4]); + + return StringHandlers.CToString(ascii); + } + + /// + /// Decodes VPD page 0x80: Unit Serial Number + /// + /// The unit serial number. + /// Page 0x80. + public static string DecodePage80(byte[] page) + { + if (page == null) + return null; + + if (page[1] != 0x80) + return null; + + if (page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii); + } + } +} + diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index 05b98aca..7e822654 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,8 @@ +2015-10-19 Natalia Portillo + + * Device/ScsiCommands.cs: + Implemented SCSI VPDs 0x00 to 0x80. + 2015-10-18 Natalia Portillo * Device/AtaCommands.cs: diff --git a/DiscImageChef.Devices/Device/ScsiCommands.cs b/DiscImageChef.Devices/Device/ScsiCommands.cs index c1aedd3c..fef69af5 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands.cs @@ -174,7 +174,7 @@ namespace DiscImageChef.Devices if (sense) return true; - byte pagesLength = (byte)(buffer[4] + 5); + byte pagesLength = (byte)(buffer[3] + 4); cdb = new byte[] { (byte)Enums.ScsiCommands.Inquiry, 1, page, 0, pagesLength, 0 }; buffer = new byte[pagesLength]; diff --git a/DiscImageChef/ChangeLog b/DiscImageChef/ChangeLog index 3e43b197..060754fb 100644 --- a/DiscImageChef/ChangeLog +++ b/DiscImageChef/ChangeLog @@ -1,3 +1,8 @@ +2015-10-19 Natalia Portillo + + * Commands/DeviceInfo.cs: + Implemented SCSI VPDs 0x00 to 0x80. + 2015-10-19 Natalia Portillo * Commands/Decode.cs: diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs index 361c4e97..a410d45a 100644 --- a/DiscImageChef/Commands/DeviceInfo.cs +++ b/DiscImageChef/Commands/DeviceInfo.cs @@ -39,6 +39,7 @@ using System; using DiscImageChef.Devices; using System.IO; using DiscImageChef.Console; +using System.Text; namespace DiscImageChef.Commands { @@ -64,45 +65,35 @@ namespace DiscImageChef.Commands return; } - byte[] senseBuf; - byte[] inqBuf; + bool ata = false; + bool atapi = false; + bool scsi = false; + bool scsi83 = false; - bool sense = dev.ScsiInquiry(out inqBuf, out senseBuf); + string decodedAta = null; + string decodedAtapi = null; + string decodedScsi = null; + string scsiSerial = null; - if(sense) - { - DicConsole.ErrorWriteLine("SCSI error. Sense decoding not yet implemented."); - - #if DEBUG - FileStream senseFs = File.Open("sense.bin", FileMode.OpenOrCreate); - senseFs.Write(senseBuf, 0, senseBuf.Length); - #endif - } - else - DicConsole.WriteLine("SCSI OK"); - - DicConsole.WriteLine(Decoders.SCSI.Inquiry.Prettify(inqBuf)); + StringBuilder sb = null; Structs.AtaErrorRegistersCHS errorRegisters; byte[] ataBuf; - sense = dev.AtaIdentify(out ataBuf, out errorRegisters); + bool sense = dev.AtaIdentify(out ataBuf, out errorRegisters); if (sense) { - + if ((errorRegisters.status & 0x01) == 0x01 - && (errorRegisters.error & 0x04) == 0x04 - && errorRegisters.cylinderHigh == 0xEB - && errorRegisters.cylinderLow == 0x14) + && (errorRegisters.error & 0x04) == 0x04 + && errorRegisters.cylinderHigh == 0xEB + && errorRegisters.cylinderLow == 0x14) { - DicConsole.WriteLine("ATA error, but ATAPI signature detected."); sense = dev.AtapiIdentify(out ataBuf, out errorRegisters); if (sense) { - DicConsole.WriteLine("ATAPI error"); - DicConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.status); DicConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.error); DicConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.sectorCount); @@ -115,14 +106,12 @@ namespace DiscImageChef.Commands } else { - DicConsole.WriteLine("ATAPI OK"); - DicConsole.WriteLine(Decoders.ATA.Identify.Prettify(ataBuf)); + atapi = true; + decodedAtapi = Decoders.ATA.Identify.Prettify(ataBuf); } } else { - DicConsole.WriteLine("ATA error"); - DicConsole.DebugWriteLine("Device-Info command", "STATUS = 0x{0:X2}", errorRegisters.status); DicConsole.DebugWriteLine("Device-Info command", "ERROR = 0x{0:X2}", errorRegisters.error); DicConsole.DebugWriteLine("Device-Info command", "NSECTOR = 0x{0:X2}", errorRegisters.sectorCount); @@ -136,9 +125,98 @@ namespace DiscImageChef.Commands } else { - DicConsole.WriteLine("ATA OK"); - DicConsole.WriteLine(Decoders.ATA.Identify.Prettify(ataBuf)); - } + ata = true; + decodedAta = Decoders.ATA.Identify.Prettify(ataBuf); + } + + if (!ata) + { + byte[] senseBuf; + byte[] inqBuf; + + sense = dev.ScsiInquiry(out inqBuf, out senseBuf); + + if (sense) + { + DicConsole.ErrorWriteLine("SCSI error. Sense decoding not yet implemented."); + + #if DEBUG + FileStream senseFs = File.Open("sense.bin", FileMode.OpenOrCreate); + senseFs.Write(senseBuf, 0, senseBuf.Length); + #endif + } + else + { + scsi = true; + decodedScsi = Decoders.SCSI.Inquiry.Prettify(inqBuf); + + sense = dev.ScsiInquiry(out inqBuf, out senseBuf, 0x00); + + if (!sense) + { + byte[] pages = Decoders.SCSI.EVPD.DecodePage00(inqBuf); + + foreach (byte page in pages) + { + if (page >= 0x01 && page <= 0x7F) + { + sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); + if (!sense) + { + if(sb == null) + sb = new StringBuilder(); + sb.AppendFormat("Page 0x{0:X2}: ", Decoders.SCSI.EVPD.DecodeASCIIPage(inqBuf)).AppendLine(); + } + } + else if (page == 0x80) + { + sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); + if (!sense) + { + scsi83 = true; + scsiSerial = Decoders.SCSI.EVPD.DecodePage80(inqBuf); + } + } + else + { + if(page != 0x00) + DicConsole.DebugWriteLine("Device-Info command", "Found undecoded SCSI VPD page 0x{0:X2}", page); + } + } + } + } + + if (atapi) + { + DicConsole.WriteLine(decodedAtapi); + } + else if (scsi) + { + DicConsole.WriteLine("SCSI device"); + } + + if(scsi) + { + DicConsole.WriteLine(decodedScsi); + + if(scsi83) + DicConsole.WriteLine("Unit Serial Number: {0}", scsiSerial); + + if(sb != null) + { + DicConsole.WriteLine("ASCII VPDs:"); + DicConsole.WriteLine(sb.ToString()); + } + } + } + else + { + DicConsole.WriteLine("ATA device"); + DicConsole.WriteLine(decodedAta); + } + + if(!ata && !atapi && !scsi) + DicConsole.ErrorWriteLine("Unknown device type, cannot get information."); } } }