using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using Aaru.Checksums; using Aaru.CommonTypes.AaruMetadata; using Aaru.Helpers; using Marshal = Aaru.Helpers.Marshal; namespace Aaru.Images; public sealed partial class AaruFormat { #region IWritableOpticalImage Members /// public bool SetDumpHardware(List dumpHardware) { var blockMs = new MemoryStream(); var dumpMs = new MemoryStream(); byte[] structureBytes; foreach(DumpHardware dump in dumpHardware) { byte[] dumpManufacturer = null; byte[] dumpModel = null; byte[] dumpRevision = null; byte[] dumpFirmware = null; byte[] dumpSerial = null; byte[] dumpSoftwareName = null; byte[] dumpSoftwareVersion = null; byte[] dumpSoftwareOperatingSystem = null; if(!string.IsNullOrWhiteSpace(dump.Manufacturer)) dumpManufacturer = Encoding.UTF8.GetBytes(dump.Manufacturer); if(!string.IsNullOrWhiteSpace(dump.Model)) dumpModel = Encoding.UTF8.GetBytes(dump.Model); if(!string.IsNullOrWhiteSpace(dump.Revision)) dumpRevision = Encoding.UTF8.GetBytes(dump.Revision); if(!string.IsNullOrWhiteSpace(dump.Firmware)) dumpFirmware = Encoding.UTF8.GetBytes(dump.Firmware); if(!string.IsNullOrWhiteSpace(dump.Serial)) dumpSerial = Encoding.UTF8.GetBytes(dump.Serial); if(!string.IsNullOrWhiteSpace(dump.Software?.Name)) dumpSoftwareName = Encoding.UTF8.GetBytes(dump.Software.Name); if(!string.IsNullOrWhiteSpace(dump.Software?.Version)) dumpSoftwareVersion = Encoding.UTF8.GetBytes(dump.Software.Version); if(!string.IsNullOrWhiteSpace(dump.Software?.OperatingSystem)) dumpSoftwareOperatingSystem = Encoding.UTF8.GetBytes(dump.Software.OperatingSystem); var dumpEntry = new DumpHardwareEntry { ManufacturerLength = (uint)(dumpManufacturer?.Length + 1 ?? 0), ModelLength = (uint)(dumpModel?.Length + 1 ?? 0), RevisionLength = (uint)(dumpRevision?.Length + 1 ?? 0), FirmwareLength = (uint)(dumpFirmware?.Length + 1 ?? 0), SerialLength = (uint)(dumpSerial?.Length + 1 ?? 0), SoftwareNameLength = (uint)(dumpSoftwareName?.Length + 1 ?? 0), SoftwareVersionLength = (uint)(dumpSoftwareVersion?.Length + 1 ?? 0), SoftwareOperatingSystemLength = (uint)(dumpSoftwareOperatingSystem?.Length + 1 ?? 0), Extents = (uint)dump.Extents.Count }; structureBytes = new byte[Marshal.SizeOf()]; MemoryMarshal.Write(structureBytes, in dumpEntry); dumpMs.Write(structureBytes, 0, structureBytes.Length); if(dumpManufacturer != null) { dumpMs.Write(dumpManufacturer, 0, dumpManufacturer.Length); dumpMs.WriteByte(0); } if(dumpModel != null) { dumpMs.Write(dumpModel, 0, dumpModel.Length); dumpMs.WriteByte(0); } if(dumpRevision != null) { dumpMs.Write(dumpRevision, 0, dumpRevision.Length); dumpMs.WriteByte(0); } if(dumpFirmware != null) { dumpMs.Write(dumpFirmware, 0, dumpFirmware.Length); dumpMs.WriteByte(0); } if(dumpSerial != null) { dumpMs.Write(dumpSerial, 0, dumpSerial.Length); dumpMs.WriteByte(0); } if(dumpSoftwareName != null) { dumpMs.Write(dumpSoftwareName, 0, dumpSoftwareName.Length); dumpMs.WriteByte(0); } if(dumpSoftwareVersion != null) { dumpMs.Write(dumpSoftwareVersion, 0, dumpSoftwareVersion.Length); dumpMs.WriteByte(0); } if(dumpSoftwareOperatingSystem != null) { dumpMs.Write(dumpSoftwareOperatingSystem, 0, dumpSoftwareOperatingSystem.Length); dumpMs.WriteByte(0); } foreach(Extent extent in dump.Extents) { dumpMs.Write(BitConverter.GetBytes(extent.Start), 0, sizeof(ulong)); dumpMs.Write(BitConverter.GetBytes(extent.End), 0, sizeof(ulong)); } } Crc64Context.Data(dumpMs.ToArray(), out byte[] dumpCrc); var dumpBlock = new DumpHardwareHeader { Identifier = BlockType.DumpHardwareBlock, Entries = (ushort)dumpHardware.Count, Crc64 = Swapping.Swap(BitConverter.ToUInt64(dumpCrc, 0)), Length = (uint)dumpMs.Length }; structureBytes = new byte[Marshal.SizeOf()]; MemoryMarshal.Write(structureBytes, in dumpBlock); blockMs.Write(structureBytes, 0, structureBytes.Length); blockMs.Write(dumpMs.ToArray(), 0, (int)dumpMs.Length); byte[] blockBytes = blockMs.ToArray(); Status res = aaruf_set_dumphw(_context, blockBytes, (nuint)blockBytes.Length); ErrorMessage = StatusToErrorMessage(res); return res == Status.Ok; } /// public List DumpHardware { get { nuint length = 0; Status res = aaruf_get_dumphw(_context, null, ref length); if(res != Status.Ok && res != Status.BufferTooSmall) { ErrorMessage = StatusToErrorMessage(res); return null; } var buffer = new byte[length]; res = aaruf_get_dumphw(_context, buffer, ref length); if(res != Status.Ok) { ErrorMessage = StatusToErrorMessage(res); return null; } var memoryStream = new MemoryStream(buffer); var structureBytes = new byte[Marshal.SizeOf()]; memoryStream.EnsureRead(structureBytes, 0, structureBytes.Length); DumpHardwareHeader dumpBlock = Marshal.SpanToStructureLittleEndian(structureBytes); if(dumpBlock.Identifier != BlockType.DumpHardwareBlock) return null; structureBytes = new byte[dumpBlock.Length]; memoryStream.EnsureRead(structureBytes, 0, structureBytes.Length); memoryStream.Position -= structureBytes.Length; List dumpHardware = []; for(ushort i = 0; i < dumpBlock.Entries; i++) { structureBytes = new byte[Marshal.SizeOf()]; memoryStream.EnsureRead(structureBytes, 0, structureBytes.Length); DumpHardwareEntry dumpEntry = Marshal.SpanToStructureLittleEndian(structureBytes); var dump = new DumpHardware { Software = new Software(), Extents = [] }; byte[] tmp; if(dumpEntry.ManufacturerLength > 0) { tmp = new byte[dumpEntry.ManufacturerLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Manufacturer = Encoding.UTF8.GetString(tmp); } if(dumpEntry.ModelLength > 0) { tmp = new byte[dumpEntry.ModelLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Model = Encoding.UTF8.GetString(tmp); } if(dumpEntry.RevisionLength > 0) { tmp = new byte[dumpEntry.RevisionLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Revision = Encoding.UTF8.GetString(tmp); } if(dumpEntry.FirmwareLength > 0) { tmp = new byte[dumpEntry.FirmwareLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Firmware = Encoding.UTF8.GetString(tmp); } if(dumpEntry.SerialLength > 0) { tmp = new byte[dumpEntry.SerialLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Serial = Encoding.UTF8.GetString(tmp); } if(dumpEntry.SoftwareNameLength > 0) { tmp = new byte[dumpEntry.SoftwareNameLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Software.Name = Encoding.UTF8.GetString(tmp); } if(dumpEntry.SoftwareVersionLength > 0) { tmp = new byte[dumpEntry.SoftwareVersionLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Software.Version = Encoding.UTF8.GetString(tmp); } if(dumpEntry.SoftwareOperatingSystemLength > 0) { tmp = new byte[dumpEntry.SoftwareOperatingSystemLength - 1]; memoryStream.EnsureRead(tmp, 0, tmp.Length); memoryStream.Position += 1; dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); } tmp = new byte[16]; for(uint j = 0; j < dumpEntry.Extents; j++) { memoryStream.EnsureRead(tmp, 0, tmp.Length); dump.Extents.Add(new Extent { Start = BitConverter.ToUInt64(tmp, 0), End = BitConverter.ToUInt64(tmp, 8) }); } dump.Extents = dump.Extents.OrderBy(t => t.Start).ToList(); if(dump.Extents.Count > 0) dumpHardware.Add(dump); } if(dumpHardware.Count == 0) dumpHardware = null; return dumpHardware; } } #endregion // AARU_EXPORT int32_t AARU_CALL aaruf_set_dumphw(void *context, uint8_t *data, size_t length) [LibraryImport("libaaruformat", EntryPoint = "aaruf_set_dumphw", SetLastError = true)] [UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])] private static partial Status aaruf_set_dumphw(IntPtr context, [In] byte[] data, nuint length); // AARU_EXPORT int32_t AARU_CALL aaruf_get_dumphw(void *context, uint8_t *buffer, size_t *length) [LibraryImport("libaaruformat", EntryPoint = "aaruf_get_dumphw", SetLastError = true)] [UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])] private static partial Status aaruf_get_dumphw(IntPtr context, byte[] buffer, ref nuint length); }