mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
294 lines
13 KiB
C#
294 lines
13 KiB
C#
// /***************************************************************************
|
|
// Aaru Data Preservation Suite
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// Filename : ScsiEvpd.cs
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
//
|
|
// Component : Aaru Server.
|
|
//
|
|
// --[ Description ] ----------------------------------------------------------
|
|
//
|
|
// Decodes SCSI EVPDs from reports.
|
|
//
|
|
// --[ 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-2024 Natalia Portillo
|
|
// ****************************************************************************/
|
|
|
|
using Aaru.CommonTypes.Metadata;
|
|
using Aaru.Decoders.SCSI;
|
|
|
|
namespace Aaru.Server.New.Core;
|
|
|
|
public static class ScsiEvpd
|
|
{
|
|
/// <summary>
|
|
/// Takes the SCSI EVPD part of a device report and prints it as a list key=value pairs to be sequenced by ASP.NET
|
|
/// in the rendering
|
|
/// </summary>
|
|
/// <param name="pages">EVPD pages</param>
|
|
/// <param name="vendor">SCSI vendor string</param>
|
|
/// <param name="evpdPages">List to put the key=value pairs on</param>
|
|
public static void Report(IEnumerable<ScsiPage> pages, string vendor,
|
|
out Dictionary<string, List<string>> evpdPages)
|
|
{
|
|
evpdPages = new Dictionary<string, List<string>>();
|
|
vendor = vendor.ToLowerInvariant();
|
|
|
|
foreach(ScsiPage evpd in pages)
|
|
{
|
|
string header = evpd.page switch
|
|
{
|
|
>= 0x01 and <= 0x7F => $"EVPD page {evpd.page:X2}h: ASCII information",
|
|
0x81 => "EVPD page 81h: Implemented operating definitions",
|
|
0x82 => "EVPD page 82h: ASCII implemented operating definition",
|
|
0x83 => "EVPD page 83h: Device identification",
|
|
0x84 => "EVPD page 84h: Software Interface Identifiers",
|
|
0x85 => "EVPD page 85h: Management Network Addresses",
|
|
0x86 => "EVPD page 86h: Extended INQUIRY Data",
|
|
0x89 => "EVPD page 89h: SCSI to ATA Translation Layer Data",
|
|
0xB0 => "EVPD page B0h: Sequential-access Device Capabilities",
|
|
0xB2 => "EVPD page B2h: TapeAlert Supported Flags Bitmap",
|
|
0xB4 => "EVPD page B4h: Unknown",
|
|
0xC0 when vendor == "quantum" =>
|
|
"EVPD page C0h: Quantum Firmware Build Information page",
|
|
0xC0 when vendor == "seagate" => "EVPD page C0h: Seagate Firmware Numbers page",
|
|
0xC0 when vendor == "ibm" => "EVPD page C0h: IBM Drive Component Revision Levels page",
|
|
0xC1 when vendor == "ibm" => "EVPD page C1h: IBM Drive Serial Numbers page",
|
|
0xC0 or 0xC1 when vendor == "certance" =>
|
|
$"EVPD page {evpd.page:X2}h: Certance Drive Component Revision Levels page",
|
|
0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 when vendor == "certance" =>
|
|
$"EVPD page {evpd.page:X2}h: Certance Drive Component Serial Number page",
|
|
0xC0 when vendor == "hp" => "EVPD page C0h: HP Drive Firmware Revision Levels page:",
|
|
0xC1 when vendor == "hp" => "EVPD page C1h: HP Drive Hardware Revision Levels page",
|
|
0xC2 when vendor == "hp" => "EVPD page C2h: HP Drive PCA Revision Levels page",
|
|
0xC3 when vendor == "hp" => "EVPD page C3h: HP Drive Mechanism Revision Levels page",
|
|
0xC4 when vendor == "hp" =>
|
|
"EVPD page C4h: HP Drive Head Assembly Revision Levels page",
|
|
0xC5 when vendor == "hp" => "EVPD page C5h: HP Drive ACI Revision Levels page",
|
|
0xDF when vendor == "certance" => "EVPD page DFh: Certance drive status page",
|
|
_ => $"EVPD page {evpd.page:X2}h: Undecoded"
|
|
};
|
|
|
|
List<string> decoded;
|
|
string? ascii;
|
|
|
|
switch(evpd.page)
|
|
{
|
|
case >= 0x01 and <= 0x7F:
|
|
ascii = EVPD.DecodeASCIIPage(evpd.value);
|
|
|
|
if(ascii is not null)
|
|
decoded = [ascii];
|
|
else
|
|
decoded = [];
|
|
|
|
break;
|
|
case 0x81:
|
|
ascii = EVPD.PrettifyPage_81(evpd.value);
|
|
|
|
if(ascii is not null)
|
|
decoded = [ascii];
|
|
else
|
|
decoded = [];
|
|
|
|
break;
|
|
case 0x82:
|
|
ascii = EVPD.DecodePage82(evpd.value);
|
|
|
|
if(ascii is not null)
|
|
decoded = [ascii];
|
|
else
|
|
decoded = [];
|
|
|
|
break;
|
|
case 0x83:
|
|
decoded = EVPD.PrettifyPage_83(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
break;
|
|
case 0x84:
|
|
decoded = EVPD.PrettifyPage_84(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0x85:
|
|
decoded = EVPD.PrettifyPage_85(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0x86:
|
|
decoded = EVPD.PrettifyPage_86(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0x89:
|
|
decoded = EVPD.PrettifyPage_89(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xB0:
|
|
decoded = EVPD.PrettifyPage_B0(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xB2:
|
|
decoded = [$"0x{EVPD.DecodePageB2(evpd.value):X16}"];
|
|
|
|
break;
|
|
case 0xB4:
|
|
ascii = EVPD.DecodePageB4(evpd.value);
|
|
|
|
if(ascii is not null)
|
|
decoded = [ascii];
|
|
else
|
|
decoded = [];
|
|
|
|
break;
|
|
case 0xC0 when vendor == "quantum":
|
|
decoded = EVPD.PrettifyPage_C0_Quantum(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC0 when vendor == "seagate":
|
|
decoded = EVPD.PrettifyPage_C0_Seagate(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC0 when vendor == "ibm":
|
|
decoded = EVPD.PrettifyPage_C0_IBM(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC1 when vendor == "ibm":
|
|
decoded = EVPD.PrettifyPage_C1_IBM(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC0 or 0xC1 when vendor == "certance":
|
|
decoded = EVPD.PrettifyPage_C0_C1_Certance(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 when vendor == "certance":
|
|
decoded = EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5 when vendor == "hp":
|
|
decoded = EVPD.PrettifyPage_C0_to_C5_HP(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
case 0xDF when vendor == "certance":
|
|
decoded = EVPD.PrettifyPage_DF_Certance(evpd.value)
|
|
?.Replace("\t", "")
|
|
.Split(Environment.NewLine,
|
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
|
.Skip(1)
|
|
.ToList() ?? [];
|
|
|
|
;
|
|
|
|
break;
|
|
default:
|
|
decoded = [];
|
|
|
|
break;
|
|
}
|
|
|
|
evpdPages.Add(header, decoded);
|
|
}
|
|
}
|
|
} |