diff --git a/Img2Ffu.Library/Img2Ffu.Library.csproj b/Img2Ffu.Library/Img2Ffu.Library.csproj
deleted file mode 100644
index 1e598df..0000000
--- a/Img2Ffu.Library/Img2Ffu.Library.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- net8.0-windows
- enable
- enable
- AnyCPU;ARM32;ARM64;x86;x64
- true
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Img2Ffu.Library/Reader/Compression/WindowsNativeCompression.cs b/Img2Ffu.Library/Reader/Compression/WindowsNativeCompression.cs
deleted file mode 100644
index d2da77c..0000000
--- a/Img2Ffu.Library/Reader/Compression/WindowsNativeCompression.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Compression
-{
- internal class WindowsNativeCompression
- {
- [DllImport("ntdll.dll")]
- private static extern uint RtlGetCompressionWorkSpaceSize(ushort CompressionFormatAndEngine, out uint CompressBufferWorkSpaceSize, out uint CompressFragmentWorkSpaceSize);
-
- [DllImport("ntdll.dll")]
- private static extern uint RtlDecompressBufferEx(ushort CompressionFormat, byte[] UncompressedBuffer, int UncompressedBufferSize, byte[] CompressedBuffer, int CompressedBufferSize, out int FinalUncompressedSize, byte[] WorkSpace);
-
- [DllImport("ntdll.dll")]
- private static extern uint RtlCompressBuffer(ushort CompressionFormatAndEngine, byte[] UncompressedBuffer, int UncompressedBufferSize, byte[] CompressedBuffer, int CompressedBufferSize, int UncompressedChunkSize, out int FinalCompressedSize, byte[] WorkSpace);
-
- public static byte[] Decompress(WindowsNativeCompressionAlgorithm CompressionFormat, byte[] CompressedBuffer, int UncompressedBufferSize)
- {
- uint ntStatus = RtlGetCompressionWorkSpaceSize((ushort)CompressionFormat, out uint compressBufferWorkSpaceSize, out _);
- if (ntStatus != 0)
- {
- throw new Exception($"Cannot get decompress workspace size! NTSTATUS=0x{ntStatus:X8}");
- }
-
- byte[] UncompressedBuffer = new byte[UncompressedBufferSize];
- byte[] workSpace = new byte[compressBufferWorkSpaceSize];
-
-
- ntStatus = RtlDecompressBufferEx((ushort)CompressionFormat, UncompressedBuffer, UncompressedBuffer.Length, CompressedBuffer, CompressedBuffer.Length, out _, workSpace);
- return ntStatus != 0 ? throw new Exception($"Cannot decompress buffer! NTSTATUS=0x{ntStatus:X8}") : UncompressedBuffer;
- }
-
- public static byte[] Compress(WindowsNativeCompressionAlgorithm CompressionFormat, byte[] UncompressedBuffer, int CompressedBufferSize)
- {
- uint ntStatus = RtlGetCompressionWorkSpaceSize((ushort)CompressionFormat, out uint compressBufferWorkSpaceSize, out _);
- if (ntStatus != 0)
- {
- throw new Exception($"Cannot get compression workspace size! NTSTATUS=0x{ntStatus:X8}");
- }
-
- byte[] CompressedBuffer = new byte[CompressedBufferSize];
- byte[] workSpace = new byte[compressBufferWorkSpaceSize];
-
-
- ntStatus = RtlCompressBuffer((ushort)CompressionFormat, UncompressedBuffer, UncompressedBuffer.Length, CompressedBuffer, CompressedBuffer.Length, 4096, out _, workSpace);
- return ntStatus != 0 ? throw new Exception($"Cannot compress buffer! NTSTATUS=0x{ntStatus:X8}") : CompressedBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/Compression/WindowsNativeCompressionAlgorithm.cs b/Img2Ffu.Library/Reader/Compression/WindowsNativeCompressionAlgorithm.cs
deleted file mode 100644
index f15e365..0000000
--- a/Img2Ffu.Library/Reader/Compression/WindowsNativeCompressionAlgorithm.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Img2Ffu.Reader.Compression
-{
- [Flags]
- public enum WindowsNativeCompressionAlgorithm
- {
- COMPRESSION_FORMAT_NONE = 0x0000,
- COMPRESSION_ENGINE_STANDARD = 0x0000,
- COMPRESSION_FORMAT_DEFAULT = 0x0001,
- COMPRESSION_FORMAT_LZNT1 = 0x0002,
- COMPRESSION_FORMAT_XPRESS = 0x0003,
- COMPRESSION_FORMAT_XPRESS_HUFF = 0x0004,
- COMPRESSION_ENGINE_MAXIMUM = 0x0100,
- COMPRESSION_ENGINE_HIBER = 0x0200
- }
-}
diff --git a/Img2Ffu.Library/Reader/Data/ImageFlash.cs b/Img2Ffu.Library/Reader/Data/ImageFlash.cs
deleted file mode 100644
index 5d618ac..0000000
--- a/Img2Ffu.Library/Reader/Data/ImageFlash.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-using Img2Ffu.Reader.Compression;
-using Img2Ffu.Reader.Enums;
-using Img2Ffu.Reader.Structs;
-using System.Text;
-
-namespace Img2Ffu.Reader.Data
-{
- internal class ImageFlash
- {
- public ImageHeader ImageHeader;
- public string ManifestData = "";
- public byte[] Padding = [];
- public readonly List Stores = [];
-
- private readonly long DataBlocksPosition;
- private readonly long InitialStreamPosition;
-
-
- public ImageFlash(Stream stream)
- {
- InitialStreamPosition = stream.Position;
- ImageHeader = stream.ReadStructure();
-
- if (ImageHeader.Signature != "ImageFlash ")
- {
- throw new InvalidDataException("Invalid Image Header Signature!");
- }
-
- byte[] manifestDataBuffer = new byte[ImageHeader.ManifestLength];
- _ = stream.Read(manifestDataBuffer, 0, (int)ImageHeader.ManifestLength);
- ASCIIEncoding asciiEncoding = new();
- ManifestData = asciiEncoding.GetString(manifestDataBuffer);
-
- long Position = stream.Position;
- if (Position % (ImageHeader.ChunkSize * 1024) > 0)
- {
- long paddingSize = (ImageHeader.ChunkSize * 1024) - (Position % (ImageHeader.ChunkSize * 1024));
- Padding = new byte[paddingSize];
- _ = stream.Read(Padding, 0, (int)paddingSize);
- }
-
- Store store = new(stream);
- Stores.Add(store);
-
- if (store.StoreHeader.MajorVersion == 2 && store.StoreHeader.FullFlashMajorVersion == 2)
- {
- for (uint i = 2; i <= store.StoreHeaderV2.NumberOfStores; i++)
- {
- Stores.Add(new Store(stream));
- }
- }
-
- DataBlocksPosition = stream.Position;
- }
-
-
- public ulong GetImageBlockCount()
- {
- ulong imageBlockCount = (ulong)(DataBlocksPosition - InitialStreamPosition) / (ImageHeader.ChunkSize * 1024);
- ulong storeBlockCount = GetDataBlockCount();
- return imageBlockCount + storeBlockCount;
- }
-
- public byte[] GetImageBlock(Stream Stream, ulong dataBlockIndex)
- {
- ulong imageBlockCount = (ulong)(DataBlocksPosition - InitialStreamPosition) / (ImageHeader.ChunkSize * 1024);
-
- // The data block is within the image headers
- if (dataBlockIndex < imageBlockCount)
- {
- byte[] dataBlock = new byte[(ImageHeader.ChunkSize * 1024)];
- ulong dataBlockPosition = (ulong)InitialStreamPosition + (dataBlockIndex * (ImageHeader.ChunkSize * 1024));
-
- _ = Stream.Seek((long)dataBlockPosition, SeekOrigin.Begin);
- _ = Stream.Read(dataBlock, 0, dataBlock.Length);
-
- return dataBlock;
- }
- // The data block is within the store data blocks, those may be compressed
- else
- {
- return GetDataBlock(Stream, dataBlockIndex - imageBlockCount);
- }
- }
-
-
- public ulong GetDataBlockCount()
- {
- ulong dataBlockCount = 0;
- foreach (Store store in Stores)
- {
- dataBlockCount += (ulong)store.WriteDescriptors.LongCount();
- }
- return dataBlockCount;
- }
-
- public byte[] GetDataBlock(Stream Stream, ulong dataBlockIndex)
- {
- ulong dataBlockIndexOffset = 0;
- for (ulong storeIndex = 0; storeIndex < (ulong)Stores.Count; storeIndex++)
- {
- ulong storeDataBlockCount = GetStoreDataBlockCount(storeIndex);
- if (dataBlockIndexOffset + storeDataBlockCount > dataBlockIndex)
- {
- return GetStoreDataBlock(Stream, storeIndex, dataBlockIndex - dataBlockIndexOffset);
- }
-
- dataBlockIndexOffset += storeDataBlockCount;
- }
-
- throw new Exception("Invalid data block index value");
- }
-
-
- public ulong GetStoreDataBlockCount(ulong storeIndex)
- {
- return (ulong)Stores[(int)storeIndex].WriteDescriptors.LongCount();
- }
-
- public byte[] GetStoreDataBlock(Stream Stream, ulong storeIndex, ulong dataBlockIndex)
- {
- ulong dataBlockPosition = (ulong)DataBlocksPosition;
- for (ulong s = 0; s < storeIndex; s++)
- {
- Store store = Stores[(int)s];
- if (store.CompressionAlgorithm != 0)
- {
- foreach (WriteDescriptor writeDescriptor in store.WriteDescriptors)
- {
- dataBlockPosition += writeDescriptor.DataSize;
- }
- }
- else
- {
- dataBlockPosition += store.StoreHeader.WriteDescriptorCount * store.StoreHeader.BlockSize;
- }
- }
-
- Store currentStore = Stores[(int)storeIndex];
- byte[] dataBlock = new byte[currentStore.StoreHeader.BlockSize];
-
- CompressionAlgorithm compressionAlgorithm = (CompressionAlgorithm)currentStore.CompressionAlgorithm;
-
- if (compressionAlgorithm != CompressionAlgorithm.None)
- {
- for (ulong i = 0; i < dataBlockIndex; i++)
- {
- WriteDescriptor writeDescriptor = currentStore.WriteDescriptors[(int)i];
- dataBlockPosition += writeDescriptor.DataSize;
- }
-
- WriteDescriptor currentWriteDescriptor = currentStore.WriteDescriptors[(int)dataBlockIndex];
- uint compressedDataBlockSize = currentWriteDescriptor.DataSize;
- byte[] compressedDataBlock = new byte[compressedDataBlockSize];
-
- _ = Stream.Seek((long)dataBlockPosition, SeekOrigin.Begin);
- _ = Stream.Read(compressedDataBlock, 0, compressedDataBlock.Length);
-
- switch ((CompressionAlgorithm)currentStore.CompressionAlgorithm)
- {
- case CompressionAlgorithm.LZNT1:
- {
- dataBlock = WindowsNativeCompression.Decompress(WindowsNativeCompressionAlgorithm.COMPRESSION_FORMAT_LZNT1, compressedDataBlock, (int)currentStore.StoreHeader.BlockSize);
- break;
- }
- case CompressionAlgorithm.Default:
- case CompressionAlgorithm.XPRESS:
- {
- dataBlock = WindowsNativeCompression.Decompress(WindowsNativeCompressionAlgorithm.COMPRESSION_FORMAT_XPRESS, compressedDataBlock, (int)currentStore.StoreHeader.BlockSize);
- break;
- }
- case CompressionAlgorithm.XPRESS_HUFF:
- {
- dataBlock = WindowsNativeCompression.Decompress(WindowsNativeCompressionAlgorithm.COMPRESSION_FORMAT_XPRESS_HUFF, compressedDataBlock, (int)currentStore.StoreHeader.BlockSize);
- break;
- }
- default:
- {
- throw new NotImplementedException("The compression algorithm this data block uses is not currently implemented.");
- }
- }
- }
- else
- {
- dataBlockPosition += dataBlockIndex * currentStore.StoreHeader.BlockSize;
-
- _ = Stream.Seek((long)dataBlockPosition, SeekOrigin.Begin);
- _ = Stream.Read(dataBlock, 0, dataBlock.Length);
- }
-
- return dataBlock;
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/Data/SignedImage.cs b/Img2Ffu.Library/Reader/Data/SignedImage.cs
deleted file mode 100644
index 8990809..0000000
--- a/Img2Ffu.Library/Reader/Data/SignedImage.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using Img2Ffu.Reader.Structs;
-using System.Collections;
-using System.Security.Cryptography;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
-
-namespace Img2Ffu.Reader.Data
-{
- internal class SignedImage
- {
- public SecurityHeader SecurityHeader;
- public byte[] Catalog;
- public byte[] TableOfHashes;
- public byte[] Padding = [];
- public ImageFlash Image;
-
- public ulong HeaderSize
- {
- get;
- }
- public int ChunkSize => (int)(SecurityHeader.ChunkSizeInKB * 1024);
- public ulong TotalChunkCount => Image.GetImageBlockCount();
-
- public readonly List BlockHashes = [];
- public X509Certificate? Certificate;
-
- private readonly Stream Stream;
-
- public SignedImage(Stream stream)
- {
- Stream = stream;
-
- SecurityHeader = stream.ReadStructure();
-
- if (SecurityHeader.Signature != "SignedImage ")
- {
- throw new InvalidDataException("Invalid Security Header Signature!");
- }
-
- Catalog = new byte[SecurityHeader.CatalogSize];
- _ = stream.Read(Catalog, 0, (int)SecurityHeader.CatalogSize);
-
- TableOfHashes = new byte[SecurityHeader.HashTableSize];
- _ = stream.Read(TableOfHashes, 0, (int)SecurityHeader.HashTableSize);
-
- long Position = stream.Position;
- uint sizeOfBlock = SecurityHeader.ChunkSizeInKB * 1024;
- if (Position % sizeOfBlock > 0)
- {
- long paddingSize = sizeOfBlock - (Position % sizeOfBlock);
- Padding = new byte[paddingSize];
- _ = stream.Read(Padding, 0, (int)paddingSize);
- }
-
- try
- {
- Certificate = new X509Certificate(Catalog);
- }
- catch { }
-
- Image = new ImageFlash(stream);
-
- HeaderSize = (ulong)stream.Position;
-
- ParseBlockHashes();
- }
-
- private void ParseBlockHashes()
- {
- BlockHashes.Clear();
-
- ulong numberOfBlocksToVerify = Image.GetImageBlockCount();
- ulong sizeOfHash = (ulong)TableOfHashes.LongLength / numberOfBlocksToVerify;
-
- for (int i = 0; i < TableOfHashes.Length; i += (int)sizeOfHash)
- {
- BlockHashes.Add(TableOfHashes[i..(i + (int)sizeOfHash)]);
- }
- }
-
- private uint GetImageHeaderPosition()
- {
- uint sizeOfBlock = SecurityHeader.ChunkSizeInKB * 1024;
- uint ImageHeaderPosition = SecurityHeader.Size + SecurityHeader.CatalogSize + SecurityHeader.HashTableSize;
- if (ImageHeaderPosition % sizeOfBlock > 0)
- {
- uint paddingSize = sizeOfBlock - (ImageHeaderPosition % sizeOfBlock);
- ImageHeaderPosition += paddingSize;
- }
- return ImageHeaderPosition;
- }
-
- public void VerifyFFU()
- {
- ulong numberOfBlocksToVerify = Image.GetImageBlockCount();
-
- long oldPosition = Stream.Position;
-
- using BinaryReader binaryReader = new(Stream, Encoding.ASCII, true);
- using BinaryReader hashTableBinaryReader = new(new MemoryStream(TableOfHashes));
-
- for (ulong i = 0; i < numberOfBlocksToVerify; i++)
- {
- Console.Title = $"{i + 1}/{numberOfBlocksToVerify}";
-
- if (SecurityHeader.AlgorithmId == 0x0000800c) // SHA256 Algorithm ID
- {
- byte[] block = Image.GetImageBlock(Stream, i);
- byte[] hash = SHA256.HashData(block);
- byte[] hashTableHash = BlockHashes.ElementAt((int)i);
-
- if (!StructuralComparisons.StructuralEqualityComparer.Equals(hash, hashTableHash))
- {
- _ = Stream.Seek(oldPosition, SeekOrigin.Begin);
- throw new InvalidDataException($"The FFU image contains a mismatched hash value at chunk {i}. " +
- $"Expected: {BitConverter.ToString(hashTableHash).Replace("-", "")} " +
- $"Computed: {BitConverter.ToString(hash).Replace("-", "")}");
- }
- }
- else
- {
- throw new InvalidDataException($"Unknown Hash algorithm id: {SecurityHeader.AlgorithmId}");
- }
- }
-
- Console.Title = $"{numberOfBlocksToVerify}/{numberOfBlocksToVerify}";
-
- _ = Stream.Seek(oldPosition, SeekOrigin.Begin);
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Data/Store.cs b/Img2Ffu.Library/Reader/Data/Store.cs
deleted file mode 100644
index daa7344..0000000
--- a/Img2Ffu.Library/Reader/Data/Store.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using Img2Ffu.Reader.Enums;
-using Img2Ffu.Reader.Structs;
-using System.Text;
-
-namespace Img2Ffu.Reader.Data
-{
- internal class Store
- {
- public StoreHeader StoreHeader;
- public uint CompressionAlgorithm;
- public StoreHeaderV2 StoreHeaderV2;
- public string DevicePath = ""; // Device path has no NUL at then end (V2 only)
- public readonly List ValidationDescriptor = [];
- public readonly List WriteDescriptors = [];
- public readonly List PlatformIDs = [];
- public byte[] Padding = [];
- public readonly FFUVersion FFUVersion;
-
- public Store(Stream stream)
- {
- StoreHeader = stream.ReadStructure();
-
- int lastFinding = 0;
- for (int i = 0; i < StoreHeader.PlatformId.Length; i++)
- {
- if (StoreHeader.PlatformId[i] == '\0')
- {
- if (i == lastFinding)
- {
- break;
- }
-
- ASCIIEncoding asciiEnconding = new();
- string PlatformID = asciiEnconding.GetString(StoreHeader.PlatformId[lastFinding..i]);
- PlatformIDs.Add(PlatformID);
- lastFinding = i + 1;
- }
- }
-
- FFUVersion = GetFFUVersion();
-
- switch (FFUVersion)
- {
- case FFUVersion.V2:
- {
- StoreHeaderV2 = stream.ReadStructure();
- byte[] stringBytes = new byte[StoreHeaderV2.DevicePathLength * 2];
- _ = stream.Read(stringBytes, 0, stringBytes.Length);
- UnicodeEncoding unicodeEncoding = new();
- DevicePath = unicodeEncoding.GetString(stringBytes);
- break;
- }
- case FFUVersion.V1_COMPRESSED:
- {
- using BinaryReader binaryReader = new(stream, Encoding.ASCII, true);
- CompressionAlgorithm = binaryReader.ReadUInt32();
- break;
- }
- }
-
- for (uint i = 0; i < StoreHeader.ValidateDescriptorCount; i++)
- {
- ValidationDescriptor.Add(new ValidationDescriptor(stream));
- }
-
- for (uint i = 0; i < StoreHeader.WriteDescriptorCount; i++)
- {
- WriteDescriptors.Add(new WriteDescriptor(stream, FFUVersion));
- }
-
- long Position = stream.Position;
- if (Position % StoreHeader.BlockSize > 0)
- {
- long paddingSize = StoreHeader.BlockSize - (Position % StoreHeader.BlockSize);
- Padding = new byte[paddingSize];
- _ = stream.Read(Padding, 0, (int)paddingSize);
- }
- }
-
- public override string ToString()
- {
- return $"{{StoreHeader: {StoreHeader}, StoreHeaderV2: {StoreHeaderV2}, DevicePath: {DevicePath}}}";
- }
-
- private FFUVersion GetFFUVersion()
- {
- return (StoreHeader.MajorVersion, StoreHeader.FullFlashMajorVersion) switch
- {
- (1, 2) => FFUVersion.V1,
- (1, 3) => FFUVersion.V1_COMPRESSED,
- (2, 2) => FFUVersion.V2,
- _ => throw new InvalidDataException($"Unsupported FFU Store Format! MajorVersion: {StoreHeader.MajorVersion} FullFlashMajorVersion: {StoreHeader.FullFlashMajorVersion}"),
- };
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/Data/ValidationDescriptor.cs b/Img2Ffu.Library/Reader/Data/ValidationDescriptor.cs
deleted file mode 100644
index 0173ace..0000000
--- a/Img2Ffu.Library/Reader/Data/ValidationDescriptor.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using Img2Ffu.Reader.Structs;
-
-namespace Img2Ffu.Reader.Data
-{
- internal class ValidationDescriptor
- {
- public ValidationEntry ValidationEntry;
- public byte[] ValidationBytes;
-
- public ValidationDescriptor(Stream stream)
- {
- ValidationEntry = stream.ReadStructure();
-
- ValidationBytes = new byte[ValidationEntry.dwByteCount];
- _ = stream.Read(ValidationBytes, 0, (int)ValidationEntry.dwByteCount);
- }
-
- public ValidationDescriptor(ValidationEntry validationEntry, byte[] validationBytes)
- {
- ValidationEntry = validationEntry;
- ValidationBytes = validationBytes;
- ValidationEntry.dwByteCount = (uint)validationBytes.LongLength;
- }
-
- public override string ToString()
- {
- return $"{{ValidationEntry: {ValidationEntry}}}";
- }
-
- public byte[] GetBytes()
- {
- List bytes = [];
-
- ValidationEntry.dwByteCount = (uint)ValidationBytes.Length;
-
- bytes.AddRange(ValidationEntry.GetBytes());
- bytes.AddRange(ValidationBytes);
-
- return [.. bytes];
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/Data/WriteDescriptor.cs b/Img2Ffu.Library/Reader/Data/WriteDescriptor.cs
deleted file mode 100644
index 1bfd448..0000000
--- a/Img2Ffu.Library/Reader/Data/WriteDescriptor.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using Img2Ffu.Reader.Enums;
-using Img2Ffu.Reader.Structs;
-using System.Text;
-
-namespace Img2Ffu.Reader.Data
-{
- internal class WriteDescriptor
- {
- public BlockDataEntry BlockDataEntry;
- public uint DataSize;
-
- public readonly List DiskLocations = [];
- private readonly bool HasDataSizeField;
-
- public WriteDescriptor(Stream stream, FFUVersion ffuVersion)
- {
- HasDataSizeField = ffuVersion == FFUVersion.V1_COMPRESSED;
-
- BlockDataEntry = stream.ReadStructure();
-
- if (HasDataSizeField)
- {
- using BinaryReader binaryReader = new(stream, Encoding.ASCII, true);
- DataSize = binaryReader.ReadUInt32();
- }
-
- for (uint i = 0; i < BlockDataEntry.LocationCount; i++)
- {
- DiskLocations.Add(stream.ReadStructure());
- }
- }
-
- public WriteDescriptor(BlockDataEntry blockDataEntry, List diskLocations, uint compressedDataBlockSize)
- {
- HasDataSizeField = true;
-
- BlockDataEntry = blockDataEntry;
- DiskLocations = diskLocations;
- DataSize = compressedDataBlockSize;
- }
-
- public WriteDescriptor(BlockDataEntry blockDataEntry, List diskLocations, FFUVersion ffuVersion)
- {
- HasDataSizeField = false;
-
- BlockDataEntry = blockDataEntry;
- DiskLocations = diskLocations;
- }
-
- public override string ToString()
- {
- return $"{{BlockDataEntry: {BlockDataEntry}}}";
- }
-
- public byte[] GetBytes()
- {
- List bytes = [];
-
- BlockDataEntry.LocationCount = (uint)DiskLocations.Count;
-
- bytes.AddRange(BlockDataEntry.GetBytes());
-
- if (HasDataSizeField)
- {
- bytes.AddRange(BitConverter.GetBytes(DataSize));
- }
-
- foreach (DiskLocation diskLocation in DiskLocations)
- {
- bytes.AddRange(diskLocation.GetBytes());
- }
-
- return [.. bytes];
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Enums/CompressionAlgorithm.cs b/Img2Ffu.Library/Reader/Enums/CompressionAlgorithm.cs
deleted file mode 100644
index 93423ac..0000000
--- a/Img2Ffu.Library/Reader/Enums/CompressionAlgorithm.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Img2Ffu.Reader.Enums
-{
- public enum CompressionAlgorithm
- {
- None = 0,
- Default = 1,
- LZNT1 = 2,
- XPRESS = 3,
- XPRESS_HUFF = 4
- }
-}
diff --git a/Img2Ffu.Library/Reader/Enums/DiskAccessMethod.cs b/Img2Ffu.Library/Reader/Enums/DiskAccessMethod.cs
deleted file mode 100644
index 5fbf7c6..0000000
--- a/Img2Ffu.Library/Reader/Enums/DiskAccessMethod.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Img2Ffu.Reader.Enums
-{
- public enum DiskAccessMethod
- {
- DISK_BEGIN = 0,
- DISK_END = 2
- }
-}
diff --git a/Img2Ffu.Library/Reader/Enums/FFUVersion.cs b/Img2Ffu.Library/Reader/Enums/FFUVersion.cs
deleted file mode 100644
index 80bd67c..0000000
--- a/Img2Ffu.Library/Reader/Enums/FFUVersion.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Img2Ffu.Reader.Enums
-{
- internal enum FFUVersion
- {
- V1,
- V1_COMPRESSED,
- V2
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/FullFlashUpdateReaderStream.cs b/Img2Ffu.Library/Reader/FullFlashUpdateReaderStream.cs
deleted file mode 100644
index 670c487..0000000
--- a/Img2Ffu.Library/Reader/FullFlashUpdateReaderStream.cs
+++ /dev/null
@@ -1,325 +0,0 @@
-using Img2Ffu.Reader.Data;
-
-namespace Img2Ffu.Reader
-{
- public class FullFlashUpdateReaderStream : Stream
- {
- private readonly Stream ffuFileStream;
- private readonly SignedImage signedImage;
- private readonly ImageFlash image;
- private readonly Store store;
- private readonly ulong storeIndex;
- private readonly long length;
- private readonly long blockSize;
- private readonly Dictionary blockTable;
-
- private long currentPosition = 0;
-
- public int SectorSize
- {
- get;
- }
- public int MinSectorCount
- {
- get;
- }
-
- public string DevicePath => store.DevicePath;
-
- public FullFlashUpdateReaderStream(string FFUFilePath, ulong storeIndex)
- {
- ffuFileStream = File.OpenRead(FFUFilePath);
- signedImage = new SignedImage(ffuFileStream);
- image = signedImage.Image;
- this.storeIndex = storeIndex;
- store = image.Stores[(int)storeIndex];
- blockSize = store.StoreHeader.BlockSize;
- (length, blockTable) = BuildBlockTable();
-
- try
- {
- (int minSectorCount, int sectorSize)[] manifestStoreInformation = ExtractImageManifestStoreInformation(signedImage);
-
- (MinSectorCount, SectorSize) = manifestStoreInformation[storeIndex];
-
- if (SectorSize == 0)
- {
- SectorSize = signedImage.ChunkSize;
- }
-
- length = (long)((ulong)MinSectorCount * (ulong)SectorSize);
- }
- catch { }
- }
-
- public static int GetStoreCount(string FFUFilePath)
- {
- using FileStream ffuStream = File.Open(FFUFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
- SignedImage ffuFile = new(ffuStream);
- return ffuFile.Image.Stores.Count;
- }
-
- private static (int minSectorCount, int minSectorSize)[] ExtractImageManifestStoreInformation(SignedImage ffuFile)
- {
- List<(int minSectorCount, int minSectorSize)> manifestStoreInformation = [];
-
- int currentMinSectorCount = 0;
- int currentSectorSize = 0;
- bool isInStoreSection = false;
-
- foreach (string line in ffuFile.Image.ManifestData.Split("\n"))
- {
- if (line.StartsWith('[') && line.Contains(']'))
- {
- string sectionName = line.Split('[')[1].Split(']')[0];
-
- if (isInStoreSection)
- {
- manifestStoreInformation.Add((currentMinSectorCount, currentSectorSize));
- }
-
- isInStoreSection = sectionName.Equals("Store", StringComparison.InvariantCultureIgnoreCase);
- }
- else if (isInStoreSection)
- {
- if (line.StartsWith("MinSectorCount", StringComparison.InvariantCultureIgnoreCase))
- {
- bool success = int.TryParse(line.Split("=")[1].Trim(), out int tempCurrentMinSectorCount);
- currentMinSectorCount = success ? tempCurrentMinSectorCount : throw new InvalidDataException(line);
- }
- else if (line.StartsWith("SectorSize", StringComparison.InvariantCultureIgnoreCase))
- {
- bool success = int.TryParse(line.Split("=")[1].Trim(), out int tempCurrentMinSectorSize);
- currentSectorSize = success ? tempCurrentMinSectorSize : throw new InvalidDataException(line);
- }
- }
- }
-
- if (isInStoreSection)
- {
- manifestStoreInformation.Add((currentMinSectorCount, currentSectorSize));
- }
-
- return [.. manifestStoreInformation];
- }
-
- public override bool CanRead => true;
-
- public override bool CanSeek => true;
-
- public override bool CanWrite => false;
-
- public override long Length => length;
-
- private (long, Dictionary) BuildBlockTable()
- {
- // We do not want to immediately return because FFU files may first blank out sectors and then write post mortem
- Dictionary blockTable = [];
-
- long blockMaxStart = 0;
- long blockMaxEnd = 0;
-
- for (int i = 0; i < store.WriteDescriptors.Count; i++)
- {
- WriteDescriptor writeDescriptor = store.WriteDescriptors[i];
- foreach (Structs.DiskLocation diskLocation in writeDescriptor.DiskLocations)
- {
- switch (diskLocation.DiskAccessMethod)
- {
- case 0:
- {
- if (diskLocation.BlockIndex > blockMaxStart)
- {
- blockMaxStart = diskLocation.BlockIndex;
- }
-
- long blockOffset = diskLocation.BlockIndex;
- if (blockTable.ContainsKey(blockOffset))
- {
- blockTable[blockOffset] = i;
- }
- else
- {
- blockTable.Add(blockOffset, i);
- }
- break;
- }
- case 2:
- {
- if (diskLocation.BlockIndex > blockMaxEnd)
- {
- blockMaxEnd = diskLocation.BlockIndex;
- }
-
- long blockOffset = (Length / blockSize) - 1 - diskLocation.BlockIndex;
- if (blockTable.ContainsKey(blockOffset))
- {
- blockTable[blockOffset] = i;
- }
- else
- {
- blockTable.Add(blockOffset, i);
- }
- break;
- }
- }
- }
- }
-
- long totalBlocks = blockMaxStart + blockMaxEnd + 2;
-
- return (totalBlocks * blockSize, blockTable);
- }
-
- private long GetBlockDataIndex(long realBlockOffset)
- {
- if (blockTable.ContainsKey(realBlockOffset))
- {
- return blockTable[realBlockOffset];
- }
-
- return -1; // Invalid
- }
-
- public override long Position
- {
- get => currentPosition;
- set
- {
- if (currentPosition < 0)
- {
- throw new ArgumentOutOfRangeException("value");
- }
-
- // Workaround for malformed MBRs
- /*if (currentPosition > Length)
- {
- throw new EndOfStreamException();
- }*/
-
- currentPosition = value;
- }
- }
-
- public override void Flush()
- {
- // Nothing to do here
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- {
- throw new ArgumentNullException("buffer");
- }
-
- if (offset + count > buffer.Length)
- {
- throw new ArgumentException("The sum of offset and count is greater than the buffer length.");
- }
-
- if (offset < 0)
- {
- throw new ArgumentOutOfRangeException("offset");
- }
-
- if (count < 0)
- {
- throw new ArgumentOutOfRangeException("count");
- }
-
- // Workaround for malformed MBRs
- if (Position >= Length)
- {
- return count;
- }
-
- long readBytes = count;
-
- if (Position + readBytes > Length)
- {
- readBytes = (int)(Length - Position);
- }
-
- byte[] readBuffer = new byte[readBytes];
- Array.Fill(readBuffer, 0);
-
- // Read the buffer from the FFU file.
- // First we have to figure out where do we land here.
-
- long overflowBlockStartByteCount = Position % blockSize;
- long overflowBlockEndByteCount = (Position + readBytes) % blockSize;
-
- long startBlockIndex = (Position - overflowBlockStartByteCount) / blockSize;
- long endBlockIndex = (Position + readBytes + (blockSize - overflowBlockEndByteCount)) / blockSize;
-
- byte[] allReadBlocks = new byte[(endBlockIndex - startBlockIndex + 1) * blockSize];
-
- for (long currentBlock = startBlockIndex; currentBlock < endBlockIndex; currentBlock++)
- {
- long virtualBlockIndex = GetBlockDataIndex(currentBlock);
- if (virtualBlockIndex != -1)
- {
- byte[] block = image.GetStoreDataBlock(ffuFileStream, storeIndex, (ulong)virtualBlockIndex);
- Array.Copy(block, 0, allReadBlocks, (int)((currentBlock - startBlockIndex) * blockSize), blockSize);
- }
- }
-
- Array.Copy(allReadBlocks, overflowBlockStartByteCount, buffer, offset, readBytes);
-
- Position += readBytes;
-
- if (Position == Length)
- {
- // Workaround for malformed MBRs
- //return 0;
- }
-
- return (int)readBytes;
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- switch (origin)
- {
- case SeekOrigin.Begin:
- {
- Position = offset;
- break;
- }
- case SeekOrigin.Current:
- {
- Position += offset;
- break;
- }
- case SeekOrigin.End:
- {
- Position = Length + offset;
- break;
- }
- default:
- {
- throw new ArgumentException(nameof(origin));
- }
- }
-
- return Position;
- }
-
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
-
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- ffuFileStream.Dispose();
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/StructExtensions.cs b/Img2Ffu.Library/Reader/StructExtensions.cs
deleted file mode 100644
index e2f1e9c..0000000
--- a/Img2Ffu.Library/Reader/StructExtensions.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader
-{
- public static class StructExtensions
- {
- public static T GetStruct(this byte[] bytes) where T : struct
- {
- int requiredSize = Marshal.SizeOf(typeof(T));
- if (bytes.Length < requiredSize)
- {
- throw new Exception($"Invalid buffer size for passed in structure. Expected: {requiredSize} Provided: {bytes.Length}");
- }
-
- GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- T structure = Marshal.PtrToStructure(handle.AddrOfPinnedObject());
- handle.Free();
- return structure;
- }
-
- public static byte[] GetBytes(this T structure) where T : struct
- {
- byte[] bytes = new byte[Marshal.SizeOf(typeof(T))];
- GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
- Marshal.StructureToPtr(structure, handle.AddrOfPinnedObject(), false);
- handle.Free();
- return bytes;
- }
-
- public static T Read(this BinaryReader reader) where T : struct
- {
- byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
- return bytes.GetStruct();
- }
-
- public static void Write(this BinaryWriter writer, T structure) where T : struct
- {
- byte[] bytes = structure.GetBytes();
- writer.Write(bytes);
- }
-
- public static T ReadStructure(this Stream stream) where T : struct
- {
- using BinaryReader binaryReader = new(stream, System.Text.Encoding.ASCII, true);
- return binaryReader.Read();
- }
-
- public static void WriteStructure(this Stream stream, T structure) where T : struct
- {
- using BinaryWriter binaryWriter = new(stream, System.Text.Encoding.ASCII, true);
- binaryWriter.Write(structure);
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/BlockDataEntry.cs b/Img2Ffu.Library/Reader/Structs/BlockDataEntry.cs
deleted file mode 100644
index ae79ca5..0000000
--- a/Img2Ffu.Library/Reader/Structs/BlockDataEntry.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct BlockDataEntry
- {
- public uint LocationCount;
- public uint BlockCount;
-
- public override readonly string ToString()
- {
- return $"{{LocationCount: {LocationCount}, BlockCount: {BlockCount}}}";
- }
- }
-}
diff --git a/Img2Ffu.Library/Reader/Structs/DiskLocation.cs b/Img2Ffu.Library/Reader/Structs/DiskLocation.cs
deleted file mode 100644
index 958ae11..0000000
--- a/Img2Ffu.Library/Reader/Structs/DiskLocation.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct DiskLocation
- {
- public uint DiskAccessMethod;
- public uint BlockIndex;
-
- public override readonly string ToString()
- {
- return $"{{DiskAccessMethod: {DiskAccessMethod}, BlockIndex: {BlockIndex}}}";
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/ImageHeader.cs b/Img2Ffu.Library/Reader/Structs/ImageHeader.cs
deleted file mode 100644
index 7f9dc26..0000000
--- a/Img2Ffu.Library/Reader/Structs/ImageHeader.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- public struct ImageHeader
- {
- public uint Size; // sizeof(ImageHeader)
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
- public string Signature; // "ImageFlash "
- public uint ManifestLength; // in bytes
- public uint ChunkSize; // Used only during image generation.
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/SecurityHeader.cs b/Img2Ffu.Library/Reader/Structs/SecurityHeader.cs
deleted file mode 100644
index c15572c..0000000
--- a/Img2Ffu.Library/Reader/Structs/SecurityHeader.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- public struct SecurityHeader
- {
- public uint Size; // size of struct, overall
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
- public string Signature; // "SignedImage "
- public uint ChunkSizeInKB; // size of a hashed chunk within the image
- public uint AlgorithmId; // algorithm used to hash
- public uint CatalogSize; // size of catalog to validate
- public uint HashTableSize; // size of hash table
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/StoreHeader.cs b/Img2Ffu.Library/Reader/Structs/StoreHeader.cs
deleted file mode 100644
index 66b8c3e..0000000
--- a/Img2Ffu.Library/Reader/Structs/StoreHeader.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- public struct StoreHeader
- {
- public uint UpdateType; // indicates partial or full flash
- public ushort MajorVersion, MinorVersion; // used to validate struct
- public ushort FullFlashMajorVersion, FullFlashMinorVersion; // FFU version, i.e. the image format
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 192)]
- public byte[] PlatformId; // string which indicates what device this FFU is intended to be written to
- public uint BlockSize; // size of an image block in bytes – the device’s actual sector size may differ
- public uint WriteDescriptorCount; // number of write descriptors to iterate through
- public uint WriteDescriptorLength; // total size of all the write descriptors, in bytes (included so they can be read out up front and interpreted later)
- public uint ValidateDescriptorCount; // number of validation descriptors to check
- public uint ValidateDescriptorLength; // total size of all the validation descriptors, in bytes
- public uint InitialTableIndex; // block index in the payload of the initial (invalid) GPT
- public uint InitialTableCount; // count of blocks for the initial GPT, i.e. the GPT spans blockArray[idx..(idx + count -1)]
- public uint FlashOnlyTableIndex; // first block index in the payload of the flash-only GPT (included so safe flashing can be accomplished)
- public uint FlashOnlyTableCount; // count of blocks in the flash-only GPT
- public uint FinalTableIndex; // index in the table of the real GPT
- public uint FinalTableCount; // number of blocks in the real GPT
-
- public override readonly string ToString()
- {
- return $"{{UpdateType: {UpdateType}, MajorVersion: {MajorVersion}, MinorVersion: {MinorVersion}}}";
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/StoreHeaderV2.cs b/Img2Ffu.Library/Reader/Structs/StoreHeaderV2.cs
deleted file mode 100644
index 15fe042..0000000
--- a/Img2Ffu.Library/Reader/Structs/StoreHeaderV2.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
- public struct StoreHeaderV2
- {
- public ushort NumberOfStores; // Total number of stores (V2 only)
- public ushort StoreIndex; // Current store index, 1-based (V2 only)
- public ulong StorePayloadSize; // Payload data only, excludes padding (V2 only)
- public ushort DevicePathLength; // Length of the device path (V2 only)
-
- public override readonly string ToString()
- {
- return $"{{NumberOfStores: {NumberOfStores}, StoreIndex: {StoreIndex}, StorePayloadSize: {StorePayloadSize}, DevicePathLength: {DevicePathLength}}}";
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Reader/Structs/ValidationEntry.cs b/Img2Ffu.Library/Reader/Structs/ValidationEntry.cs
deleted file mode 100644
index ab67289..0000000
--- a/Img2Ffu.Library/Reader/Structs/ValidationEntry.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Reader.Structs
-{
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct ValidationEntry
- {
- public uint dwSectorIndex;
- public uint dwSectorOffset;
- public uint dwByteCount;
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Data/BlockDataEntry.cs b/Img2Ffu.Library/Writer/Data/BlockDataEntry.cs
deleted file mode 100644
index e81b746..0000000
--- a/Img2Ffu.Library/Writer/Data/BlockDataEntry.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public class BlockDataEntry
- {
- public uint LocationCount;
- public uint BlockCount;
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/CompressionAlgorithm.cs b/Img2Ffu.Library/Writer/Data/CompressionAlgorithm.cs
deleted file mode 100644
index a55df57..0000000
--- a/Img2Ffu.Library/Writer/Data/CompressionAlgorithm.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public enum CompressionAlgorithm
- {
- None = 0,
- Default = 1,
- LZNT1 = 2,
- XPRESS = 3,
- XPRESS_HUFF = 4
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/DeviceTargetInfo.cs b/Img2Ffu.Library/Writer/Data/DeviceTargetInfo.cs
deleted file mode 100644
index 904a734..0000000
--- a/Img2Ffu.Library/Writer/Data/DeviceTargetInfo.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System.Text;
-
-namespace Img2Ffu.Writer.Data
-{
- public class DeviceTargetInfo(string manufacturer, string family, string productName, string productVersion, string sKUNumber, string baseboardManufacturer, string baseboardProduct)
- {
- private uint ManufacturerLength;
-
- private uint FamilyLength;
-
- private uint ProductNameLength;
-
- private uint ProductVersionLength;
-
- private uint SKUNumberLength;
-
- private uint BaseboardManufacturerLength;
-
- private uint BaseboardProductLength;
-
- public string Manufacturer { get; } = manufacturer;
-
- public string Family { get; } = family;
-
- public string ProductName { get; } = productName;
-
- public string ProductVersion { get; } = productVersion;
-
- public string SKUNumber { get; } = sKUNumber;
-
- public string BaseboardManufacturer { get; } = baseboardManufacturer;
-
- public string BaseboardProduct { get; } = baseboardProduct;
-
- internal byte[] GetResultingBuffer()
- {
- using MemoryStream DeviceTargetInfoStream = new();
- using BinaryWriter binaryWriter = new(DeviceTargetInfoStream);
-
- ManufacturerLength = (uint)Manufacturer.Length;
- FamilyLength = (uint)Family.Length;
- ProductNameLength = (uint)ProductName.Length;
- ProductVersionLength = (uint)ProductVersion.Length;
- SKUNumberLength = (uint)SKUNumber.Length;
- BaseboardManufacturerLength = (uint)BaseboardManufacturer.Length;
- BaseboardProductLength = (uint)BaseboardProduct.Length;
-
- binaryWriter.Write(ManufacturerLength);
- binaryWriter.Write(FamilyLength);
- binaryWriter.Write(ProductNameLength);
- binaryWriter.Write(ProductVersionLength);
- binaryWriter.Write(SKUNumberLength);
- binaryWriter.Write(BaseboardManufacturerLength);
- binaryWriter.Write(BaseboardProductLength);
-
- binaryWriter.Write(Encoding.ASCII.GetBytes(Manufacturer));
- binaryWriter.Write(Encoding.ASCII.GetBytes(Family));
- binaryWriter.Write(Encoding.ASCII.GetBytes(ProductName));
- binaryWriter.Write(Encoding.ASCII.GetBytes(ProductVersion));
- binaryWriter.Write(Encoding.ASCII.GetBytes(SKUNumber));
- binaryWriter.Write(Encoding.ASCII.GetBytes(BaseboardManufacturer));
- binaryWriter.Write(Encoding.ASCII.GetBytes(BaseboardProduct));
-
- byte[] DeviceTargetInfoBuffer = new byte[DeviceTargetInfoStream.Length];
- _ = DeviceTargetInfoStream.Seek(0, SeekOrigin.Begin);
- DeviceTargetInfoStream.ReadExactly(DeviceTargetInfoBuffer, 0, DeviceTargetInfoBuffer.Length);
-
- return DeviceTargetInfoBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/DiskLocation.cs b/Img2Ffu.Library/Writer/Data/DiskLocation.cs
deleted file mode 100644
index 8071cde..0000000
--- a/Img2Ffu.Library/Writer/Data/DiskLocation.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public class DiskLocation
- {
- public uint DiskAccessMethod;
- public uint BlockIndex;
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Data/FlashUpdateType.cs b/Img2Ffu.Library/Writer/Data/FlashUpdateType.cs
deleted file mode 100644
index 349797c..0000000
--- a/Img2Ffu.Library/Writer/Data/FlashUpdateType.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public enum FlashUpdateType
- {
- Full,
- Partial
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Data/FlashUpdateVersion.cs b/Img2Ffu.Library/Writer/Data/FlashUpdateVersion.cs
deleted file mode 100644
index a3778b5..0000000
--- a/Img2Ffu.Library/Writer/Data/FlashUpdateVersion.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public enum FlashUpdateVersion
- {
- V1,
- V1_COMPRESSED,
- V2
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/ImageHeader.cs b/Img2Ffu.Library/Writer/Data/ImageHeader.cs
deleted file mode 100644
index e62bb05..0000000
--- a/Img2Ffu.Library/Writer/Data/ImageHeader.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Text;
-
-namespace Img2Ffu.Writer.Data
-{
- internal class ImageHeader
- {
- public uint ManifestLength
- {
- get; set;
- }
-
- public byte[] GetResultingBuffer(uint BlockSize, bool HasDeviceTargetInfo, uint DeviceTargetInfosCount)
- {
- using MemoryStream ImageHeaderStream = new();
- using BinaryWriter binaryWriter = new(ImageHeaderStream);
-
- binaryWriter.Write(HasDeviceTargetInfo ? 28u : 24u); // Size
- binaryWriter.Write(Encoding.ASCII.GetBytes("ImageFlash ")); // Signature
- binaryWriter.Write(ManifestLength); // Manifest Length
- binaryWriter.Write(BlockSize / 1024); // Chunk Size in KB
-
- if (HasDeviceTargetInfo)
- {
- binaryWriter.Write(DeviceTargetInfosCount); // Device Target Infos Count
- }
-
- byte[] ImageHeaderBuffer = new byte[ImageHeaderStream.Length];
- _ = ImageHeaderStream.Seek(0, SeekOrigin.Begin);
- ImageHeaderStream.ReadExactly(ImageHeaderBuffer, 0, ImageHeaderBuffer.Length);
-
- return ImageHeaderBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/SecurityHeader.cs b/Img2Ffu.Library/Writer/Data/SecurityHeader.cs
deleted file mode 100644
index d1d7c8e..0000000
--- a/Img2Ffu.Library/Writer/Data/SecurityHeader.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Text;
-
-namespace Img2Ffu.Writer.Data
-{
- public class SecurityHeader
- {
- private readonly uint Size = 32;
- private readonly string Signature = "SignedImage ";
- private readonly uint HashAlgorithm = 0x800C; // SHA256 algorithm id
-
- public uint CatalogSize;
- public uint HashTableSize;
-
- public byte[] GetResultingBuffer(uint BlockSize)
- {
- using MemoryStream SecurityHeaderStream = new();
- using BinaryWriter binaryWriter = new(SecurityHeaderStream);
-
- uint ChunkSizeInKb = BlockSize / 1024;
-
- binaryWriter.Write(Size);
- binaryWriter.Write(Encoding.ASCII.GetBytes(Signature));
- binaryWriter.Write(ChunkSizeInKb);
- binaryWriter.Write(HashAlgorithm);
- binaryWriter.Write(CatalogSize);
- binaryWriter.Write(HashTableSize);
-
- byte[] SecurityHeaderBuffer = new byte[SecurityHeaderStream.Length];
- _ = SecurityHeaderStream.Seek(0, SeekOrigin.Begin);
- SecurityHeaderStream.ReadExactly(SecurityHeaderBuffer, 0, SecurityHeaderBuffer.Length);
-
- return SecurityHeaderBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/StoreHeader.cs b/Img2Ffu.Library/Writer/Data/StoreHeader.cs
deleted file mode 100644
index afbcc1d..0000000
--- a/Img2Ffu.Library/Writer/Data/StoreHeader.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Text;
-
-namespace Img2Ffu.Writer.Data
-{
- public class StoreHeader
- {
- private uint UpdateType = 0; // Full update
-
- private ushort MajorVersion = 1;
- private ushort MinorVersion = 0;
- private ushort FullFlashMajorVersion = 2;
- private ushort FullFlashMinorVersion = 0;
-
- // Size is 0xC0
- public required string[] PlatformIds
- {
- get; set;
- }
-
- public uint BlockSize
- {
- get; set;
- }
- public uint WriteDescriptorCount
- {
- get; set;
- }
- public uint WriteDescriptorLength
- {
- get; set;
- }
- public uint ValidateDescriptorCount { get; set; } = 0;
- public uint ValidateDescriptorLength { get; set; } = 0;
- public uint InitialTableIndex { get; set; } = 0;
- public uint InitialTableCount { get; set; } = 0;
- public uint FlashOnlyTableIndex { get; set; } = 0; // Should be the index of the critical partitions, but for now we don't implement that
- public uint FlashOnlyTableCount { get; set; } = 1;
-
- private uint FinalTableIndex; //= WriteDescriptorCount - FinalTableCount;
-
- public uint FinalTableCount { get; set; } = 0;
-
- // V1 Compressed
- private uint CompressionAlgorithm = 0; // 0: None, 1: GZip
-
- // V2
- public ushort NumberOfStores
- {
- get; set;
- } // 0x4 (Total number of stores)
- public ushort StoreIndex
- {
- get; set;
- } // 0x1 (Starts counting from 1)
- public ulong StorePayloadSize
- {
- get; set;
- } // 0x420000
-
- private ushort DevicePathLength; // 0x2b
- // Must be followed by the unicode string of the device path
- // So the total size would be doubled from DevicePathLength in bytes in the binary
-
- private byte[] DevicePathBuffer;
-
- public required string DevicePath
- {
- get; set;
- }
-
- public byte[] GetResultingBuffer(FlashUpdateVersion storeHeaderVersion, FlashUpdateType storeHeaderUpdateType, CompressionAlgorithm storeHeaderCompressionAlgorithm)
- {
- switch (storeHeaderVersion)
- {
- case FlashUpdateVersion.V1:
- MajorVersion = 1;
- MinorVersion = 0;
- FullFlashMajorVersion = 2;
- FullFlashMinorVersion = 0;
- break;
- case FlashUpdateVersion.V1_COMPRESSED:
- MajorVersion = 1;
- MinorVersion = 0;
- FullFlashMajorVersion = 3;
- FullFlashMinorVersion = 0;
- CompressionAlgorithm = (uint)storeHeaderCompressionAlgorithm;
- break;
- case FlashUpdateVersion.V2:
- MajorVersion = 2;
- MinorVersion = 0;
- FullFlashMajorVersion = 2;
- FullFlashMinorVersion = 0;
- UnicodeEncoding UnicodeEncoding = new();
- DevicePathBuffer = UnicodeEncoding.GetBytes(DevicePath.ToCharArray());
- DevicePathLength = (ushort)DevicePath.Length;
- break;
- }
-
- switch (storeHeaderUpdateType)
- {
- case FlashUpdateType.Full:
- UpdateType = 0;
- break;
- case FlashUpdateType.Partial:
- UpdateType = 1;
- break;
- }
-
- byte[] PlatformIdsBuffer = new byte[192];
- int CurrentBufferSize = 0;
- foreach (string PlatformId in PlatformIds)
- {
- byte[] PlatformIdBuffer = Encoding.ASCII.GetBytes(PlatformId);
- int AddedBufferSize = PlatformIdBuffer.Length + 1;
- if (CurrentBufferSize + AddedBufferSize > PlatformIdsBuffer.Length - 1)
- {
- break;
- }
- PlatformIdBuffer.CopyTo(PlatformIdsBuffer, CurrentBufferSize);
- CurrentBufferSize += AddedBufferSize;
- }
-
- FinalTableIndex = WriteDescriptorCount - FinalTableCount;
-
- using MemoryStream StoreHeaderStream = new();
- using BinaryWriter binaryWriter = new(StoreHeaderStream);
-
- binaryWriter.Write(UpdateType);
- binaryWriter.Write(MajorVersion);
- binaryWriter.Write(MinorVersion);
- binaryWriter.Write(FullFlashMajorVersion);
- binaryWriter.Write(FullFlashMinorVersion);
- binaryWriter.Write(PlatformIdsBuffer);
- binaryWriter.Write(BlockSize);
- binaryWriter.Write(WriteDescriptorCount);
- binaryWriter.Write(WriteDescriptorLength);
- binaryWriter.Write(ValidateDescriptorCount);
- binaryWriter.Write(ValidateDescriptorLength);
- binaryWriter.Write(InitialTableIndex);
- binaryWriter.Write(InitialTableCount);
- binaryWriter.Write(FlashOnlyTableIndex);
- binaryWriter.Write(FlashOnlyTableCount);
- binaryWriter.Write(FinalTableIndex);
- binaryWriter.Write(FinalTableCount);
-
- switch (storeHeaderVersion)
- {
- case FlashUpdateVersion.V1_COMPRESSED:
- binaryWriter.Write(CompressionAlgorithm);
- break;
- case FlashUpdateVersion.V2:
- binaryWriter.Write(NumberOfStores);
- binaryWriter.Write(StoreIndex);
- binaryWriter.Write(StorePayloadSize);
- binaryWriter.Write(DevicePathLength);
- binaryWriter.Write(DevicePathBuffer);
- break;
- }
-
- byte[] StoreHeaderBuffer = new byte[StoreHeaderStream.Length];
- _ = StoreHeaderStream.Seek(0, SeekOrigin.Begin);
- StoreHeaderStream.ReadExactly(StoreHeaderBuffer, 0, StoreHeaderBuffer.Length);
-
- return StoreHeaderBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/Data/WriteDescriptor.cs b/Img2Ffu.Library/Writer/Data/WriteDescriptor.cs
deleted file mode 100644
index b85669d..0000000
--- a/Img2Ffu.Library/Writer/Data/WriteDescriptor.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Img2Ffu.Writer.Data
-{
- public class WriteDescriptor
- {
- public required BlockDataEntry BlockDataEntry
- {
- get; set;
- }
- public required DiskLocation[] DiskLocations
- {
- get; set;
- }
-
- public byte[] GetResultingBuffer(FlashUpdateVersion storeHeaderVersion, uint CompressedDataBlockSize = 0)
- {
- using MemoryStream WriteDescriptorStream = new();
- using BinaryWriter binaryWriter = new(WriteDescriptorStream);
-
- BlockDataEntry.LocationCount = (uint)DiskLocations.Length;
-
- binaryWriter.Write(BlockDataEntry.LocationCount);
- binaryWriter.Write(BlockDataEntry.BlockCount);
-
- switch (storeHeaderVersion)
- {
- case FlashUpdateVersion.V1_COMPRESSED:
- binaryWriter.Write(CompressedDataBlockSize);
- break;
- }
-
- foreach (DiskLocation DiskLocation in DiskLocations)
- {
- binaryWriter.Write(DiskLocation.DiskAccessMethod);
- binaryWriter.Write(DiskLocation.BlockIndex);
- }
-
- byte[] WriteDescriptorBuffer = new byte[WriteDescriptorStream.Length];
- _ = WriteDescriptorStream.Seek(0, SeekOrigin.Begin);
- WriteDescriptorStream.ReadExactly(WriteDescriptorBuffer, 0, WriteDescriptorBuffer.Length);
-
- return WriteDescriptorBuffer;
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/FFUFactory.cs b/Img2Ffu.Library/Writer/FFUFactory.cs
deleted file mode 100644
index d6a3770..0000000
--- a/Img2Ffu.Library/Writer/FFUFactory.cs
+++ /dev/null
@@ -1,542 +0,0 @@
-using DiscUtils;
-using Img2Ffu.Writer.Data;
-using Img2Ffu.Writer.Flashing;
-using Img2Ffu.Writer.Manifest;
-using System.Diagnostics;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Img2Ffu.Writer
-{
- public class FFUFactory
- {
-
- private static byte[] GenerateCatalogFile(byte[] hashData)
- {
- byte[] catalog_first_part = [0x30, 0x82, 0x01, 0x44, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x01, 0x35, 0x30, 0x82, 0x01, 0x31, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x82, 0x01, 0x26, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x01, 0xA0, 0x82, 0x01, 0x17, 0x30, 0x82, 0x01, 0x13, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x01, 0x04, 0x10, 0xA8, 0xCA, 0xD9, 0x7D, 0xBF, 0x6D, 0x67, 0x4D, 0xB1, 0x4D, 0x62, 0xFB, 0xE6, 0x26, 0x22, 0xD4, 0x17, 0x0D, 0x32, 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x32, 0x31, 0x32, 0x32, 0x37, 0x5A, 0x30, 0x0E, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x02, 0x05, 0x00, 0x30, 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x04, 0x1E, 0x48, 0x00, 0x61, 0x00, 0x73, 0x00, 0x68, 0x00, 0x54, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x2E, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x62, 0x00, 0x00, 0x00, 0x31, 0x81, 0xAB, 0x30, 0x45, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x31, 0x37, 0x30, 0x35, 0x30, 0x10, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x19, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14];
- byte[] catalog_second_part = [0x30, 0x62, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x02, 0x02, 0x31, 0x54, 0x30, 0x52, 0x1E, 0x4C, 0x00, 0x7B, 0x00, 0x44, 0x00, 0x45, 0x00, 0x33, 0x00, 0x35, 0x00, 0x31, 0x00, 0x41, 0x00, 0x34, 0x00, 0x32, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x45, 0x00, 0x35, 0x00, 0x39, 0x00, 0x2D, 0x00, 0x31, 0x00, 0x31, 0x00, 0x44, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x43, 0x00, 0x34, 0x00, 0x37, 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30, 0x00, 0x43, 0x00, 0x30, 0x00, 0x34, 0x00, 0x46, 0x00, 0x43, 0x00, 0x32, 0x00, 0x39, 0x00, 0x35, 0x00, 0x45, 0x00, 0x45, 0x00, 0x7D, 0x02, 0x02, 0x02, 0x00, 0x31, 0x00];
-
- byte[] hash = SHA1.HashData(hashData);
-
- byte[] catalog = new byte[catalog_first_part.Length + hash.Length + catalog_second_part.Length];
- Buffer.BlockCopy(catalog_first_part, 0, catalog, 0, catalog_first_part.Length);
- Buffer.BlockCopy(hash, 0, catalog, catalog_first_part.Length, hash.Length);
- Buffer.BlockCopy(catalog_second_part, 0, catalog, catalog_first_part.Length + hash.Length, catalog_second_part.Length);
-
- return catalog;
- }
-
- private static byte[] GenerateCatalogFile2(byte[] hashData)
- {
- string catalog = Path.GetTempFileName();
- string cdf = Path.GetTempFileName();
- string hashTableBlob = Path.GetTempFileName();
-
- File.WriteAllBytes(hashTableBlob, hashData);
-
- using (StreamWriter streamWriter = new(cdf))
- {
- streamWriter.WriteLine("[CatalogHeader]");
- streamWriter.WriteLine("Name={0}", catalog);
- streamWriter.WriteLine("[CatalogFiles]");
- streamWriter.WriteLine("{0}={1}", "HashTable.blob", hashTableBlob);
- }
-
- using (Process process = new())
- {
- process.StartInfo.FileName = "MakeCat.exe";
- process.StartInfo.Arguments = string.Format("\"{0}\"", cdf);
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.CreateNoWindow = true;
- process.StartInfo.RedirectStandardOutput = true;
-
- _ = process.Start();
- process.WaitForExit();
-
- if (process.ExitCode != 0)
- {
- throw new Exception();
- }
- }
-
- byte[] catalogBuffer = File.ReadAllBytes(catalog);
-
- File.Delete(catalog);
- File.Delete(hashTableBlob);
- File.Delete(cdf);
-
- return catalogBuffer;
- }
-
- private static byte[] GetWriteDescriptorsBuffer(KeyValuePair[] payloads, FlashUpdateVersion storeHeaderVersion)
- {
- using MemoryStream WriteDescriptorsStream = new();
- using BinaryWriter binaryWriter = new(WriteDescriptorsStream);
-
- foreach (KeyValuePair payload in payloads)
- {
- byte[] WriteDescriptorBuffer = payload.Value.WriteDescriptor.GetResultingBuffer(storeHeaderVersion);
- binaryWriter.Write(WriteDescriptorBuffer);
- }
-
- byte[] WriteDescriptorsBuffer = new byte[WriteDescriptorsStream.Length];
- _ = WriteDescriptorsStream.Seek(0, SeekOrigin.Begin);
- WriteDescriptorsStream.ReadExactly(WriteDescriptorsBuffer, 0, WriteDescriptorsBuffer.Length);
-
- return WriteDescriptorsBuffer;
- }
-
- private static byte[] GenerateHashTable(MemoryStream FFUMetadataHeaderTempFileStream, KeyValuePair[] BlockPayloads, uint BlockSize)
- {
- _ = FFUMetadataHeaderTempFileStream.Seek(0, SeekOrigin.Begin);
-
- using MemoryStream HashTableStream = new();
- using BinaryWriter binaryWriter = new(HashTableStream);
-
- for (int i = 0; i < FFUMetadataHeaderTempFileStream.Length / BlockSize; i++)
- {
- byte[] buffer = new byte[BlockSize];
- _ = FFUMetadataHeaderTempFileStream.Read(buffer, 0, (int)BlockSize);
- byte[] hash = SHA256.HashData(buffer);
- binaryWriter.Write(hash, 0, hash.Length);
- }
-
- foreach (KeyValuePair payload in BlockPayloads)
- {
- binaryWriter.Write(payload.Key.Bytes, 0, payload.Key.Bytes.Length);
- }
-
- byte[] HashTableBuffer = new byte[HashTableStream.Length];
- _ = HashTableStream.Seek(0, SeekOrigin.Begin);
- HashTableStream.ReadExactly(HashTableBuffer, 0, HashTableBuffer.Length);
-
- return HashTableBuffer;
- }
-
- /*
- *: Device Targeting Infos is optional
- **: Only available on V1_COMPRESSION FFU file formats
- ***: Only available on V2 FFU file formats
-
- - Validation Descriptor is always of size 0
- - While it is possible in the struct to specify more than one Block
- for a BlockDataEntry it shall only be equal to 0
- - The hash table contains every hash of every block in the FFU file
- starting from the Image Header to the end
- - When using V1_COMPRESSION FFU file format, BlockDataEntry contains
- an extra entry of size 4 bytes
- - Multiple locations for a block data entry only copies the block
- to multiple places
-
- +------------------------------+
- | |
- | Security Header |
- | |
- +------------------------------+
- | |
- | Security Catalog |
- | |
- +------------------------------+
- | |
- | Hash Table |
- | |
- +------------------------------+
- | |
- | (Block Size) Padding |
- | |
- +------------------------------+
- | |
- | Image Header |
- | |
- +------------------------------+
- | * |
- | Image Header Extended |
- | DeviceTargetingInfoCount |
- | |
- +------------------------------+
- | |
- | Image Manifest |
- | |
- +------------------------------+
- | * |
- | DeviceTargetInfoLengths[0] |
- | |
- +------------------------------+
- | * |
- | DeviceTargetInfoStrings[0] |
- | |
- +------------------------------+
- | * |
- | . . . |
- | |
- +------------------------------+
- | * |
- | DeviceTargetInfoLengths[n] |
- | |
- +------------------------------+
- | * |
- | DeviceTargetInfoStrings[n] |
- | |
- +------------------------------+
- | |
- | (Block Size) Padding |
- | |
- +------------------------------+
- | |
- | Store Header[0] |
- | |
- +------------------------------+
- | * * |
- | CompressionAlgo[0] |
- | |
- +------------------------------+
- | * * * |
- | Store Header Ex[0] |
- | |
- +------------------------------+
- | |
- | Validation Descriptor[0] |
- | |
- +------------------------------+
- | |
- | Write Descriptors[0] |
- |(BlockDataEntry+DiskLocations)|
- +------------------------------+
- | |
- | (Block Size) Padding[0] |
- | |
- +------------------------------+
- | * * * |
- | . . . |
- | |
- +------------------------------+
- | * * * |
- | Store Header[n] |
- | |
- +------------------------------+
- | * * * |
- | Store Header Ex[n] |
- | |
- +------------------------------+
- | * * * |
- | Validation Descriptor[n] |
- | |
- +------------------------------+
- | * * * |
- | Write Descriptors[n] |
- |(BlockDataEntry+DiskLocations)|
- +------------------------------+
- | * * * |
- | (Block Size) Padding[n] |
- | |
- +------------------------------+
- | |
- | Data Blocks |
- | |
- +------------------------------+
- */
-
- private static (uint MinSectorCount, List partitions, byte[] StoreHeaderBuffer, byte[] WriteDescriptorBuffer, KeyValuePair[] BlockPayloads, FlashPart[] flashParts, VirtualDisk InputDisk) GenerateStore(string InputFile, string[] PlatformIDs, uint SectorSize, uint BlockSize, string[] ExcludedPartitionNames, uint MaximumNumberOfBlankBlocksAllowed, FlashUpdateVersion FlashUpdateVersion, ILogging Logging)
- {
- Logging.Log("Opening input file...");
-
- Stream InputStream;
- VirtualDisk? InputDisk = null;
-
- if (InputFile.Contains(@"\\.\physicaldrive", StringComparison.CurrentCultureIgnoreCase))
- {
- InputStream = new Img2Ffu.Streams.DeviceStream(InputFile, FileAccess.Read);
- }
- else if (File.Exists(InputFile) && Path.GetExtension(InputFile).Equals(".vhd", StringComparison.InvariantCultureIgnoreCase))
- {
- DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhd.Disk).Assembly);
- DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhdx.Disk).Assembly);
- InputDisk = VirtualDisk.OpenDisk(InputFile, FileAccess.Read);
- InputStream = InputDisk.Content;
- }
- else if (File.Exists(InputFile) && Path.GetExtension(InputFile).Equals(".vhdx", StringComparison.InvariantCultureIgnoreCase))
- {
- DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhd.Disk).Assembly);
- DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhdx.Disk).Assembly);
- InputDisk = VirtualDisk.OpenDisk(InputFile, FileAccess.Read);
- InputStream = InputDisk.Content;
- }
- else if (File.Exists(InputFile))
- {
- InputStream = new FileStream(InputFile, FileMode.Open);
- }
- else
- {
- Logging.Log("Unknown input specified");
- return (0, null, null, null, null, null, null);
- }
-
- Logging.Log("Generating Image Slices...");
- (FlashPart[] flashParts, List partitions) = ImageSplitter.GetImageSlices(InputStream, BlockSize, ExcludedPartitionNames, SectorSize, Logging);
-
- Logging.Log("Generating Block Payloads...");
- KeyValuePair[] BlockPayloads = BlockPayloadsGenerator.GetOptimizedPayloads(flashParts, BlockSize, MaximumNumberOfBlankBlocksAllowed, Logging);
-
- bool IsFixedDiskLength = false; // POC!
- BlockPayloads = BlockPayloadsGenerator.GetGPTPayloads(BlockPayloads, InputStream, BlockSize, IsFixedDiskLength);
-
- Logging.Log("Generating write descriptors...");
- byte[] WriteDescriptorBuffer = GetWriteDescriptorsBuffer(BlockPayloads, FlashUpdateVersion);
-
- Logging.Log("Generating store header...");
- StoreHeader store = new()
- {
- WriteDescriptorCount = (uint)BlockPayloads.LongLength,
- WriteDescriptorLength = (uint)WriteDescriptorBuffer.Length,
- PlatformIds = PlatformIDs,
- BlockSize = BlockSize,
-
- // POC Begins
- NumberOfStores = 1,
- StoreIndex = 1,
- DevicePath = "VenHw(860845C1-BE09-4355-8BC1-30D64FF8E63A)",
- StorePayloadSize = (ulong)BlockPayloads.LongLength * BlockSize
- // POC Ends
- };
-
- byte[] StoreHeaderBuffer = store.GetResultingBuffer(FlashUpdateVersion, FlashUpdateType.Full, CompressionAlgorithm.None);
-
- uint MinSectorCount = (uint)(InputStream.Length / SectorSize);
-
- return (MinSectorCount, partitions, StoreHeaderBuffer, WriteDescriptorBuffer, BlockPayloads, flashParts, InputDisk);
- }
-
- public static void GenerateFFU(string InputFile, string FFUFile, string[] PlatformIDs, uint SectorSize, uint BlockSize, string AntiTheftVersion, string OperatingSystemVersion, string[] ExcludedPartitionNames, uint MaximumNumberOfBlankBlocksAllowed, FlashUpdateVersion FlashUpdateVersion, List deviceTargetInfos, ILogging Logging)
- {
- if (File.Exists(FFUFile))
- {
- Logging.Log("File already exists!", ILoggingLevel.Error);
- return;
- }
-
- Logging.Log($"Input image: {InputFile}");
- Logging.Log($"Destination image: {FFUFile}");
- Logging.Log($"Platform IDs: {string.Join("\nPlatform IDs: ", PlatformIDs)}");
- Logging.Log($"Sector Size: {SectorSize}");
- Logging.Log($"Block Size: {BlockSize}");
- Logging.Log($"Anti Theft Version: {AntiTheftVersion}");
- Logging.Log($"OS Version: {OperatingSystemVersion}");
- Logging.Log("");
-
- (uint MinSectorCount, List partitions, byte[] StoreHeaderBuffer, byte[] WriteDescriptorBuffer, KeyValuePair[] BlockPayloads, FlashPart[] flashParts, VirtualDisk InputDisk) = GenerateStore(InputFile, PlatformIDs, SectorSize, BlockSize, ExcludedPartitionNames, MaximumNumberOfBlankBlocksAllowed, FlashUpdateVersion, Logging);
-
- // Todo make this read the image itself
- Logging.Log("Generating full flash manifest...");
- FullFlashManifest FullFlash = new()
- {
- OSVersion = OperatingSystemVersion,
- DevicePlatformId3 = PlatformIDs.Count() > 3 ? PlatformIDs[3] : "",
- DevicePlatformId2 = PlatformIDs.Count() > 2 ? PlatformIDs[2] : "",
- DevicePlatformId1 = PlatformIDs.Count() > 1 ? PlatformIDs[1] : "",
- DevicePlatformId0 = PlatformIDs[0],
- AntiTheftVersion = AntiTheftVersion
- };
-
- Logging.Log("Generating store manifest...");
- StoreManifest Store = new()
- {
- SectorSize = SectorSize,
- MinSectorCount = MinSectorCount
- };
-
- Logging.Log("Generating image manifest...");
- string ImageManifest = ManifestIni.BuildUpManifest(FullFlash, Store, partitions);
- byte[] ManifestBuffer = Encoding.ASCII.GetBytes(ImageManifest);
-
-
- Logging.Log("Generating image header...");
- ImageHeader ImageHeader = new()
- {
- ManifestLength = (uint)ManifestBuffer.Length
- };
-
- byte[] ImageHeaderBuffer = ImageHeader.GetResultingBuffer(BlockSize, deviceTargetInfos.Count != 0, (uint)deviceTargetInfos.Count);
-
- using MemoryStream FFUMetadataHeaderStream = new();
-
- //
- // Image Header
- //
- Logging.Log("Writing Image Header...");
- FFUMetadataHeaderStream.Write(ImageHeaderBuffer, 0, ImageHeaderBuffer.Length);
-
- //
- // Image Manifest
- //
- Logging.Log("Writing Image Manifest...");
- FFUMetadataHeaderStream.Write(ManifestBuffer, 0, ManifestBuffer.Length);
-
- if (deviceTargetInfos.Count != 0)
- {
- //
- // Device Target Infos...
- //
- Logging.Log("Writing Device Target Infos...");
- foreach (DeviceTargetInfo deviceTargetInfo in deviceTargetInfos)
- {
- byte[] deviceTargetInfoBuffer = deviceTargetInfo.GetResultingBuffer();
- FFUMetadataHeaderStream.Write(deviceTargetInfoBuffer, 0, deviceTargetInfoBuffer.Length);
- }
- }
-
- //
- // (Block Size) Padding
- //
- Logging.Log("Writing Padding...");
- RoundUpToChunks(FFUMetadataHeaderStream, BlockSize);
-
- //
- // Store Header[0]
- //
- Logging.Log("Writing Store Header...");
- FFUMetadataHeaderStream.Write(StoreHeaderBuffer, 0, StoreHeaderBuffer.Length);
-
- //
- // Write Descriptors[0]
- //
- Logging.Log("Writing Write Descriptors...");
- FFUMetadataHeaderStream.Write(WriteDescriptorBuffer, 0, WriteDescriptorBuffer.Length);
-
- //
- // (Block Size) Padding[0]
- //
- Logging.Log("Writing Padding...");
- RoundUpToChunks(FFUMetadataHeaderStream, BlockSize);
-
- Logging.Log("Generating image hash table...");
- byte[] HashTable = GenerateHashTable(FFUMetadataHeaderStream, BlockPayloads, BlockSize);
-
- Logging.Log("Generating image catalog...");
- byte[] CatalogBuffer = GenerateCatalogFile(HashTable);
-
- Logging.Log("Generating Security Header...");
- SecurityHeader security = new()
- {
- HashTableSize = (uint)HashTable.Length,
- CatalogSize = (uint)CatalogBuffer.Length
- };
-
- byte[] SecurityHeaderBuffer = security.GetResultingBuffer(BlockSize);
-
- byte[] FFUMetadataHeaderBuffer = new byte[FFUMetadataHeaderStream.Length];
- _ = FFUMetadataHeaderStream.Seek(0, SeekOrigin.Begin);
- _ = FFUMetadataHeaderStream.Read(FFUMetadataHeaderBuffer, 0, (int)FFUMetadataHeaderStream.Length);
-
- Logging.Log("Opening FFU file for writing...");
- WriteFFUFile(FFUFile, SecurityHeaderBuffer, CatalogBuffer, HashTable, FFUMetadataHeaderBuffer, BlockPayloads, flashParts, BlockSize, Logging);
-
- InputDisk?.Dispose();
- }
-
- private static void WriteFFUFile(string FFUFile, byte[] SecurityHeaderBuffer, byte[] CatalogBuffer, byte[] HashTable, byte[] FFUMetadataHeaderBuffer, KeyValuePair[] BlockPayloads, FlashPart[] flashParts, uint BlockSize, ILogging Logging)
- {
- FileStream FFUFileStream = new(FFUFile, FileMode.CreateNew);
-
- //
- // Security Header
- //
- Logging.Log("Writing Security Header...");
- FFUFileStream.Write(SecurityHeaderBuffer, 0, SecurityHeaderBuffer.Length);
-
- //
- // Security Catalog
- //
- Logging.Log("Writing Security Catalog...");
- FFUFileStream.Write(CatalogBuffer, 0, CatalogBuffer.Length);
-
- //
- // Hash Table
- //
- Logging.Log("Writing Hash Table...");
- FFUFileStream.Write(HashTable, 0, HashTable.Length);
-
- //
- // (Block Size) Padding
- //
- Logging.Log("Writing Padding...");
- RoundUpToChunks(FFUFileStream, BlockSize);
-
- //
- // Image Header
- // Image Manifest
- // (Block Size) Padding
- // Store Header[0]
- // Write Descriptors[0]
- // (Block Size) Padding[0]
- //
- Logging.Log("Writing Image Header...");
- Logging.Log("Writing Image Manifest...");
- Logging.Log("Writing Padding...");
- Logging.Log("Writing Store Header...");
- Logging.Log("Writing Write Descriptors...");
- Logging.Log("Writing Padding...");
- FFUFileStream.Write(FFUMetadataHeaderBuffer, 0, FFUMetadataHeaderBuffer.Length);
-
- DateTime startTime = DateTime.Now;
-
- //
- // Data Blocks
- //
- Logging.Log("Writing Data Blocks...");
- for (ulong CurrentBlockIndex = 0; CurrentBlockIndex < (ulong)BlockPayloads.LongLength; CurrentBlockIndex++)
- {
- BlockPayload BlockPayload = BlockPayloads.ElementAt((int)CurrentBlockIndex).Value;
- byte[] BlockBuffer = BlockPayload.ReadBlock(BlockSize);
-
- FFUFileStream.Write(BlockBuffer, 0, (int)BlockSize);
-
- ulong totalBytes = (ulong)BlockPayloads.LongLength * BlockSize;
- ulong bytesRead = CurrentBlockIndex * BlockSize;
- ulong sourcePosition = CurrentBlockIndex * BlockSize;
-
- ShowProgress(totalBytes, startTime, bytesRead, sourcePosition, Logging);
- }
- Logging.Log("");
-
- FFUFileStream.Close();
- }
-
- private static void RoundUpToChunks(FileStream stream, uint chunkSize)
- {
- long Size = stream.Length;
- if ((Size % chunkSize) > 0)
- {
- long padding = (uint)(((Size / chunkSize) + 1) * chunkSize) - Size;
- stream.Write(new byte[padding], 0, (int)padding);
- }
- }
-
- private static void RoundUpToChunks(MemoryStream stream, uint chunkSize)
- {
- long Size = stream.Length;
- if ((Size % chunkSize) > 0)
- {
- long padding = (uint)(((Size / chunkSize) + 1) * chunkSize) - Size;
- stream.Write(new byte[padding], 0, (int)padding);
- }
- }
-
- private static void ShowProgress(ulong TotalBytes, DateTime startTime, ulong BytesRead, ulong SourcePosition, ILogging Logging)
- {
- DateTime now = DateTime.Now;
- TimeSpan timeSoFar = now - startTime;
-
- double milliseconds = timeSoFar.TotalMilliseconds / BytesRead * (TotalBytes - BytesRead);
- double ticks = milliseconds * TimeSpan.TicksPerMillisecond;
- if ((ticks > long.MaxValue) || (ticks < long.MinValue) || double.IsNaN(ticks))
- {
- milliseconds = 0;
- }
- TimeSpan remaining = TimeSpan.FromMilliseconds(milliseconds);
-
- double speed = Math.Round(SourcePosition / 1024L / 1024L / timeSoFar.TotalSeconds);
-
- Logging.Log(string.Format($"{LoggingHelpers.GetDismLikeProgBar(int.Parse((BytesRead * 100 / TotalBytes).ToString()))} {speed}MB/s {Math.Truncate(remaining.TotalHours):00}:{remaining.Minutes:00}:{remaining.Seconds:00}.{remaining.Milliseconds:000}"), returnLine: false, severity: ILoggingLevel.Information);
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/FlashPart.cs b/Img2Ffu.Library/Writer/FlashPart.cs
deleted file mode 100644
index 4a5cbbc..0000000
--- a/Img2Ffu.Library/Writer/FlashPart.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer
-{
- internal class FlashPart(Stream Stream, ulong StartLocation)
- {
- public ulong StartLocation = StartLocation;
- public Stream Stream = Stream;
- }
-}
diff --git a/Img2Ffu.Library/Writer/Flashing/BlockPayload.cs b/Img2Ffu.Library/Writer/Flashing/BlockPayload.cs
deleted file mode 100644
index 4dc8eb4..0000000
--- a/Img2Ffu.Library/Writer/Flashing/BlockPayload.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using Img2Ffu.Writer.Data;
-
-namespace Img2Ffu.Writer.Flashing
-{
- public class BlockPayload(WriteDescriptor WriteDescriptor, Stream Stream, ulong StreamLocation)
- {
- public WriteDescriptor WriteDescriptor = WriteDescriptor;
- public Stream Stream = Stream;
- public ulong FlashPartStreamLocation = StreamLocation;
-
- internal byte[] ReadBlock(ulong BlockSize)
- {
- _ = Stream.Seek((long)FlashPartStreamLocation, SeekOrigin.Begin);
-
- byte[] BlockBuffer = new byte[BlockSize];
- _ = Stream.Read(BlockBuffer, 0, (int)BlockSize);
-
- return BlockBuffer;
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Flashing/BlockPayloadsGenerator.cs b/Img2Ffu.Library/Writer/Flashing/BlockPayloadsGenerator.cs
deleted file mode 100644
index b719cce..0000000
--- a/Img2Ffu.Library/Writer/Flashing/BlockPayloadsGenerator.cs
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using Img2Ffu.Writer.Data;
-using System.Collections;
-using System.Security.Cryptography;
-
-namespace Img2Ffu.Writer.Flashing
-{
- internal class BlockPayloadsGenerator
- {
- private static void ShowProgress(ulong CurrentProgress, ulong TotalProgress, DateTime startTime, bool DisplayRed, ILogging Logging)
- {
- DateTime now = DateTime.Now;
- TimeSpan timeSoFar = now - startTime;
-
- double milliseconds = timeSoFar.TotalMilliseconds / CurrentProgress * (TotalProgress - CurrentProgress);
- double ticks = milliseconds * TimeSpan.TicksPerMillisecond;
- if (ticks > long.MaxValue || ticks < long.MinValue || double.IsNaN(ticks))
- {
- milliseconds = 0;
- }
- TimeSpan remaining = TimeSpan.FromMilliseconds(milliseconds);
-
- Logging.Log(string.Format($"{LoggingHelpers.GetDismLikeProgBar(int.Parse((CurrentProgress * 100 / TotalProgress).ToString()))} {Math.Truncate(remaining.TotalHours):00}:{remaining.Minutes:00}:{remaining.Seconds:00}.{remaining.Milliseconds:000}"), returnLine: false, severity: DisplayRed ? ILoggingLevel.Warning : ILoggingLevel.Information);
- }
-
- internal static KeyValuePair[] GetGPTPayloads(KeyValuePair[] blockPayloads, Stream stream, uint BlockSize, bool IsFixedDiskLength)
- {
- List> blockPayloadsList = [.. blockPayloads];
-
- byte[] EMPTY_BLOCK_HASH = SHA256.HashData(new byte[BlockSize]);
-
- // Erase both GPTs as per spec first
- blockPayloadsList.Insert(0, new KeyValuePair(new ByteArrayKey(EMPTY_BLOCK_HASH), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 2
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = 0,
- DiskAccessMethod = 0
- },
- new DiskLocation()
- {
- BlockIndex = 0,
- DiskAccessMethod = 2 // From End
- }
- ]
- },
- new MemoryStream(new byte[(int)BlockSize]),
- 0
- )));
-
- byte[] PrimaryGPTBuffer = new byte[(int)BlockSize];
- _ = stream.Seek(0, SeekOrigin.Begin);
- _ = stream.Read(PrimaryGPTBuffer, 0, (int)BlockSize);
-
- MemoryStream primaryGPTStream = new(PrimaryGPTBuffer);
-
- KeyValuePair primaryGPTKeyValuePair = new(new ByteArrayKey(SHA256.HashData(primaryGPTStream)), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 1
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = 0,
- DiskAccessMethod = 0
- }
- ]
- },
- primaryGPTStream,
- 0
- ));
-
- if (IsFixedDiskLength)
- {
- ulong endGPTChunkStartLocation = (ulong)stream.Length - BlockSize;
- byte[] SecondaryGPTBuffer = new byte[(int)BlockSize];
- _ = stream.Seek((long)endGPTChunkStartLocation, SeekOrigin.Begin);
- _ = stream.Read(SecondaryGPTBuffer, 0, (int)BlockSize);
-
- MemoryStream secondaryGPTStream = new(SecondaryGPTBuffer);
-
- // Now add back both GPTs
- // Apparently the first one needs to be added twice?
- blockPayloadsList.Add(primaryGPTKeyValuePair);
- blockPayloadsList.Add(primaryGPTKeyValuePair);
-
- blockPayloadsList.Add(new KeyValuePair(new ByteArrayKey(SHA256.HashData(secondaryGPTStream)), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 1
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = 0,
- DiskAccessMethod = 2
- }
- ]
- },
- secondaryGPTStream,
- 0
- )));
- }
- else
- {
- // Now add back both GPTs
- // Apparently the first one needs to be added twice?
- blockPayloadsList.Insert(1, primaryGPTKeyValuePair);
- blockPayloadsList.Add(primaryGPTKeyValuePair);
-
- ulong endGPTChunkStartLocation = (ulong)stream.Length - BlockSize;
- byte[] SecondaryGPTBuffer = new byte[(int)BlockSize];
- _ = stream.Seek((long)endGPTChunkStartLocation, SeekOrigin.Begin);
- _ = stream.Read(SecondaryGPTBuffer, 0, (int)BlockSize);
-
- MemoryStream secondaryGPTStream = new(SecondaryGPTBuffer);
-
- // HACK
- blockPayloadsList.Add(new KeyValuePair(new ByteArrayKey(SHA256.HashData(secondaryGPTStream)), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 1
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = 0,
- DiskAccessMethod = 2
- }
- ]
- },
- secondaryGPTStream,
- 0
- )));
- }
-
- return [.. blockPayloadsList];
- }
-
- internal static KeyValuePair[] GetOptimizedPayloads(FlashPart[] flashParts, uint BlockSize, uint BlankSectorBufferSize, ILogging Logging)
- {
- List> hashedBlocks = [];
-
- if (flashParts == null)
- {
- return [.. hashedBlocks];
- }
-
- ulong CurrentBlockCount = 0;
- ulong TotalBlockCount = 0;
- foreach (FlashPart flashPart in flashParts)
- {
- TotalBlockCount += (ulong)flashPart.Stream.Length / BlockSize;
- }
-
- DateTime startTime = DateTime.Now;
-
- Logging.Log($"Total Block Count: {TotalBlockCount} - {TotalBlockCount * BlockSize / (1024 * 1024 * 1024)}GB");
- Logging.Log("Hashing resources...");
-
- bool blankPayloadPhase = false;
- ulong blankPayloadCount = 0;
-
- byte[] EMPTY_BLOCK_HASH = SHA256.HashData(new byte[BlockSize]);
-
- List> blankBlocks = [];
-
- foreach (FlashPart flashPart in flashParts)
- {
- _ = flashPart.Stream.Seek(0, SeekOrigin.Begin);
- long totalBlockCount = flashPart.Stream.Length / BlockSize;
-
- for (uint blockIndex = 0; blockIndex < totalBlockCount; blockIndex++)
- {
- byte[] blockBuffer = new byte[BlockSize];
- long streamPosition = flashPart.Stream.Position;
- _ = flashPart.Stream.Read(blockBuffer, 0, (int)BlockSize);
- byte[] blockHash = SHA256.HashData(blockBuffer);
-
- if (!StructuralComparisons.StructuralEqualityComparer.Equals(EMPTY_BLOCK_HASH, blockHash))
- {
- hashedBlocks.Add(new KeyValuePair(new ByteArrayKey(blockHash), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 1
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = (uint)((flashPart.StartLocation / BlockSize) + blockIndex),
- DiskAccessMethod = 0
- }
- ]
- },
- flashPart.Stream,
- (ulong)streamPosition
- )));
-
- if (blankPayloadPhase && blankPayloadCount < BlankSectorBufferSize)
- {
- foreach (KeyValuePair blankPayload in blankBlocks)
- {
- hashedBlocks.Add(blankPayload);
- }
- }
-
- blankPayloadPhase = false;
- blankPayloadCount = 0;
- blankBlocks.Clear();
- }
- else if (blankPayloadCount < BlankSectorBufferSize)
- {
- blankPayloadPhase = true;
- blankPayloadCount++;
-
- blankBlocks.Add(new KeyValuePair(new ByteArrayKey(blockHash), new BlockPayload(
- new WriteDescriptor()
- {
- BlockDataEntry = new BlockDataEntry()
- {
- BlockCount = 1,
- LocationCount = 1
- },
- DiskLocations =
- [
- new DiskLocation()
- {
- BlockIndex = (uint)((flashPart.StartLocation / BlockSize) + blockIndex),
- DiskAccessMethod = 0
- }
- ]
- },
- flashPart.Stream,
- (ulong)streamPosition
- )));
- }
- else if (blankPayloadCount >= BlankSectorBufferSize && blankBlocks.Count > 0)
- {
- foreach (KeyValuePair blankPayload in blankBlocks)
- {
- hashedBlocks.Add(blankPayload);
- }
-
- blankBlocks.Clear();
- }
-
- CurrentBlockCount++;
- ShowProgress(CurrentBlockCount, TotalBlockCount, startTime, blankPayloadPhase, Logging);
- }
- }
-
- Logging.Log("");
- Logging.Log($"FFU Block Count: {hashedBlocks.Count} - {hashedBlocks.Count * BlockSize / (1024 * 1024 * 1024)}GB");
-
- return [.. hashedBlocks];
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Flashing/ByteArrayKey.cs b/Img2Ffu.Library/Writer/Flashing/ByteArrayKey.cs
deleted file mode 100644
index 029ab69..0000000
--- a/Img2Ffu.Library/Writer/Flashing/ByteArrayKey.cs
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Diagnostics.CodeAnalysis;
-
-namespace Img2Ffu.Writer.Flashing
-{
- public readonly struct ByteArrayKey
- {
- public readonly byte[] Bytes;
- private readonly int _hashCode;
-
- public override bool Equals(object obj)
- {
- ByteArrayKey other = (ByteArrayKey)obj;
- return Compare(Bytes, other.Bytes);
- }
-
- public override int GetHashCode()
- {
- return _hashCode;
- }
-
- private static int GetHashCode([NotNull] byte[] bytes)
- {
- unchecked
- {
- int hash = 17;
- for (int i = 0; i < bytes.Length; i++)
- {
- hash = (hash * 23) + bytes[i];
- }
- return hash;
- }
- }
-
- public ByteArrayKey(byte[] bytes)
- {
- Bytes = bytes;
- _hashCode = GetHashCode(bytes);
- }
-
- public static ByteArrayKey Create(byte[] bytes)
- {
- return new ByteArrayKey(bytes);
- }
-
- public static unsafe bool Compare(byte[] a1, byte[] a2)
- {
- if (a1 == null || a2 == null || a1.Length != a2.Length)
- {
- return false;
- }
-
- fixed (byte* p1 = a1, p2 = a2)
- {
- byte* x1 = p1, x2 = p2;
- int l = a1.Length;
- for (int i = 0; i < l / 8; i++, x1 += 8, x2 += 8)
- {
- if (*(long*)x1 != *(long*)x2)
- {
- return false;
- }
- }
-
- if ((l & 4) != 0)
- {
- if (*(int*)x1 != *(int*)x2)
- {
- return false;
- }
-
- x1 += 4;
- x2 += 4;
- }
- if ((l & 2) != 0)
- {
- if (*(short*)x1 != *(short*)x2)
- {
- return false;
- }
-
- x1 += 2;
- x2 += 2;
- }
- if ((l & 1) != 0)
- {
- if (*x1 != *x2)
- {
- return false;
- }
- }
-
- return true;
- }
- }
-
- public static bool operator ==(ByteArrayKey left, ByteArrayKey right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(ByteArrayKey left, ByteArrayKey right)
- {
- return !(left == right);
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Flashing/FileSystemAllocationUtils.cs b/Img2Ffu.Library/Writer/Flashing/FileSystemAllocationUtils.cs
deleted file mode 100644
index 484dd56..0000000
--- a/Img2Ffu.Library/Writer/Flashing/FileSystemAllocationUtils.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using DiscUtils;
-using DiscUtils.Ntfs;
-
-namespace Img2Ffu.Writer.Flashing
-{
- internal class FileSystemAllocationUtils
- {
- public static (ulong StartOffset, ulong Length)[] GetNTFSAllocatedClustersMap(Stream fileSystemStream)
- {
- try
- {
- using NtfsFileSystem fileSystem = new(fileSystemStream);
- ulong totalClusters = (ulong)fileSystem.TotalClusters;
- ulong usedClusters = (ulong)fileSystem.UsedSpace / (ulong)fileSystem.ClusterSize;
-
- List ClustersInUse = [];
- for (ulong i = 0; i < totalClusters; i++)
- {
- if (fileSystem.IsClusterInUse((long)i))
- {
- ClustersInUse.Add((ulong)fileSystem.ClusterToOffset((long)i));
- }
- }
- return GetAllocatedClustersMap(ClustersInUse, fileSystem);
- }
- catch (InvalidFileSystemException)
- {
- // Not NTFS
- throw;
- }
- }
-
- private static (ulong StartOffset, ulong Length)[] GetAllocatedClustersMap(List ClustersInUse, IClusterBasedFileSystem fileSystem)
- {
- ulong sizeOfOneCluster = (ulong)fileSystem.ClusterSize;
- ClustersInUse.Sort();
-
- if (ClustersInUse[0] != 0)
- {
- ClustersInUse.Insert(0, ClustersInUse[0]);
- }
-
- List<(ulong StartOffset, ulong Length)> FileSystemParts = [];
-
- foreach (ulong clusterStartOffset in ClustersInUse)
- {
- if (FileSystemParts.Count == 0)
- {
- FileSystemParts.Add((clusterStartOffset, sizeOfOneCluster));
- }
- else
- {
- (ulong StartOffset, ulong Length) = FileSystemParts[^1];
- if (StartOffset + Length == clusterStartOffset)
- {
- FileSystemParts[^1] = (StartOffset, Length + sizeOfOneCluster);
- }
- else
- {
- FileSystemParts.Add((clusterStartOffset, sizeOfOneCluster));
- }
- }
- }
-
- return [.. FileSystemParts];
- }
-
- public static bool IsNTFS(Stream fileSystemStream)
- {
- _ = fileSystemStream.Seek(0, SeekOrigin.Begin);
- return NtfsFileSystem.Detect(fileSystemStream);
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/GPT/GPT.cs b/Img2Ffu.Library/Writer/GPT/GPT.cs
deleted file mode 100644
index 3d41b9d..0000000
--- a/Img2Ffu.Library/Writer/GPT/GPT.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using Img2Ffu.Writer.Helpers;
-
-namespace Img2Ffu
-{
- public partial class GPT
- {
- public byte[] GPTBuffer;
- private readonly uint HeaderOffset;
- private readonly uint HeaderSize;
- private uint TableOffset;
- private uint TableSize;
- private readonly uint PartitionEntrySize;
- private readonly uint MaxPartitions;
- internal ulong FirstUsableSector;
- internal ulong LastUsableSector;
- internal bool HasChanged = false;
-
- public List Partitions = [];
-
- internal static uint GetGPTSize(byte[] GPTBuffer, uint SectorSize)
- {
- uint? TempHeaderOffset = ByteOperations.FindAscii(GPTBuffer, "EFI PART") ?? throw new Exception("Bad GPT");
-
- uint HeaderOffset = (uint)TempHeaderOffset;
- uint TableOffset = HeaderOffset + SectorSize;
- uint MaxPartitions = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x50);
- uint PartitionEntrySize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x54);
- uint TableSize = MaxPartitions * PartitionEntrySize;
-
- return TableOffset + TableSize;
- }
-
- internal GPT(byte[] GPTBuffer, uint SectorSize)
- {
- this.GPTBuffer = GPTBuffer;
- uint? TempHeaderOffset = ByteOperations.FindAscii(GPTBuffer, "EFI PART") ?? throw new Exception("Bad GPT");
-
- HeaderOffset = (uint)TempHeaderOffset;
- HeaderSize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x0C);
- TableOffset = HeaderOffset + SectorSize;
- FirstUsableSector = ByteOperations.ReadUInt64(GPTBuffer, HeaderOffset + 0x28);
- LastUsableSector = ByteOperations.ReadUInt64(GPTBuffer, HeaderOffset + 0x30);
- MaxPartitions = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x50);
- PartitionEntrySize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x54);
- TableSize = MaxPartitions * PartitionEntrySize;
- if ((TableOffset + TableSize) > GPTBuffer.Length)
- {
- throw new Exception("Bad GPT");
- }
-
- uint PartitionOffset = TableOffset;
-
- while (PartitionOffset < (TableOffset + TableSize))
- {
- string Name = ByteOperations.ReadUnicodeString(GPTBuffer, PartitionOffset + 0x38, 0x48).TrimEnd([(char)0, ' ']);
- if (Name.Length == 0)
- {
- break;
- }
-
- Partition CurrentPartition = new()
- {
- Name = Name,
- FirstSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x20),
- LastSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x28),
- PartitionTypeGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x00),
- PartitionGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x10),
- Attributes = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x30)
- };
- Partitions.Add(CurrentPartition);
- PartitionOffset += PartitionEntrySize;
- }
-
- HasChanged = false;
- }
-
- internal Partition GetPartition(string Name)
- {
- return Partitions.Where(p => string.Compare(p.Name, Name, true) == 0).FirstOrDefault();
- }
-
- internal byte[] Rebuild(uint SectorSize)
- {
- if (GPTBuffer == null)
- {
- TableSize = 0x21 * SectorSize;
- TableOffset = 0;
- GPTBuffer = new byte[TableSize];
- }
- else
- {
- Array.Clear(GPTBuffer, (int)TableOffset, (int)TableSize);
- }
-
- uint PartitionOffset = TableOffset;
- foreach (Partition CurrentPartition in Partitions)
- {
- ByteOperations.WriteGuid(GPTBuffer, PartitionOffset + 0x00, CurrentPartition.PartitionTypeGuid);
- ByteOperations.WriteGuid(GPTBuffer, PartitionOffset + 0x10, CurrentPartition.PartitionGuid);
- ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x20, CurrentPartition.FirstSector);
- ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x28, CurrentPartition.LastSector);
- ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x30, CurrentPartition.Attributes);
- ByteOperations.WriteUnicodeString(GPTBuffer, PartitionOffset + 0x38, CurrentPartition.Name, 0x48);
-
- PartitionOffset += PartitionEntrySize;
- }
-
- ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x58, ByteOperations.CRC32(GPTBuffer, TableOffset, TableSize));
- ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x10, 0);
- ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x10, ByteOperations.CRC32(GPTBuffer, HeaderOffset, HeaderSize));
-
- return GPTBuffer;
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/GPT/Partition.cs b/Img2Ffu.Library/Writer/GPT/Partition.cs
deleted file mode 100644
index d2be15e..0000000
--- a/Img2Ffu.Library/Writer/GPT/Partition.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-namespace Img2Ffu
-{
- public partial class GPT
- {
- public class Partition
- {
- private ulong _SizeInSectors;
- private ulong _FirstSector;
- private ulong _LastSector;
-
- public required string Name; // 0x48
- public Guid PartitionTypeGuid; // 0x10
- public Guid PartitionGuid; // 0x10
- internal ulong Attributes; // 0x08
-
- internal ulong SizeInSectors
- {
- get => _SizeInSectors != 0 ? _SizeInSectors : LastSector - FirstSector + 1;
- set
- {
- _SizeInSectors = value;
- if (FirstSector != 0)
- {
- LastSector = FirstSector + _SizeInSectors - 1;
- }
- }
- }
-
- internal ulong FirstSector // 0x08
- {
- get => _FirstSector;
- set
- {
- _FirstSector = value;
- if (_SizeInSectors != 0)
- {
- _LastSector = FirstSector + _SizeInSectors - 1;
- }
- }
- }
-
- internal ulong LastSector // 0x08
- {
- get => _LastSector;
- set
- {
- _LastSector = value;
- _SizeInSectors = 0;
- }
- }
-
- public string Volume => @"\\?\Volume" + PartitionGuid.ToString("b") + @"\";
-
- public string FirstSectorAsString
- {
- get => "0x" + FirstSector.ToString("X16");
- set => FirstSector = Convert.ToUInt64(value, 16);
- }
-
- public string LastSectorAsString
- {
- get => "0x" + LastSector.ToString("X16");
- set => LastSector = Convert.ToUInt64(value, 16);
- }
-
- public string AttributesAsString
- {
- get => "0x" + Attributes.ToString("X16");
- set => Attributes = Convert.ToUInt64(value, 16);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Helpers/ByteOperations.cs b/Img2Ffu.Library/Writer/Helpers/ByteOperations.cs
deleted file mode 100644
index 4b2414f..0000000
--- a/Img2Ffu.Library/Writer/Helpers/ByteOperations.cs
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-// These functions assume same endianness for the CPU architecture and the raw data it reads from or writes to.
-
-namespace Img2Ffu.Writer.Helpers
-{
- internal static class ByteOperations
- {
- internal static string ReadUnicodeString(byte[] ByteArray, uint Offset, uint Length)
- {
- byte[] Bytes = new byte[Length];
- Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length);
- return System.Text.Encoding.Unicode.GetString(Bytes);
- }
-
- internal static void WriteAsciiString(byte[] ByteArray, uint Offset, string Text, uint? MaxBufferLength = null)
- {
- if (MaxBufferLength != null)
- {
- Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
- }
-
- byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(Text);
- int WriteLength = TextBytes.Length;
- if (WriteLength > MaxBufferLength)
- {
- WriteLength = (int)MaxBufferLength;
- }
-
- Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
- }
-
- internal static void WriteUnicodeString(byte[] ByteArray, uint Offset, string Text, uint? MaxBufferLength = null)
- {
- if (MaxBufferLength != null)
- {
- Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
- }
-
- byte[] TextBytes = System.Text.Encoding.Unicode.GetBytes(Text);
- int WriteLength = TextBytes.Length;
- if (WriteLength > MaxBufferLength)
- {
- WriteLength = (int)MaxBufferLength;
- }
-
- Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength);
- }
-
- internal static uint ReadUInt32(byte[] ByteArray, uint Offset)
- {
- return BitConverter.ToUInt32(ByteArray, (int)Offset);
- }
-
- internal static void WriteUInt32(byte[] ByteArray, uint Offset, uint Value)
- {
- Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
- }
-
- internal static ulong ReadUInt64(byte[] ByteArray, uint Offset)
- {
- return BitConverter.ToUInt64(ByteArray, (int)Offset);
- }
-
- internal static void WriteUInt64(byte[] ByteArray, uint Offset, ulong Value)
- {
- Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
- }
-
- internal static Guid ReadGuid(byte[] ByteArray, uint Offset)
- {
- byte[] GuidBuffer = new byte[0x10];
- Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10);
- return new Guid(GuidBuffer);
- }
-
- internal static void WriteGuid(byte[] ByteArray, uint Offset, Guid Value)
- {
- Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10);
- }
-
- internal static uint? FindAscii(byte[] SourceBuffer, string Pattern)
- {
- return FindPattern(SourceBuffer, System.Text.Encoding.ASCII.GetBytes(Pattern), null, null);
- }
-
- internal static uint? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[]? Mask, byte[]? OutPattern)
- {
- return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern);
- }
-
- internal static bool Compare(byte[] Array1, byte[] Array2)
- {
- return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Array1, Array2);
- }
-
- internal static uint? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern)
- {
- // The mask is optional.
- // In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
-
- uint? Result = null;
-
- uint SearchPosition = SourceOffset;
- int i;
-
- while (SearchPosition <= SourceBuffer.Length - Pattern.Length && (SourceSize == null || SearchPosition <= SourceOffset + SourceSize - Pattern.Length))
- {
- bool Match = true;
- for (i = 0; i < Pattern.Length; i++)
- {
- if (SourceBuffer[SearchPosition + i] != Pattern[i])
- {
- if (Mask == null || Mask[i] == 0)
- {
- Match = false;
- break;
- }
- }
- }
-
- if (Match)
- {
- Result = SearchPosition;
-
- if (OutPattern != null)
- {
- Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
- }
-
- break;
- }
-
- SearchPosition++;
- }
-
- return Result;
- }
-
- private static readonly uint[] CRC32Table = [
- 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
- 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
- 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
- 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
- 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
- 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
- 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
- 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
- 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
- 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
- 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
- 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
- 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
- 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
- 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
- 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
- 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
- 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
- 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
- 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
- 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
- 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
- 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
- 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
- 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
- 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
- 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
- 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
- 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
- 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
- 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
- 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
- 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
- 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
- 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
- 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
- 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
- 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
- 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
- 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
- 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
- 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
- ];
-
- internal static uint CRC32(byte[] Input, uint Offset, uint Length)
- {
- if (Input == null || Offset + Length > Input.Length)
- {
- throw new ArgumentException();
- }
-
- unchecked
- {
- uint crc = (uint)((uint)0 ^ -1);
- for (uint i = Offset; i < Offset + Length; i++)
- {
- crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF];
- }
- crc = (uint)(crc ^ -1);
-
- if (crc < 0)
- {
- crc += (uint)4294967296;
- }
-
- return crc;
- }
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/ILogging.cs b/Img2Ffu.Library/Writer/ILogging.cs
deleted file mode 100644
index 2d02004..0000000
--- a/Img2Ffu.Library/Writer/ILogging.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Img2Ffu.Writer
-{
- public interface ILogging
- {
- public void Log(string message, ILoggingLevel severity = ILoggingLevel.Information, bool returnLine = true);
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/ILoggingLevel.cs b/Img2Ffu.Library/Writer/ILoggingLevel.cs
deleted file mode 100644
index dfc30dc..0000000
--- a/Img2Ffu.Library/Writer/ILoggingLevel.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Img2Ffu.Writer
-{
- public enum ILoggingLevel
- {
- Information,
- Warning,
- Error
- }
-}
diff --git a/Img2Ffu.Library/Writer/ImageSplitter.cs b/Img2Ffu.Library/Writer/ImageSplitter.cs
deleted file mode 100644
index f22cb9b..0000000
--- a/Img2Ffu.Library/Writer/ImageSplitter.cs
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using Img2Ffu.Writer.Streams;
-using static Img2Ffu.GPT;
-
-namespace Img2Ffu.Writer
-{
- internal class ImageSplitter
- {
- internal static readonly string IS_UNLOCKED_PARTITION_NAME = "IS_UNLOCKED";
- internal static readonly string HACK_PARTITION_NAME = "HACK";
- internal static readonly string BACKUP_BS_NV_PARTITION_NAME = "BACKUP_BS_NV";
- internal static readonly string UEFI_BS_NV_PARTITION_NAME = "UEFI_BS_NV";
-
- internal static GPT GetGPT(Stream stream, uint BlockSize, uint sectorSize, ILogging Logging)
- {
- byte[] GPTBuffer = new byte[BlockSize];
- _ = stream.Read(GPTBuffer, 0, (int)BlockSize);
-
- uint requiredGPTBufferSize = GetGPTSize(GPTBuffer, sectorSize);
- if (BlockSize < requiredGPTBufferSize)
- {
- string errorMessage = $"The Block size is too small to contain the GPT, the GPT is {requiredGPTBufferSize} bytes long, the Block size is {BlockSize} bytes long";
- Logging.Log(errorMessage, ILoggingLevel.Error);
- throw new Exception(errorMessage);
- }
-
- uint sectorsInABlock = BlockSize / sectorSize;
-
- GPT GPT = new(GPTBuffer, sectorSize);
-
- if (BlockSize > requiredGPTBufferSize && GPT.Partitions.OrderBy(x => x.FirstSector).Any(x => x.FirstSector < sectorsInABlock))
- {
- Partition conflictingPartition = GPT.Partitions.OrderBy(x => x.FirstSector).First(x => x.FirstSector < sectorsInABlock);
-
- string errorMessage = $"The Block size is too big to contain only the GPT, the GPT is {requiredGPTBufferSize} bytes long, the Block size is {BlockSize} bytes long. The overlapping partition is {conflictingPartition.Name} at {conflictingPartition.FirstSector * sectorSize}";
- Logging.Log(errorMessage, ILoggingLevel.Error);
- throw new Exception(errorMessage);
- }
-
- return GPT;
- }
-
- internal static (FlashPart[], List partitions) GetImageSlices(Stream stream, uint BlockSize, string[] ExcludedPartitionNames, uint sectorSize, ILogging Logging)
- {
- GPT GPT = GetGPT(stream, BlockSize, sectorSize, Logging);
- uint sectorsInABlock = BlockSize / sectorSize;
-
- Logging.Log($"Sector Size: {sectorSize}");
- Logging.Log($"Block Size: {BlockSize}");
- Logging.Log($"Sectors in a Block: {sectorsInABlock}");
-
- List Partitions = GPT.Partitions;
-
- bool isUnlocked = GPT.GetPartition(IS_UNLOCKED_PARTITION_NAME) != null;
- bool isUnlockedSpecA = GPT.GetPartition(HACK_PARTITION_NAME) != null && GPT.GetPartition(BACKUP_BS_NV_PARTITION_NAME) != null;
-
- if (isUnlocked)
- {
- Logging.Log($"The phone is an unlocked Spec B phone, {UEFI_BS_NV_PARTITION_NAME} will be kept in the FFU image for the unlock to work");
- }
-
- if (isUnlockedSpecA)
- {
- Logging.Log($"The phone is an UEFI unlocked Spec A phone, {UEFI_BS_NV_PARTITION_NAME} will be kept in the FFU image for the unlock to work");
- }
-
- List flashParts = [];
-
- Logging.Log("Partitions with a * appended are ignored partitions");
- Logging.Log("");
-
- int maxPartitionNameSize = Partitions.Select(x => x.Name.Length).Max() + 1;
- int maxPartitionLastSector = Partitions.Select(x => x.LastSector.ToString().Length).Max() + 1;
-
- Logging.Log($"{"Name".PadRight(maxPartitionNameSize)} - " +
- $"{"First".PadRight(maxPartitionLastSector)} - " +
- $"{"Last".PadRight(maxPartitionLastSector)} - " +
- $"{"Sectors".PadRight(maxPartitionLastSector)} - " +
- $"{"Blocks".PadRight(maxPartitionLastSector)}",
- ILoggingLevel.Information);
- Logging.Log("");
-
- ulong CurrentStartingOffset = 0;
- ulong CurrentEndingOffset = 0;
- List<(ulong StartOffset, ulong Length)> AllocatedPartitionsMap = [];
-
- foreach (Partition Partition in Partitions.OrderBy(x => x.FirstSector))
- {
- bool IsPartitionExcluded = false;
-
- if (ExcludedPartitionNames.Any(x => x == Partition.Name))
- {
- IsPartitionExcluded = true;
- if (isUnlocked && Partition.Name == UEFI_BS_NV_PARTITION_NAME)
- {
- IsPartitionExcluded = false;
- }
-
- if (isUnlockedSpecA && Partition.Name == UEFI_BS_NV_PARTITION_NAME)
- {
- IsPartitionExcluded = false;
- }
- }
-
- string name = $"{(IsPartitionExcluded ? "*" : "")}{Partition.Name}";
-
- Logging.Log($"{name.PadRight(maxPartitionNameSize)} - " +
- $"{(Partition.FirstSector + "s").PadRight(maxPartitionLastSector)} - " +
- $"{(Partition.LastSector + "s").PadRight(maxPartitionLastSector)} - " +
- $"{(Partition.SizeInSectors + "s").PadRight(maxPartitionLastSector)} - " +
- $"{((Partition.SizeInSectors / (double)sectorsInABlock) + "c").PadRight(maxPartitionLastSector)}",
- IsPartitionExcluded ? ILoggingLevel.Warning : ILoggingLevel.Information);
-
- ulong CurrentPartitionStartingOffset = Partition.FirstSector * sectorSize;
- ulong CurrentPartitionEndingOffset = (Partition.LastSector + 1) * sectorSize;
-
- if (IsPartitionExcluded)
- {
- if (AllocatedPartitionsMap.Count != 0)
- {
- ulong AllocationTotalSizeInBytes = CurrentEndingOffset - CurrentStartingOffset;
- (ulong StartOffset, ulong Length)[] AllocatedBlocks = GetBlockAlignedAllocationMap([.. AllocatedPartitionsMap], AllocationTotalSizeInBytes, BlockSize);
-
- foreach ((ulong StartOffset, ulong Length) in AllocatedBlocks)
- {
- ulong blockStartOffset = CurrentStartingOffset + StartOffset;
- PartialStream blockStream = new(stream, (long)blockStartOffset, (long)(blockStartOffset + Length));
- FlashPart flashPart = new(blockStream, blockStartOffset);
- flashParts.Add(flashPart);
- }
-
- AllocatedPartitionsMap.Clear();
- CurrentStartingOffset = 0;
- CurrentEndingOffset = 0;
- }
- }
- else
- {
- // 0 would be the GPT, we can't land in this case here because we deal with partitions
- if (CurrentStartingOffset == 0)
- {
- CurrentStartingOffset = CurrentPartitionStartingOffset;
- CurrentEndingOffset = CurrentPartitionEndingOffset;
- }
- else
- {
- CurrentEndingOffset = CurrentPartitionEndingOffset;
- }
-
- ulong allocationOffset = CurrentPartitionStartingOffset - CurrentStartingOffset;
-
- PartialStream partialStream = new(stream, (long)CurrentPartitionStartingOffset, (long)CurrentPartitionEndingOffset);
-
- /*if (FileSystemAllocationUtils.IsNTFS(partialStream))
- {
- (ulong StartOffset, ulong Length)[] AllocatedClusterMap = FileSystemAllocationUtils.GetNTFSAllocatedClustersMap(partialStream);
- //AllocatedPartitionsMap.AddRange(AllocatedClusterMap.Select(x => (allocationOffset + x.StartOffset, x.Length)));
-
- (ulong StartOffset, ulong Length) lastElement = AllocatedClusterMap.MaxBy(x => x.StartOffset);
- AllocatedPartitionsMap.Add((allocationOffset, lastElement.StartOffset + lastElement.Length));
- }
- else*/
- {
- AllocatedPartitionsMap.Add((allocationOffset, Partition.SizeInSectors * sectorSize));
- }
- }
- }
-
- if (AllocatedPartitionsMap.Count != 0)
- {
- (ulong StartOffset, ulong Length)[] AllocatedBlocks = GetBlockAlignedAllocationMap([.. AllocatedPartitionsMap], CurrentStartingOffset - CurrentEndingOffset, BlockSize);
-
- foreach ((ulong StartOffset, ulong Length) in AllocatedBlocks)
- {
- ulong blockStartOffset = CurrentStartingOffset + StartOffset;
- PartialStream blockStream = new(stream, (long)blockStartOffset, (long)(blockStartOffset + Length));
- FlashPart flashPart = new(blockStream, blockStartOffset);
- flashParts.Add(flashPart);
- }
-
- AllocatedPartitionsMap.Clear();
- CurrentStartingOffset = 0;
- CurrentEndingOffset = 0;
- }
-
- FlashPart[] finalFlashParts = [.. flashParts];
-
- Logging.Log("");
- Logging.Log("Final Flash Parts");
- Logging.Log("");
- PrintFlashParts(finalFlashParts, sectorSize, BlockSize, Logging);
- Logging.Log("");
-
- foreach (FlashPart flashPart in finalFlashParts)
- {
- ulong totalSectors = (ulong)flashPart.Stream.Length / sectorSize;
- ulong firstSector = flashPart.StartLocation / sectorSize;
- ulong lastSector = firstSector + totalSectors - 1;
-
- if (firstSector % sectorsInABlock != 0)
- {
- string errorMessage = $"- The stream doesn't start on a Block boundary (Total Sectors: {totalSectors} - First Sector: {firstSector} - Last Sector: {lastSector}) - Overflow: {firstSector % sectorsInABlock}, a Block is {sectorsInABlock} sectors";
- Logging.Log(errorMessage, ILoggingLevel.Error);
- throw new Exception(errorMessage);
- }
-
- if ((lastSector + 1) % sectorsInABlock != 0)
- {
- string errorMessage = $"- The stream doesn't end on a Block boundary (Total Sectors: {totalSectors} - First Sector: {firstSector} - Last Sector: {lastSector}) - Overflow: {(lastSector + 1) % sectorsInABlock}, a Block is {sectorsInABlock} sectors";
- Logging.Log(errorMessage, ILoggingLevel.Error);
- throw new Exception(errorMessage);
- }
- }
-
- return (finalFlashParts, Partitions);
- }
-
- internal static (ulong StartOffset, ulong Length)[] GetBlockAlignedAllocationMap((ulong StartOffset, ulong Length)[] AllocationMap, ulong TotalSizeInBytes, ulong BlockSize)
- {
- List<(ulong StartOffset, ulong Length)> AllocatedBlocks = [];
-
- (ulong MaxStartOffset, ulong MaxLength) = AllocationMap.MaxBy(x => x.StartOffset + x.Length);
- ulong MaxEndOffset = MaxStartOffset + MaxLength;
-
- ulong MaxNumberOfBlocks = (MaxEndOffset / BlockSize) + 1;
-
- (ulong MinStartOffset, ulong MinLength) = AllocationMap.MinBy(x => x.StartOffset);
- ulong MinNumberOfBlocks = MinStartOffset / BlockSize;
-
- for (ulong CurrentBlockIndex = MinNumberOfBlocks; CurrentBlockIndex < MaxNumberOfBlocks; CurrentBlockIndex++)
- {
- ulong CurrentBlockStartOffset = CurrentBlockIndex * BlockSize;
- ulong CurrentBlockEndOffset = CurrentBlockStartOffset + BlockSize;
-
- if (AllocationMap.Any(Allocation => (CurrentBlockEndOffset > Allocation.StartOffset) && ((Allocation.StartOffset + Allocation.Length) > CurrentBlockStartOffset)))
- {
- if (AllocatedBlocks.Count == 0)
- {
- AllocatedBlocks.Add((CurrentBlockStartOffset, BlockSize));
- }
- else
- {
- (ulong LastStartOffset, ulong LastLength) = AllocatedBlocks[^1];
- if (LastStartOffset + LastLength == CurrentBlockStartOffset)
- {
- AllocatedBlocks[^1] = (LastStartOffset, LastLength + BlockSize);
- }
- else
- {
- AllocatedBlocks.Add((CurrentBlockStartOffset, BlockSize));
- }
- }
- }
- }
-
- ulong NewAllocationTotalSizeInBytes = AllocatedBlocks[^1].StartOffset + AllocatedBlocks[^1].Length;
-
- if (NewAllocationTotalSizeInBytes > TotalSizeInBytes)
- {
- AllocatedBlocks[^1] = (AllocatedBlocks[^1].StartOffset, AllocatedBlocks[^1].Length - (NewAllocationTotalSizeInBytes - TotalSizeInBytes));
- }
-
- return [.. AllocatedBlocks];
- }
-
- internal static void PrintFlashParts(FlashPart[] finalFlashParts, uint sectorSize, uint BlockSize, ILogging Logging)
- {
- for (int i = 0; i < finalFlashParts.Length; i++)
- {
- FlashPart flashPart = finalFlashParts[i];
- PrintFlashPart(flashPart, sectorSize, BlockSize, $"FlashPart[{i}]", Logging);
- }
- }
-
- internal static void PrintFlashPart(FlashPart flashPart, uint sectorSize, uint BlockSize, string name, ILogging Logging)
- {
- uint sectorsInABlock = BlockSize / sectorSize;
-
- ulong totalSectors = (ulong)flashPart.Stream.Length / sectorSize;
- ulong firstSector = flashPart.StartLocation / sectorSize;
- ulong lastSector = firstSector + totalSectors - 1;
-
- Logging.Log($"{name} - {firstSector}s - {lastSector}s - {totalSectors}s - {totalSectors / (double)sectorsInABlock}c", ILoggingLevel.Information);
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/LoggingHelpers.cs b/Img2Ffu.Library/Writer/LoggingHelpers.cs
deleted file mode 100644
index 22e897f..0000000
--- a/Img2Ffu.Library/Writer/LoggingHelpers.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Img2Ffu.Writer
-{
- internal static class LoggingHelpers
- {
- internal static string GetDismLikeProgBar(int perc)
- {
- int eqsLength = (int)((double)perc / 100 * 55);
- string bases = new string('=', eqsLength) + new string(' ', 55 - eqsLength);
- bases = bases.Insert(28, perc + "%");
- if (perc == 100)
- {
- bases = bases[1..];
- }
- else if (perc < 10)
- {
- bases = bases.Insert(28, " ");
- }
-
- return $"[{bases}]";
- }
- }
-}
diff --git a/Img2Ffu.Library/Writer/Manifest/FullFlashManifest.cs b/Img2Ffu.Library/Writer/Manifest/FullFlashManifest.cs
deleted file mode 100644
index d84a82e..0000000
--- a/Img2Ffu.Library/Writer/Manifest/FullFlashManifest.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer.Manifest
-{
- internal class FullFlashManifest
- {
- public required string OSVersion;
- public string AntiTheftVersion = "1.1"; // Allow flashing on all devices
- public string Description = "Update on: " + DateTime.Now.ToString("u") + "::\r\n";
-
- public string StateSeparationLevel = "0";
- public string UEFI = "True";
- public string Version = "2.0";
- public required string DevicePlatformId3;
- public required string DevicePlatformId2;
- public required string DevicePlatformId1;
- public required string DevicePlatformId0;
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Manifest/ManifestIni.cs b/Img2Ffu.Library/Writer/Manifest/ManifestIni.cs
deleted file mode 100644
index a841bec..0000000
--- a/Img2Ffu.Library/Writer/Manifest/ManifestIni.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer.Manifest
-{
- internal class ManifestIni
- {
- internal static string BuildUpFullFlashSection(FullFlashManifest fullFlash)
- {
- string FullFlashSection = "[FullFlash]\r\n";
-
- if (!string.IsNullOrEmpty(fullFlash.OSVersion))
- {
- FullFlashSection += $"OSVersion = {fullFlash.OSVersion}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.AntiTheftVersion))
- {
- FullFlashSection += $"AntiTheftVersion = {fullFlash.AntiTheftVersion}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.Description))
- {
- FullFlashSection += $"Description = {fullFlash.Description}\r\n";
- }
-
- FullFlashSection += "\r\n";
-
- if (!string.IsNullOrEmpty(fullFlash.StateSeparationLevel))
- {
- FullFlashSection += $"StateSeparationLevel = {fullFlash.StateSeparationLevel}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.UEFI))
- {
- FullFlashSection += $"UEFI = {fullFlash.UEFI}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.Version))
- {
- FullFlashSection += $"Version = {fullFlash.Version}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId3))
- {
- FullFlashSection += $"DevicePlatformId3 = {fullFlash.DevicePlatformId3}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId2))
- {
- FullFlashSection += $"DevicePlatformId2 = {fullFlash.DevicePlatformId2}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId1))
- {
- FullFlashSection += $"DevicePlatformId1 = {fullFlash.DevicePlatformId1}\r\n";
- }
-
- if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId0))
- {
- FullFlashSection += $"DevicePlatformId0 = {fullFlash.DevicePlatformId0}\r\n";
- }
-
- FullFlashSection += "\r\n";
-
- return FullFlashSection;
- }
-
- internal static string BuildUpStoreSection(StoreManifest store)
- {
- string StoreSection = "[Store]\r\n";
- StoreSection += $"OnlyAllocateDefinedGptEntries = False\r\n";
- StoreSection += $"StoreId = {{5a585bae-900b-41b5-b736-a4cecffc34b4}}\r\n";
- StoreSection += $"IsMainOSStore = False\r\n";
- StoreSection += $"DevicePath = VenHw(860845C1-BE09-4355-8BC1-30D64FF8E63A)\r\n";
- StoreSection += $"StoreType = Default\r\n";
- StoreSection += $"MinSectorCount = {store.MinSectorCount}\r\n";
- StoreSection += $"SectorSize = {store.SectorSize}\r\n";
- StoreSection += "\r\n";
- return StoreSection;
- }
-
- internal static string BuildUpPartitionSection(PartitionManifest partition)
- {
- string PartitionSection = "[Partition]\r\n";
-
- if (partition.ByteAlignment.HasValue)
- {
- PartitionSection += $"ByteAlignment = {partition.ByteAlignment.Value}\r\n";
- }
-
- if (!string.IsNullOrEmpty(partition.FileSystem))
- {
- PartitionSection += $"FileSystem = {partition.FileSystem}\r\n";
- }
-
- PartitionSection += $"UsedSectors = {partition.UsedSectors}\r\n";
-
- if (partition.UseAllSpace.HasValue)
- {
- PartitionSection += $"UseAllSpace = {(partition.UseAllSpace.Value ? "True" : "False")}\r\n";
- }
-
- if (partition.Type != null)
- {
- PartitionSection += $"Type = {{{partition.Type.Value.ToString().ToUpper()}}}\r\n";
- }
-
- PartitionSection += $"TotalSectors = {partition.TotalSectors}\r\n";
-
- if (partition.RequiredToFlash.HasValue)
- {
- PartitionSection += $"RequiredToFlash = {(partition.RequiredToFlash.Value ? "True" : "False")}\r\n";
- }
-
- if (!string.IsNullOrEmpty(partition.Primary))
- {
- PartitionSection += $"Primary = {partition.Primary}\r\n";
- }
-
- if (!string.IsNullOrEmpty(partition.Name))
- {
- PartitionSection += $"Name = {partition.Name}\r\n";
- }
-
- if (partition.ClusterSize.HasValue)
- {
- PartitionSection += $"ClusterSize = {partition.ClusterSize.Value}\r\n";
- }
-
- PartitionSection += "\r\n";
-
- return PartitionSection;
- }
-
- internal static string BuildUpStoragePoolSection()
- {
- string StoragePoolSection = "[StoragePool]\r\n";
- StoragePoolSection += "Name = OSPool\r\n";
- StoragePoolSection += "\r\n";
- return StoragePoolSection;
- }
-
- internal static string BuildUpManifest(FullFlashManifest fullFlash, StoreManifest store, List partitions)
- {
- string Manifest = "";
-
- Manifest += BuildUpFullFlashSection(fullFlash);
- Manifest += BuildUpStoragePoolSection();
- Manifest += BuildUpStoreSection(store);
-
- foreach (PartitionManifest partition in partitions)
- {
- Manifest += BuildUpPartitionSection(partition);
- }
-
- return Manifest;
- }
-
- internal static List GPTPartitionsToPartitions(List partitions)
- {
- List Parts = [];
-
- // TODO: implement more
- foreach (GPT.Partition part in partitions)
- {
- Parts.Add(new PartitionManifest() { Name = part.Name, TotalSectors = (uint)part.SizeInSectors, UsedSectors = (uint)part.SizeInSectors, RequiredToFlash = true, Type = part.PartitionTypeGuid });
- }
-
- return Parts;
- }
-
- internal static string BuildUpManifest(FullFlashManifest fullFlash, StoreManifest store, List partitions)
- {
- return BuildUpManifest(fullFlash, store, GPTPartitionsToPartitions(partitions));
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Manifest/PartitionManifest.cs b/Img2Ffu.Library/Writer/Manifest/PartitionManifest.cs
deleted file mode 100644
index 343831d..0000000
--- a/Img2Ffu.Library/Writer/Manifest/PartitionManifest.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer.Manifest
-{
- internal class PartitionManifest
- {
- public bool? RequiredToFlash;
- public uint UsedSectors;
- public Guid? Type;
- public uint TotalSectors;
- public string Primary;
- public required string Name;
- public string FileSystem;
- public uint? ByteAlignment;
- public uint? ClusterSize;
- public bool? UseAllSpace;
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Manifest/StoreManifest.cs b/Img2Ffu.Library/Writer/Manifest/StoreManifest.cs
deleted file mode 100644
index cca9ff1..0000000
--- a/Img2Ffu.Library/Writer/Manifest/StoreManifest.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer.Manifest
-{
- internal class StoreManifest
- {
- public uint SectorSize;
- public uint MinSectorCount;
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY.cs b/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY.cs
deleted file mode 100644
index 9faa171..0000000
--- a/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-Copyright (c) 2018, Proto Beta Test - protobetatest.com - @ProtoBetaTest
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Streams
-{
- public partial class DeviceStream
- {
- [StructLayout(LayoutKind.Sequential)]
- private struct DISK_GEOMETRY
- {
- internal long Cylinders;
- internal MEDIA_TYPE MediaType;
- internal uint TracksPerCylinder;
- internal uint SectorsPerTrack;
- internal uint BytesPerSector;
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY_EX.cs b/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY_EX.cs
deleted file mode 100644
index 53f93ce..0000000
--- a/Img2Ffu.Library/Writer/Streams/DISK_GEOMETRY_EX.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-Copyright (c) 2018, Proto Beta Test - protobetatest.com - @ProtoBetaTest
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Streams
-{
- public partial class DeviceStream
- {
- [StructLayout(LayoutKind.Sequential)]
- private struct DISK_GEOMETRY_EX
- {
- internal DISK_GEOMETRY Geometry;
- internal long DiskSize;
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
- internal byte[] Data;
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Streams/DeviceStream.cs b/Img2Ffu.Library/Writer/Streams/DeviceStream.cs
deleted file mode 100644
index 7a5439d..0000000
--- a/Img2Ffu.Library/Writer/Streams/DeviceStream.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-Copyright (c) 2018, Proto Beta Test - protobetatest.com - @ProtoBetaTest
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-using Microsoft.Win32.SafeHandles;
-using System.ComponentModel;
-using System.Runtime.InteropServices;
-
-namespace Img2Ffu.Streams
-{
- public partial class DeviceStream : Stream
- {
- private const uint GENERIC_READ = 0x80000000;
- private const uint GENERIC_WRITE = 0x40000000;
-
- private const uint OPEN_EXISTING = 3;
- private const uint FILE_ATTRIBUTE_DEVICE = 0x40;
- private const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
- private const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
- private const uint DISK_BASE = 7;
-
- private const uint FILE_ANY_ACCESS = 0;
- private const uint FILE_SHARE_READ = 1;
- private const uint FILE_SHARE_WRITE = 2;
-
- private const uint FILE_DEVICE_FILE_SYSTEM = 9;
- private const uint METHOD_BUFFERED = 0;
-
- private static readonly uint DISK_GET_DRIVE_GEOMETRY_EX = CTL_CODE(DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS);
- private static readonly uint FSCTL_LOCK_VOLUME = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS);
- private static readonly uint FSCTL_UNLOCK_VOLUME = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- private static extern nint CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, nint lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, nint hTemplateFile);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool ReadFile(nint hFile, byte[] lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, nint lpOverlapped);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool WriteFile(nint hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, nint lpOverlapped);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern uint DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode, nint lpInBuffer, uint nInBufferSize, nint lpOutBuffer, int nOutBufferSize, ref uint lpBytesReturned, nint lpOverlapped);
-
- [DllImport("kernel32.dll")]
- private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, out long lpNewFilePointer, uint dwMoveMethod);
-
- private SafeFileHandle? handleValue = null;
- private long _Position = 0;
- private readonly long _length = 0;
- private readonly uint _sectorsize = 0;
- private readonly bool _canWrite = false;
- private readonly bool _canRead = false;
- private bool disposed = false;
-
- private static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
- {
- return (DeviceType << 16) | (Access << 14) | (Function << 2) | Method;
- }
-
- public DeviceStream(string device, FileAccess access)
- {
- if (string.IsNullOrEmpty(device))
- {
- throw new ArgumentNullException(nameof(device));
- }
-
- uint fileAccess = 0;
- switch (access)
- {
- case FileAccess.Read:
- fileAccess = GENERIC_READ;
- _canRead = true;
- break;
- case FileAccess.ReadWrite:
- fileAccess = GENERIC_READ | GENERIC_WRITE;
- _canRead = true;
- _canWrite = true;
- break;
- case FileAccess.Write:
- fileAccess = GENERIC_WRITE;
- _canWrite = true;
- break;
- }
-
- string devicePath = @"\\.\PhysicalDrive" + device.ToLower().Replace(@"\\.\physicaldrive", "");
-
- (_length, _sectorsize) = GetDiskProperties(devicePath);
-
- nint ptr = CreateFile(devicePath, fileAccess, 0, nint.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_DEVICE | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, nint.Zero);
- handleValue = new SafeFileHandle(ptr, true);
-
- if (handleValue.IsInvalid)
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
-
- uint lpBytesReturned = 0;
- uint result = DeviceIoControl(handleValue, FSCTL_LOCK_VOLUME, nint.Zero, 0, nint.Zero, 0, ref lpBytesReturned, nint.Zero);
-
- if (result == 0)
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
- }
-
- public override bool CanRead => _canRead;
-
- public override bool CanSeek => true;
-
- public override bool CanWrite => _canWrite;
-
- public override void Flush()
- {
- return;
- }
-
- public override long Length => _length;
-
- public override long Position
- {
- get => _Position;
- set => Seek(value, SeekOrigin.Begin);
- }
-
- ///
- ///
- /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and
- /// (offset + count - 1) replaced by the bytes read from the current source.
- /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream.
- /// The maximum number of bytes to be read from the current stream.
- ///
- private int InternalRead(byte[] buffer, int offset, int count)
- {
- int BytesRead = 0;
- byte[] BufBytes = new byte[count];
- if (!ReadFile(handleValue.DangerousGetHandle(), BufBytes, count, ref BytesRead, nint.Zero))
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
- for (int i = 0; i < BytesRead; i++)
- {
- buffer[offset + i] = BufBytes[i];
- }
-
- _Position += count;
-
- return BytesRead;
- }
-
- ///
- /// Some devices cannot read portions that are not modulo a sector, this aims to fix that issue.
- ///
- /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and
- /// (offset + count - 1) replaced by the bytes read from the current source.
- /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream.
- /// The maximum number of bytes to be read from the current stream.
- ///
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (count % _sectorsize != 0)
- {
- long extrastart = Position % _sectorsize;
- if (extrastart != 0)
- {
- _ = Seek(-extrastart, SeekOrigin.Current);
- }
-
- long addedcount = _sectorsize - (count % _sectorsize);
- long ncount = count + addedcount;
- byte[] tmpbuffer = new byte[extrastart + buffer.Length + addedcount];
- buffer.CopyTo(tmpbuffer, extrastart);
- _ = InternalRead(tmpbuffer, offset + (int)extrastart, (int)ncount);
- tmpbuffer.ToList().Skip((int)extrastart).Take(count + offset).ToArray().CopyTo(buffer, 0);
- return count;
- }
-
- return InternalRead(buffer, offset, count);
- }
-
- public override int ReadByte()
- {
- int BytesRead = 0;
- byte[] lpBuffer = new byte[1];
- if (!ReadFile(
- handleValue.DangerousGetHandle(), // handle to file
- lpBuffer, // data buffer
- 1, // number of bytes to read
- ref BytesRead, // number of bytes read
- nint.Zero
- ))
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- ;
- }
-
- _Position += 1;
-
- return lpBuffer[0];
- }
-
- public override void WriteByte(byte Byte)
- {
- int BytesWritten = 0;
- byte[] lpBuffer = [Byte];
- if (!WriteFile(
- handleValue.DangerousGetHandle(), // handle to file
- lpBuffer, // data buffer
- 1, // number of bytes to write
- ref BytesWritten, // number of bytes written
- nint.Zero
- ))
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- ;
- }
-
- _Position += 1;
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- long off = offset;
-
- switch (origin)
- {
- case SeekOrigin.Current:
- off += _Position;
- break;
- case SeekOrigin.End:
- off += _length;
- break;
- }
-
- if (!SetFilePointerEx(handleValue, off, out long ret, 0))
- {
- return _Position;
- }
-
- _Position = ret;
-
- return ret;
- }
-
- public override void SetLength(long value)
- {
- throw new NotImplementedException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- int BytesWritten = 0;
- byte[] BufBytes = new byte[count];
- for (int i = 0; i < count; i++)
- {
- BufBytes[offset + i] = buffer[i];
- }
-
- if (!WriteFile(handleValue.DangerousGetHandle(), BufBytes, count, ref BytesWritten, nint.Zero))
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
-
- _Position += count;
- }
-
- public override void Close()
- {
- uint lpBytesReturned = 0;
- uint result = DeviceIoControl(handleValue, FSCTL_UNLOCK_VOLUME, nint.Zero, 0, nint.Zero, 0, ref lpBytesReturned, nint.Zero);
-
- if (0 == result)
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
-
- handleValue.Close();
- handleValue.Dispose();
- handleValue = null;
- base.Close();
- }
-
- private new void Dispose()
- {
- Dispose(true);
- base.Dispose();
- GC.SuppressFinalize(this);
- }
-
- private new void Dispose(bool disposing)
- {
- // Check to see if Dispose has already been called.
- if (!disposed)
- {
- if (disposing)
- {
- if (handleValue != null)
- {
- uint lpBytesReturned = 0;
- uint result = DeviceIoControl(handleValue, FSCTL_UNLOCK_VOLUME, nint.Zero, 0, nint.Zero, 0, ref lpBytesReturned, nint.Zero);
-
- if (0 == result)
- {
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
- }
-
- handleValue.Close();
- handleValue.Dispose();
- handleValue = null;
- }
- }
- // Note disposing has been done.
- disposed = true;
- }
- }
-
- private static (long, uint) GetDiskProperties(string deviceName)
- {
- DISK_GEOMETRY_EX x = new();
- Execute(ref x, DISK_GET_DRIVE_GEOMETRY_EX, deviceName);
- return (x.DiskSize, x.Geometry.BytesPerSector);
- }
-
- private static void Execute(ref T x, uint dwIoControlCode, string lpFileName, uint dwDesiredAccess = GENERIC_READ, uint dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ, nint lpSecurityAttributes = default, uint dwCreationDisposition = OPEN_EXISTING, uint dwFlagsAndAttributes = 0, nint hTemplateFile = default)
- {
- nint hDevice = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
-
- SafeFileHandle handleValue = new(hDevice, true);
-
- if (handleValue.IsInvalid)
- {
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
-
- int nOutBufferSize = Marshal.SizeOf(typeof(T));
- nint lpOutBuffer = Marshal.AllocHGlobal(nOutBufferSize);
- uint lpBytesReturned = default;
-
- uint result = DeviceIoControl(handleValue, dwIoControlCode, nint.Zero, 0, lpOutBuffer, nOutBufferSize, ref lpBytesReturned, nint.Zero);
-
- if (result == 0)
- {
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
-
- x = (T)Marshal.PtrToStructure(lpOutBuffer, typeof(T));
- Marshal.FreeHGlobal(lpOutBuffer);
-
- handleValue.Close();
- handleValue.Dispose();
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Streams/MEDIA_TYPE.cs b/Img2Ffu.Library/Writer/Streams/MEDIA_TYPE.cs
deleted file mode 100644
index 4cd5852..0000000
--- a/Img2Ffu.Library/Writer/Streams/MEDIA_TYPE.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-Copyright (c) 2018, Proto Beta Test - protobetatest.com - @ProtoBetaTest
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Streams
-{
- public partial class DeviceStream
- {
- private enum MEDIA_TYPE : int
- {
- Unknown = 0,
- F5_1Pt2_512 = 1,
- F3_1Pt44_512 = 2,
- F3_2Pt88_512 = 3,
- F3_20Pt8_512 = 4,
- F3_720_512 = 5,
- F5_360_512 = 6,
- F5_320_512 = 7,
- F5_320_1024 = 8,
- F5_180_512 = 9,
- F5_160_512 = 10,
- RemovableMedia = 11,
- FixedMedia = 12,
- F3_120M_512 = 13,
- F3_640_512 = 14,
- F5_640_512 = 15,
- F5_720_512 = 16,
- F3_1Pt2_512 = 17,
- F3_1Pt23_1024 = 18,
- F5_1Pt23_1024 = 19,
- F3_128Mb_512 = 20,
- F3_230Mb_512 = 21,
- F8_256_128 = 22,
- F3_200Mb_512 = 23,
- F3_240M_512 = 24,
- F3_32M_512 = 25
- }
- }
-}
\ No newline at end of file
diff --git a/Img2Ffu.Library/Writer/Streams/PartialStream.cs b/Img2Ffu.Library/Writer/Streams/PartialStream.cs
deleted file mode 100644
index 9b4140c..0000000
--- a/Img2Ffu.Library/Writer/Streams/PartialStream.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-
-Copyright (c) 2019, Gustave Monce - gus33000.me - @gus33000
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-namespace Img2Ffu.Writer.Streams
-{
- internal class PartialStream : Stream
- {
- private Stream? innerStream;
-
- private bool disposed;
- private readonly long startOffset;
- private readonly long endOffset;
-
- public PartialStream(Stream stream, long StartOffset, long EndOffset)
- {
- _ = stream.Seek(StartOffset, SeekOrigin.Begin);
- startOffset = StartOffset;
- endOffset = EndOffset;
- innerStream = stream;
- }
-
- public override bool CanRead => innerStream.CanRead;
- public override bool CanSeek => innerStream.CanSeek;
- public override bool CanWrite => innerStream.CanWrite;
- public override long Length => endOffset - startOffset;
- public override long Position
- {
- get => innerStream.Position - startOffset; set => innerStream.Position = value + startOffset;
- }
-
- public override void Flush()
- {
- innerStream.Flush();
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- return innerStream.Read(buffer, offset, count);
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- return origin == SeekOrigin.Begin
- ? innerStream.Seek(offset + startOffset, origin)
- : origin == SeekOrigin.End ? innerStream.Seek(endOffset + offset, origin) : innerStream.Seek(offset, origin);
- }
-
- public override void SetLength(long value)
- {
- innerStream.SetLength(value);
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- innerStream.Write(buffer, offset, count);
- }
-
- public override void Close()
- {
- innerStream.Dispose();
- innerStream = null;
- base.Close();
- }
-
- private new void Dispose()
- {
- Dispose(true);
- base.Dispose();
- GC.SuppressFinalize(this);
- }
-
- private new void Dispose(bool disposing)
- {
- // Check to see if Dispose has already been called.
- if (!disposed)
- {
- if (disposing)
- {
- if (innerStream != null)
- {
- innerStream.Dispose();
- innerStream = null;
- }
- }
-
- // Note disposing has been done.
- disposed = true;
- }
- }
- }
-}
\ No newline at end of file