From 734c53fc2b96b9fa126ed3de0e0856f587ed0ba8 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 13 Oct 2016 06:59:56 +0100 Subject: [PATCH] Add EVPD page 85h, management network addresses. --- ChangeLog | 4 + SCSI/EVPD.cs | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+) diff --git a/ChangeLog b/ChangeLog index be020ff00..55f6d595d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-10-13 Natalia Portillo + + * EVPD.cs: Add EVPD page 85h, management network addresses. + 2016-10-13 Natalia Portillo * EVPD.cs: diff --git a/SCSI/EVPD.cs b/SCSI/EVPD.cs index b570be327..075a545b7 100644 --- a/SCSI/EVPD.cs +++ b/SCSI/EVPD.cs @@ -683,6 +683,287 @@ namespace DiscImageChef.Decoders.SCSI } #endregion EVPD Page 0x83: Device identification page + + #region EVPD Page 0x84: Software Interface Identification page + + public struct SoftwareIdentifier + { + /// + /// EUI-48 identifier + /// + public byte[] Identifier; + } + + /// + /// Software Interface Identification page + /// Page code 0x84 + /// + public struct Page_84 + { + /// + /// The peripheral qualifier. + /// + public PeripheralQualifiers PeripheralQualifier; + /// + /// The type of the peripheral device. + /// + public PeripheralDeviceTypes PeripheralDeviceType; + /// + /// The page code. + /// + public byte PageCode; + /// + /// The length of the page. + /// + public byte PageLength; + /// + /// The descriptors. + /// + public SoftwareIdentifier[] Identifiers; + } + + public static Page_84? DecodePage_84(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0x84) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 10) + return null; + + Page_84 decoded = new Page_84(); + + decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); + decoded.PageLength = (byte)(pageResponse[3] + 4); + + int position = 4; + List identifiers = new List(); + + while(position < pageResponse.Length) + { + SoftwareIdentifier identifier = new SoftwareIdentifier(); + identifier.Identifier = new byte[6]; + Array.Copy(pageResponse, position, identifier.Identifier, 0, 6); + identifiers.Add(identifier); + position += 6; + } + + decoded.Identifiers = identifiers.ToArray(); + + return decoded; + } + + public static string PrettifyPage_84(byte[] pageResponse) + { + return PrettifyPage_84(DecodePage_84(pageResponse)); + } + + public static string PrettifyPage_84(Page_84? modePage) + { + if(!modePage.HasValue) + return null; + + Page_84 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Software Interface Identifiers:"); + + if(page.Identifiers.Length == 0) + { + sb.AppendLine("\tThere are no identifiers"); + return sb.ToString(); + } + + foreach(SoftwareIdentifier identifier in page.Identifiers) + { + sb.AppendFormat("\t{0:X2}", identifier.Identifier[0]); + for(int i = 1; i < identifier.Identifier.Length; i++) + sb.AppendFormat(":{0:X2}", identifier.Identifier[i]); + sb.AppendLine(); + } + + return sb.ToString(); + } + + #endregion EVPD Page 0x84: Software Interface Identification page + + #region EVPD Page 0x85: Management Network Addresses page + + public enum NetworkServiceTypes : byte + { + Unspecified = 0, + StorageConf = 1, + Diagnostics = 2, + Status = 3, + Logging = 4, + CodeDownload = 5 + } + + public struct NetworkDescriptor + { + /// + /// Identifies which device the identifier associates with + /// + public IdentificationAssociation Association; + /// + /// Defines the type of the identifier + /// + public NetworkServiceTypes Type; + /// + /// Length of the identifier + /// + public ushort Length; + /// + /// Binary identifier + /// + public byte[] Address; + } + + /// + /// Device identification page + /// Page code 0x85 + /// + public struct Page_85 + { + /// + /// The peripheral qualifier. + /// + public PeripheralQualifiers PeripheralQualifier; + /// + /// The type of the peripheral device. + /// + public PeripheralDeviceTypes PeripheralDeviceType; + /// + /// The page code. + /// + public byte PageCode; + /// + /// The length of the page. + /// + public ushort PageLength; + /// + /// The descriptors. + /// + public NetworkDescriptor[] Descriptors; + } + + public static Page_85? DecodePage_85(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0x85) + return null; + + if((pageResponse[2] << 4) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 4) + return null; + + Page_85 decoded = new Page_85(); + + decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); + decoded.PageLength = (ushort)((pageResponse[2] << 4) + pageResponse[3] + 4); + + int position = 4; + List descriptors = new List(); + + while(position < pageResponse.Length) + { + NetworkDescriptor descriptor = new NetworkDescriptor(); + descriptor.Association = (IdentificationAssociation)((pageResponse[position] & 0x60) >> 5); + descriptor.Type = (NetworkServiceTypes)(pageResponse[position] & 0x1F); + descriptor.Length = (ushort)((pageResponse[position + 2] << 4) + pageResponse[position + 3]); + descriptor.Address = new byte[descriptor.Length]; + Array.Copy(pageResponse, position + 4, descriptor.Address, 0, descriptor.Length); + + position += 4 + descriptor.Length; + descriptors.Add(descriptor); + } + + decoded.Descriptors = descriptors.ToArray(); + + return decoded; + } + + public static string PrettifyPage_85(byte[] pageResponse) + { + return PrettifyPage_85(DecodePage_85(pageResponse)); + } + + public static string PrettifyPage_85(Page_85? modePage) + { + if(!modePage.HasValue) + return null; + + Page_85 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Management Network Addresses:"); + + if(page.Descriptors.Length == 0) + { + sb.AppendLine("\tThere are no addresses"); + return sb.ToString(); + } + + foreach(NetworkDescriptor descriptor in page.Descriptors) + { + switch(descriptor.Association) + { + case IdentificationAssociation.LogicalUnit: + sb.AppendLine("\tIdentifier belongs to addressed logical unit"); + break; + case IdentificationAssociation.TargetPort: + sb.AppendLine("\tIdentifier belongs to target port"); + break; + case IdentificationAssociation.TargetDevice: + sb.AppendLine("\tIdentifier belongs to target device that contains the addressed logical unit"); + break; + default: + sb.AppendFormat("\tIndentifier has unknown association with code {0}", (byte)descriptor.Association).AppendLine(); + break; + } + + switch(descriptor.Type) + { + case NetworkServiceTypes.CodeDownload: + sb.AppendFormat("Address for code download: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + case NetworkServiceTypes.Diagnostics: + sb.AppendFormat("Address for diagnostics: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + case NetworkServiceTypes.Logging: + sb.AppendFormat("Address for logging: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + case NetworkServiceTypes.Status: + sb.AppendFormat("Address for status: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + case NetworkServiceTypes.StorageConf: + sb.AppendFormat("Address for storage configuration service: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + case NetworkServiceTypes.Unspecified: + sb.AppendFormat("Unspecified address: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; + default: + sb.AppendFormat("Address of unknown type {1}: {0}", StringHandlers.CToString(descriptor.Address), (byte)descriptor.Type).AppendLine(); + break; + } + } + + return sb.ToString(); + } + + #endregion EVPD Page 0x85: Management Network Addresses page + } }