├── FirmwareGen ├── SplittingStrategy.cs ├── VirtualDisks │ ├── OPEN_VIRTUAL_DISK_VERSION.cs │ ├── DETACH_VIRTUAL_DISK_FLAG.cs │ ├── ATTACH_VIRTUAL_DISK_VERSION.cs │ ├── OPEN_VIRTUAL_DISK_PARAMETERS_Version1.cs │ ├── ATTACH_VIRTUAL_DISK_PARAMETERS_Version1.cs │ ├── VIRTUAL_STORAGE_TYPE.cs │ ├── OPEN_VIRTUAL_DISK_FLAG.cs │ ├── OPEN_VIRTUAL_DISK_PARAMETERS.cs │ ├── ATTACH_VIRTUAL_DISK_PARAMETERS.cs │ ├── ATTACH_VIRTUAL_DISK_FLAG.cs │ ├── VIRTUAL_DISK_ACCESS_MASK.cs │ ├── NativeMethods.cs │ ├── BlankVHDUtils.cs │ └── VHDUtils.cs ├── CommandLine │ ├── CLIOptions.cs │ └── GenerateWindowsFFUOptions.cs ├── GPT │ ├── GPTPartition.cs │ ├── GPTHeader.cs │ └── CRC32.cs ├── XmlUtils.cs ├── Program.cs ├── DeviceProfile.cs ├── Extensions │ └── FileInfoExtensions.cs ├── app.manifest ├── DeviceProfiles │ ├── EpsilonHalfSplit128GB.xml │ ├── EpsilonHalfSplit256GB.xml │ ├── EpsilonMaximizedForWindows.xml │ ├── MTP845MaximizedForWindows.xml │ ├── HDK8998MaximizedForWindows.xml │ ├── MTP8998MaximizedForWindows.xml │ ├── ZetaHalfSplit512GB.xml │ ├── ZetaHalfSplit128GB.xml │ ├── ZetaHalfSplit256GB.xml │ ├── ZetaMaximizedForWindows.xml │ ├── MTP8996SGMaximizedForWindows.xml │ ├── HDK8150MaximizedForWindows.xml │ ├── HHG8350MaximizedForWindows.xml │ ├── QRD7325MaximizedForWindows.xml │ ├── QRD8350MaximizedForWindows.xml │ ├── MTP50MaximizedForWindows.xml │ ├── MTP8150MaximizedForWindows.xml │ ├── QRD8150MaximizedForWindows.xml │ ├── MTP8350MaximizedForWindows.xml │ └── MTP8250MaximizedForWindows.xml ├── FirmwareGen.csproj ├── CommonLogic.cs ├── MainLogic.cs ├── Logging.cs └── VolumeUtils.cs ├── GPT2DeviceProfile ├── SplittingStrategy.cs ├── GPT2DeviceProfile.csproj ├── GPT │ └── GPTPartition.cs ├── GptStudio │ ├── GPTHeader.cs │ ├── GPTPartition.cs │ └── GPT.cs ├── DeviceProfile.cs └── Program.cs ├── publish_win_x64.cmd ├── publish_win_x86.cmd ├── publish_win_arm64.cmd ├── GPTFixer ├── GPTFixer.csproj ├── FirmwareGen │ ├── GPT │ │ ├── GPTPartition.cs │ │ ├── GPTHeader.cs │ │ ├── CRC32.cs │ │ └── GPTUtils.cs │ └── CommonLogic.cs ├── Options.cs ├── Img2Ffu │ ├── GPT │ │ ├── Partition.cs │ │ └── GPT.cs │ └── Helpers │ │ └── ByteOperations.cs └── Program.cs ├── PartitionOffsetsHelperTool ├── PartitionOffsetsHelperTool.csproj ├── GPT │ ├── GPTPartition.cs │ ├── GPTHeader.cs │ └── CRC32.cs └── DeviceProfiles │ └── Constants.cs ├── README.md ├── LICENSE ├── .github └── workflows │ └── ci.yml ├── .gitignore └── FirmwareGen.sln /FirmwareGen/SplittingStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen 2 | { 3 | public enum SplittingStrategy 4 | { 5 | HalfSplit, 6 | MaximizedForWindows, 7 | Custom 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/OPEN_VIRTUAL_DISK_VERSION.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum OPEN_VIRTUAL_DISK_VERSION 4 | { 5 | OPEN_VIRTUAL_DISK_VERSION_1 = 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/DETACH_VIRTUAL_DISK_FLAG.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum DETACH_VIRTUAL_DISK_FLAG 4 | { 5 | DETACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /GPT2DeviceProfile/SplittingStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen 2 | { 3 | public enum SplittingStrategy 4 | { 5 | HalfSplit, 6 | MaximizedForWindows, 7 | Custom 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /publish_win_x64.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | msbuild /m /t:restore,firmwaregen:publish /p:Platform=x64 /p:RuntimeIdentifier=win-x64 /p:PublishDir="%CD%\publish\artifacts\win-x64\CLI" /p:PublishSingleFile=true /p:PublishTrimmed=false /p:Configuration=Release FirmwareGen.sln -------------------------------------------------------------------------------- /publish_win_x86.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | msbuild /m /t:restore,firmwaregen:publish /p:Platform=x86 /p:RuntimeIdentifier=win-x86 /p:PublishDir="%CD%\publish\artifacts\win-x86\CLI" /p:PublishSingleFile=true /p:PublishTrimmed=false /p:Configuration=Release FirmwareGen.sln -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/ATTACH_VIRTUAL_DISK_VERSION.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum ATTACH_VIRTUAL_DISK_VERSION 4 | { 5 | ATTACH_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0, 6 | ATTACH_VIRTUAL_DISK_VERSION_1 = 1 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /publish_win_arm64.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | msbuild /m /t:restore,firmwaregen:publish /p:Platform=arm64 /p:RuntimeIdentifier=win-arm64 /p:PublishDir="%CD%\publish\artifacts\win-arm64\CLI" /p:PublishSingleFile=true /p:PublishTrimmed=false /p:Configuration=Release FirmwareGen.sln -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/OPEN_VIRTUAL_DISK_PARAMETERS_Version1.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace FirmwareGen.VirtualDisks 4 | { 5 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 6 | public struct OPEN_VIRTUAL_DISK_PARAMETERS_Version1 7 | { 8 | public int RWDepth; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/ATTACH_VIRTUAL_DISK_PARAMETERS_Version1.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace FirmwareGen.VirtualDisks 4 | { 5 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 6 | public struct ATTACH_VIRTUAL_DISK_PARAMETERS_Version1 7 | { 8 | public int Reserved; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/VIRTUAL_STORAGE_TYPE.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace FirmwareGen.VirtualDisks 5 | { 6 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 7 | public struct VIRTUAL_STORAGE_TYPE 8 | { 9 | public int DeviceId; 10 | public Guid VendorId; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/OPEN_VIRTUAL_DISK_FLAG.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum OPEN_VIRTUAL_DISK_FLAG 4 | { 5 | OPEN_VIRTUAL_DISK_FLAG_NONE = 0x00000000, 6 | OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 0x00000001, 7 | OPEN_VIRTUAL_DISK_FLAG_BLANK_FILE = 0x00000002, 8 | OPEN_VIRTUAL_DISK_FLAG_BOOT_DRIVE = 0x00000004 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/OPEN_VIRTUAL_DISK_PARAMETERS.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace FirmwareGen.VirtualDisks 4 | { 5 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 6 | public struct OPEN_VIRTUAL_DISK_PARAMETERS 7 | { 8 | public OPEN_VIRTUAL_DISK_VERSION Version; 9 | public OPEN_VIRTUAL_DISK_PARAMETERS_Version1 Version1; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/ATTACH_VIRTUAL_DISK_PARAMETERS.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace FirmwareGen.VirtualDisks 4 | { 5 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 6 | public struct ATTACH_VIRTUAL_DISK_PARAMETERS 7 | { 8 | public ATTACH_VIRTUAL_DISK_VERSION Version; 9 | public ATTACH_VIRTUAL_DISK_PARAMETERS_Version1 Version1; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/ATTACH_VIRTUAL_DISK_FLAG.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum ATTACH_VIRTUAL_DISK_FLAG 4 | { 5 | ATTACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000, 6 | ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 0x00000001, 7 | ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 0x00000002, 8 | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME = 0x00000004, 9 | ATTACH_VIRTUAL_DISK_FLAG_NO_LOCAL_HOST = 0x00000008 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FirmwareGen/CommandLine/CLIOptions.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | 3 | namespace FirmwareGen.CommandLine 4 | { 5 | public static class CLIOptions 6 | { 7 | public static void ParseOptionsAndTakeAction(string[] args) 8 | { 9 | if (!MainLogic.VerifyAllComponentsArePresent()) 10 | { 11 | return; 12 | } 13 | 14 | _ = Parser.Default.ParseArguments(args).WithParsed(MainLogic.GenerateWindowsFFU); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /GPTFixer/GPTFixer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net8.0 5 | ARM32;ARM64;x86;x64 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/VIRTUAL_DISK_ACCESS_MASK.cs: -------------------------------------------------------------------------------- 1 | namespace FirmwareGen.VirtualDisks 2 | { 3 | public enum VIRTUAL_DISK_ACCESS_MASK 4 | { 5 | VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x00010000, 6 | VIRTUAL_DISK_ACCESS_ATTACH_RW = 0x00020000, 7 | VIRTUAL_DISK_ACCESS_DETACH = 0x00040000, 8 | VIRTUAL_DISK_ACCESS_GET_INFO = 0x00080000, 9 | VIRTUAL_DISK_ACCESS_READ = 0x000d0000, 10 | VIRTUAL_DISK_ACCESS_CREATE = 0x00100000, 11 | VIRTUAL_DISK_ACCESS_METAOPS = 0x00200000, 12 | VIRTUAL_DISK_ACCESS_WRITABLE = 0x00320000, 13 | VIRTUAL_DISK_ACCESS_ALL = 0x003f0000 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GPT2DeviceProfile/GPT2DeviceProfile.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0-windows 4 | Exe 5 | win-x86;win-x64;win-arm64 6 | $(SolutionDir)build\$(Platform)\$(Configuration)\GPT2DeviceProfile\ 7 | $(SolutionDir)intermediate\$(Platform)\$(Configuration)\GPT2DeviceProfile\ 8 | MinimumRecommendedRules.ruleset 9 | AnyCPU;x64;x86;ARM64 10 | 11 | -------------------------------------------------------------------------------- /PartitionOffsetsHelperTool/PartitionOffsetsHelperTool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0-windows 5 | Exe 6 | win-x86;win-x64;win-arm64 7 | $(SolutionDir)build\$(Platform)\$(Configuration)\PartitionOffsetsHelperTool\ 8 | $(SolutionDir)intermediate\$(Platform)\$(Configuration)\PartitionOffsetsHelperTool\ 9 | MinimumRecommendedRules.ruleset 10 | AnyCPU;x64;x86;ARM64 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /FirmwareGen/GPT/GPTPartition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FirmwareGen.GPT 4 | { 5 | public class GPTPartition 6 | { 7 | public Guid TypeGUID 8 | { 9 | get; set; 10 | } 11 | 12 | public Guid UID 13 | { 14 | get; set; 15 | } 16 | 17 | public ulong FirstLBA 18 | { 19 | get; set; 20 | } 21 | 22 | public ulong LastLBA 23 | { 24 | get; set; 25 | } 26 | 27 | public ulong Attributes 28 | { 29 | get; set; 30 | } 31 | 32 | public string Name 33 | { 34 | get; set; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /GPT2DeviceProfile/GPT/GPTPartition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FirmwareGen.GPT 4 | { 5 | public class GPTPartition 6 | { 7 | public Guid TypeGUID 8 | { 9 | get; set; 10 | } 11 | 12 | public Guid UID 13 | { 14 | get; set; 15 | } 16 | 17 | public ulong FirstLBA 18 | { 19 | get; set; 20 | } 21 | 22 | public ulong LastLBA 23 | { 24 | get; set; 25 | } 26 | 27 | public ulong Attributes 28 | { 29 | get; set; 30 | } 31 | 32 | public string Name 33 | { 34 | get; set; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /GPTFixer/FirmwareGen/GPT/GPTPartition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GPTFixer.FirmwareGen.GPT 4 | { 5 | public class GPTPartition 6 | { 7 | public Guid TypeGUID 8 | { 9 | get; set; 10 | } 11 | 12 | public Guid UID 13 | { 14 | get; set; 15 | } 16 | 17 | public ulong FirstLBA 18 | { 19 | get; set; 20 | } 21 | 22 | public ulong LastLBA 23 | { 24 | get; set; 25 | } 26 | 27 | public ulong Attributes 28 | { 29 | get; set; 30 | } 31 | 32 | public string Name 33 | { 34 | get; set; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /PartitionOffsetsHelperTool/GPT/GPTPartition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PartitionOffsetsHelperTool.GPT 4 | { 5 | public class GPTPartition 6 | { 7 | public Guid TypeGUID 8 | { 9 | get; set; 10 | } 11 | 12 | public Guid UID 13 | { 14 | get; set; 15 | } 16 | 17 | public ulong FirstLBA 18 | { 19 | get; set; 20 | } 21 | 22 | public ulong LastLBA 23 | { 24 | get; set; 25 | } 26 | 27 | public ulong Attributes 28 | { 29 | get; set; 30 | } 31 | 32 | public required string Name 33 | { 34 | get; set; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /GPT2DeviceProfile/GptStudio/GPTHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace GptStudio 5 | { 6 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 7 | public struct GPTHeader 8 | { 9 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 10 | public char[] Signature; 11 | public uint Revision; 12 | public uint Size; 13 | public uint CRC32; 14 | public uint Reserved; 15 | public ulong CurrentLBA; 16 | public ulong BackupLBA; 17 | public ulong FirstUsableLBA; 18 | public ulong LastUsableLBA; 19 | public Guid DiskGUID; 20 | public ulong PartitionArrayLBA; 21 | public uint PartitionEntryCount; 22 | public uint PartitionEntrySize; 23 | public uint PartitionArrayCRC32; 24 | } 25 | } -------------------------------------------------------------------------------- /FirmwareGen/XmlUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Xml; 3 | using System.Xml.Serialization; 4 | 5 | namespace FirmwareGen 6 | { 7 | public static class XmlUtils 8 | { 9 | public static void Serialize(this T type, string path) where T : class 10 | { 11 | XmlSerializer serializer = new(type.GetType()); 12 | using FileStream writer = new(path, FileMode.Create); 13 | serializer.Serialize(writer, type); 14 | } 15 | 16 | public static T Deserialize(string path) where T : class 17 | { 18 | T type; 19 | XmlSerializer serializer = new(typeof(T)); 20 | using (XmlReader reader = XmlReader.Create(path)) 21 | { 22 | type = serializer.Deserialize(reader) as T; 23 | } 24 | return type; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /GPT2DeviceProfile/GptStudio/GPTPartition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace GptStudio 5 | { 6 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)] 7 | public struct GPTPartition 8 | { 9 | public readonly void CloneTo(GPTPartition target) 10 | { 11 | target.TypeGUID = TypeGUID; 12 | target.UID = UID; 13 | target.FirstLBA = FirstLBA; 14 | target.LastLBA = LastLBA; 15 | target.Attributes = Attributes; 16 | target.Name = Name; 17 | } 18 | 19 | public Guid TypeGUID; 20 | public Guid UID; 21 | public ulong FirstLBA; 22 | public ulong LastLBA; 23 | public ulong Attributes; 24 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 36)] 25 | public char[] Name; 26 | } 27 | } -------------------------------------------------------------------------------- /FirmwareGen/Program.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.CommandLine; 2 | using System; 3 | 4 | namespace FirmwareGen 5 | { 6 | internal static class Program 7 | { 8 | private static void Main(string[] args) 9 | { 10 | Logging.Log("FirmwareGen"); 11 | Logging.Log("Copyright (c) 2019-2024, Gustave Monce - gus33000.me - @gus33000"); 12 | Logging.Log("Released under the MIT license at github.com/WOA-Project/FirmwareGen"); 13 | Logging.Log(""); 14 | 15 | try 16 | { 17 | CLIOptions.ParseOptionsAndTakeAction(args); 18 | } 19 | catch (Exception ex) 20 | { 21 | Logging.Log("Something happened.", Logging.LoggingLevel.Error); 22 | Logging.Log(ex.Message, Logging.LoggingLevel.Error); 23 | Logging.Log(ex.StackTrace, Logging.LoggingLevel.Error); 24 | Environment.Exit(1); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FirmwareGen 2 | 3 | FirmwareGen (or Firmware Generator) is a tool designed to fully automate and assist in building fully fledged ready to go Full Flash Update (FFU) images for devices supported as part of the WOA-Project organisation. 4 | 5 | Namely, the FirmwareGen tool is designed to setup prep and create FFU files containing Windows Desktop for ARM64 Processors for specific phone based devices: 6 | 7 | - Lumia 950 8 | - Lumia 950 XL 9 | - RX-130 EB0.5, EB1.0, EB2.0, EB2.1, EB2.2 and EB2.3 10 | - Surface Duo (1st Gen) 128GB, 256GB 11 | - Surface Duo 2 128GB, 256GB, 512GB 12 | - Various Qualcomm Reference Platforms 13 | 14 | This tool is not specifically hardcoded to target those exact devices and can be easily extended without forking it or even modifying it by simply authoring device profile xml files. 15 | 16 | In a nut shell the tool is going to: 17 | 18 | - Generate a Virtual Hard Disk matching the specifications of the device profile 19 | - Generate the target's wanted GUID Partition Table on said Virtual Disk 20 | - Apply a Windows Desktop Operating System Image from a provided installation media 21 | - Configure the ESP 22 | - Install Drivers 23 | - Package it all up as a FFU file ready to flash on the given device -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Gustave Monce 4 | Copyright (c) 2019-2024 The LumiaWoA authors 5 | Copyright (c) 2019-2024 The DuoWoA authors 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfile.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.GPT; 2 | using System; 3 | 4 | namespace FirmwareGen 5 | { 6 | public class DeviceProfile 7 | { 8 | public virtual string[] SupplementaryBCDCommands 9 | { 10 | get; set; 11 | } 12 | public virtual string[] PlatformIDs 13 | { 14 | get; set; 15 | } 16 | public virtual string FFUFileName 17 | { 18 | get; set; 19 | } 20 | public virtual string DriverDefinitionPath 21 | { 22 | get; set; 23 | } 24 | public virtual ulong DiskTotalSize 25 | { 26 | get; set; 27 | } 28 | public virtual uint DiskSectorSize 29 | { 30 | get; set; 31 | } 32 | public virtual GPTPartition[] PartitionLayout 33 | { 34 | get; set; 35 | } 36 | public virtual SplittingStrategy SplittingStrategy 37 | { 38 | get; set; 39 | } 40 | public virtual ulong CustomSplittingAndroidDesiredSpace 41 | { 42 | get; set; 43 | } 44 | public virtual Guid DiskGuid 45 | { 46 | get; set; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /GPT2DeviceProfile/DeviceProfile.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.GPT; 2 | using System; 3 | 4 | namespace FirmwareGen 5 | { 6 | public class DeviceProfile 7 | { 8 | public virtual string[] SupplementaryBCDCommands 9 | { 10 | get; set; 11 | } 12 | public virtual string[] PlatformIDs 13 | { 14 | get; set; 15 | } 16 | public virtual string FFUFileName 17 | { 18 | get; set; 19 | } 20 | public virtual string DriverDefinitionPath 21 | { 22 | get; set; 23 | } 24 | public virtual ulong DiskTotalSize 25 | { 26 | get; set; 27 | } 28 | public virtual uint DiskSectorSize 29 | { 30 | get; set; 31 | } 32 | public virtual GPTPartition[] PartitionLayout 33 | { 34 | get; set; 35 | } 36 | public virtual SplittingStrategy SplittingStrategy 37 | { 38 | get; set; 39 | } 40 | public virtual ulong CustomSplittingAndroidDesiredSpace 41 | { 42 | get; set; 43 | } 44 | public virtual Guid DiskGuid 45 | { 46 | get; set; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /FirmwareGen/Extensions/FileInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | 5 | namespace FirmwareGen.Extensions 6 | { 7 | public static class FileInfoExtensions 8 | { 9 | public static void CopyTo(this FileInfo file, FileInfo destination, Action progressCallback) 10 | { 11 | const int bufferSize = 1024 * 1024; 12 | byte[] buffer = new byte[bufferSize], buffer2 = new byte[bufferSize]; 13 | bool swap = false; 14 | int reportedProgress = 0; 15 | long len = file.Length; 16 | float flen = len; 17 | Task writer = null; 18 | 19 | using FileStream source = file.OpenRead(); 20 | using FileStream dest = destination.OpenWrite(); 21 | dest.SetLength(source.Length); 22 | int read; 23 | for (long size = 0; size < len; size += read) 24 | { 25 | int progress; 26 | if ((progress = (int)(size / flen * 100)) != reportedProgress) 27 | { 28 | progressCallback(reportedProgress = progress); 29 | } 30 | 31 | read = source.Read(swap ? buffer : buffer2, 0, bufferSize); 32 | writer?.Wait(); 33 | writer = dest.WriteAsync(swap ? buffer : buffer2, 0, read); 34 | swap = !swap; 35 | } 36 | writer?.Wait(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /FirmwareGen/GPT/GPTHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FirmwareGen.GPT 4 | { 5 | public class GPTHeader 6 | { 7 | public string Signature 8 | { 9 | get; set; 10 | } 11 | 12 | public uint Revision 13 | { 14 | get; set; 15 | } 16 | 17 | public uint Size 18 | { 19 | get; set; 20 | } 21 | 22 | public uint CRC32 23 | { 24 | get; set; 25 | } 26 | 27 | public uint Reserved 28 | { 29 | get; set; 30 | } 31 | 32 | public ulong CurrentLBA 33 | { 34 | get; set; 35 | } 36 | 37 | public ulong BackupLBA 38 | { 39 | get; set; 40 | } 41 | 42 | public ulong FirstUsableLBA 43 | { 44 | get; set; 45 | } 46 | 47 | public ulong LastUsableLBA 48 | { 49 | get; set; 50 | } 51 | 52 | public Guid DiskGUID 53 | { 54 | get; set; 55 | } 56 | 57 | public ulong PartitionArrayLBA 58 | { 59 | get; set; 60 | } 61 | 62 | public uint PartitionEntryCount 63 | { 64 | get; set; 65 | } 66 | 67 | public uint PartitionEntrySize 68 | { 69 | get; set; 70 | } 71 | 72 | public uint PartitionArrayCRC32 73 | { 74 | get; set; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /GPTFixer/FirmwareGen/GPT/GPTHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GPTFixer.FirmwareGen.GPT 4 | { 5 | public class GPTHeader 6 | { 7 | public string Signature 8 | { 9 | get; set; 10 | } 11 | 12 | public uint Revision 13 | { 14 | get; set; 15 | } 16 | 17 | public uint Size 18 | { 19 | get; set; 20 | } 21 | 22 | public uint CRC32 23 | { 24 | get; set; 25 | } 26 | 27 | public uint Reserved 28 | { 29 | get; set; 30 | } 31 | 32 | public ulong CurrentLBA 33 | { 34 | get; set; 35 | } 36 | 37 | public ulong BackupLBA 38 | { 39 | get; set; 40 | } 41 | 42 | public ulong FirstUsableLBA 43 | { 44 | get; set; 45 | } 46 | 47 | public ulong LastUsableLBA 48 | { 49 | get; set; 50 | } 51 | 52 | public Guid DiskGUID 53 | { 54 | get; set; 55 | } 56 | 57 | public ulong PartitionArrayLBA 58 | { 59 | get; set; 60 | } 61 | 62 | public uint PartitionEntryCount 63 | { 64 | get; set; 65 | } 66 | 67 | public uint PartitionEntrySize 68 | { 69 | get; set; 70 | } 71 | 72 | public uint PartitionArrayCRC32 73 | { 74 | get; set; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /PartitionOffsetsHelperTool/GPT/GPTHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PartitionOffsetsHelperTool.GPT 4 | { 5 | public class GPTHeader 6 | { 7 | public string Signature 8 | { 9 | get; set; 10 | } 11 | 12 | public uint Revision 13 | { 14 | get; set; 15 | } 16 | 17 | public uint Size 18 | { 19 | get; set; 20 | } 21 | 22 | public uint CRC32 23 | { 24 | get; set; 25 | } 26 | 27 | public uint Reserved 28 | { 29 | get; set; 30 | } 31 | 32 | public ulong CurrentLBA 33 | { 34 | get; set; 35 | } 36 | 37 | public ulong BackupLBA 38 | { 39 | get; set; 40 | } 41 | 42 | public ulong FirstUsableLBA 43 | { 44 | get; set; 45 | } 46 | 47 | public ulong LastUsableLBA 48 | { 49 | get; set; 50 | } 51 | 52 | public Guid DiskGUID 53 | { 54 | get; set; 55 | } 56 | 57 | public ulong PartitionArrayLBA 58 | { 59 | get; set; 60 | } 61 | 62 | public uint PartitionEntryCount 63 | { 64 | get; set; 65 | } 66 | 67 | public uint PartitionEntrySize 68 | { 69 | get; set; 70 | } 71 | 72 | public uint PartitionArrayCRC32 73 | { 74 | get; set; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /GPTFixer/FirmwareGen/CommonLogic.cs: -------------------------------------------------------------------------------- 1 | using GPTFixer.FirmwareGen.GPT; 2 | using System; 3 | 4 | namespace GPTFixer.FirmwareGen 5 | { 6 | internal static class CommonLogic 7 | { 8 | public static byte[] GetPrimaryGPT(ulong DiskTotalSize, uint DiskSectorSize, Guid DiskGuid, GPTPartition[] PartitionLayout) 9 | { 10 | ulong DiskSize = DiskTotalSize; 11 | uint SectorSize = DiskSectorSize; 12 | 13 | byte[] PrimaryMBR = new byte[SectorSize]; 14 | PrimaryMBR[0x1C0] = 0x01; 15 | PrimaryMBR[0x1C2] = 0xEE; 16 | PrimaryMBR[0x1C3] = 0xFF; 17 | PrimaryMBR[0x1C4] = 0xFF; 18 | PrimaryMBR[0x1C5] = 0xFF; 19 | PrimaryMBR[0x1C6] = 0x01; 20 | PrimaryMBR[0x1CA] = 0xFF; 21 | PrimaryMBR[0x1CB] = 0xFF; 22 | PrimaryMBR[0x1CC] = 0xFF; 23 | PrimaryMBR[0x1CD] = 0xFF; 24 | PrimaryMBR[0x1FE] = 0x55; 25 | PrimaryMBR[0x1FF] = 0xAA; 26 | 27 | return [ 28 | .. PrimaryMBR, 29 | .. GPTUtils.MakeGPT(DiskSize, SectorSize, PartitionLayout, DiskGuid, IsBackupGPT: false) 30 | ]; 31 | } 32 | 33 | public static byte[] GetBackupGPT(ulong DiskTotalSize, uint DiskSectorSize, Guid DiskGuid, GPTPartition[] PartitionLayout) 34 | { 35 | ulong DiskSize = DiskTotalSize; 36 | uint SectorSize = DiskSectorSize; 37 | 38 | return GPTUtils.MakeGPT(DiskSize, SectorSize, PartitionLayout, DiskGuid, IsBackupGPT: true); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GPTFixer/Options.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Gustave Monce and Contributors 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | using CommandLine; 23 | 24 | namespace GPTFixer 25 | { 26 | internal class Options 27 | { 28 | [Option('i', "img-file", HelpText = @"A path to the img file to convert *OR* a PhysicalDisk path. i.e. \\.\PhysicalDrive1", Required = true)] 29 | public required string InputFile 30 | { 31 | get; set; 32 | } 33 | 34 | [Option('s', "sector-size", HelpText = "Sector size to use for the FFU file", Default = 0x200u, Required = false)] 35 | public uint SectorSize 36 | { 37 | get; set; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /FirmwareGen/CommandLine/GenerateWindowsFFUOptions.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | 3 | namespace FirmwareGen.CommandLine 4 | { 5 | [Verb("generate-windows-ffu", HelpText = "Generates a ffu from a Windows Base VHDX")] 6 | public class GenerateWindowsFFUOptions 7 | { 8 | [Option('d', "driver-pack", HelpText = "Driver pack with device.xml", Required = true)] 9 | public string DriverPack 10 | { 11 | get; set; 12 | } 13 | 14 | [Option('o', "output", HelpText = "Output folder", Required = true)] 15 | public string Output 16 | { 17 | get; set; 18 | } 19 | 20 | [Option('v', "windows-ver", HelpText = "Version of Windows e.g. 10.0.26063.1", Required = true)] 21 | public string WindowsVer 22 | { 23 | get; set; 24 | } 25 | 26 | [Option('w', "windows-dvd", HelpText = "Windows Setup Media DVD drive letter e.g. F:", Required = true)] 27 | public string WindowsDVD 28 | { 29 | get; set; 30 | } 31 | 32 | [Option('i', "windows-index", HelpText = "The index of the Windows Setup Media DVD Install Image, to apply. e.g. 1", Required = true)] 33 | public string WindowsIndex 34 | { 35 | get; set; 36 | } 37 | 38 | [Option('p', "device-profile", HelpText = "Path to the device profile xml containing information on how to build the FFU", Required = true)] 39 | public string DeviceProfile 40 | { 41 | get; set; 42 | } 43 | 44 | [Option('t', "secure-boot-signing-command", HelpText = "Optional command to sign the resulting FFU file to work in Secure Boot scenarios. The File to sign is passed as a path appended after the provided command string, and is the sole and only argument provided.", Default = "", Required = false)] 45 | public required string SecureBootSigningCommand 46 | { 47 | get; set; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace FirmwareGen.VirtualDisks 6 | { 7 | internal static class NativeMethods 8 | { 9 | public const int ERROR_SUCCESS = 0; 10 | public const int OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT = 1; 11 | public const int VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN = 0; 12 | public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2; 13 | public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3; 14 | 15 | public static readonly Guid VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = new("EC984AEC-A0F9-47e9-901F-71415A66345B"); 16 | public static readonly Guid VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN = new("00000000-0000-0000-0000-000000000000"); 17 | 18 | [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] 19 | public static extern int AttachVirtualDisk(nint VirtualDiskHandle, nint SecurityDescriptor, ATTACH_VIRTUAL_DISK_FLAG Flags, int ProviderSpecificFlags, ref ATTACH_VIRTUAL_DISK_PARAMETERS Parameters, nint Overlapped); 20 | 21 | [DllImport("kernel32.dll", SetLastError = true)] 22 | [return: MarshalAs(UnmanagedType.Bool)] 23 | public static extern bool CloseHandle(nint hObject); 24 | 25 | [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] 26 | public static extern int OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE VirtualStorageType, string Path, VIRTUAL_DISK_ACCESS_MASK VirtualDiskAccessMask, OPEN_VIRTUAL_DISK_FLAG Flags, ref OPEN_VIRTUAL_DISK_PARAMETERS Parameters, ref nint Handle); 27 | 28 | [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] 29 | public static extern int GetVirtualDiskPhysicalPath(nint VirtualDiskHandle, ref int DiskPathSizeInBytes, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder DiskPath); 30 | 31 | [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] 32 | public static extern int DetachVirtualDisk(nint virtualDiskHandle, DETACH_VIRTUAL_DISK_FLAG flags, int providerSpecificFlags); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /FirmwareGen/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | true 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | runs-on: windows-latest 13 | strategy: 14 | matrix: 15 | target: [win-x86,win-x64,win-arm64] 16 | include: 17 | - target: win-x86 18 | platform: win 19 | architecture: x86 20 | - target: win-x64 21 | platform: win 22 | architecture: x64 23 | - target: win-arm64 24 | platform: win 25 | architecture: arm64 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4.1.1 29 | 30 | - name: Install .NET SDK 31 | uses: actions/setup-dotnet@v4.0.0 32 | with: 33 | dotnet-version: "8.0.x" 34 | 35 | - name: Add MSBuild to PATH 36 | uses: microsoft/setup-msbuild@v1.3.1 37 | 38 | - name: Build CLI utilities 39 | shell: pwsh 40 | run: | 41 | msbuild /m /t:restore,firmwaregen:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}/CLIs /p:PublishSingleFile=true /p:PublishTrimmed=false /p:Configuration=Release FirmwareGen.sln 42 | 43 | - name: Create PDB Output Directory 44 | shell: pwsh 45 | run: | 46 | mkdir ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}\PDBs 47 | 48 | - name: Move PDBs 49 | shell: pwsh 50 | run: | 51 | move ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}\CLIs\*.pdb ${{ github.workspace }}\artifacts\${{ matrix.platform }}-${{ matrix.architecture }}\PDBs\ 52 | 53 | - name: Upload artifact (Binaries) 54 | uses: actions/upload-artifact@v4.0.0 55 | with: 56 | name: ${{ matrix.platform }}-${{ matrix.architecture }}-binaries 57 | path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}\CLIs 58 | 59 | - name: Upload artifact (Symbols) 60 | uses: actions/upload-artifact@v4.0.0 61 | with: 62 | name: ${{ matrix.platform }}-${{ matrix.architecture }}-symbols 63 | path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}\PDBs 64 | -------------------------------------------------------------------------------- /GPT2DeviceProfile/Program.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Xml.Serialization; 6 | 7 | namespace GPT2DeviceProfile 8 | { 9 | internal class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | DeviceProfile deviceProfile = GenerateDeviceProfile(args[0], 4096); 14 | 15 | XmlSerializer serializer = new(typeof(DeviceProfile)); 16 | 17 | using StringWriter writer = new(); 18 | serializer.Serialize(writer, deviceProfile); 19 | string xml = writer.ToString(); 20 | 21 | Console.WriteLine(xml); 22 | } 23 | 24 | private static DeviceProfile GenerateDeviceProfile(string GPTBin, uint SectorSize) 25 | { 26 | byte[] Buffer = File.ReadAllBytes(GPTBin); 27 | using Stream stream = new MemoryStream(Buffer); 28 | 29 | GptStudio.GPT GPT = GptStudio.GPT.ReadFromStream(stream, (int)SectorSize)!; 30 | 31 | List deviceProfilePartitions = []; 32 | foreach (GptStudio.GPTPartition partition in GPT.Partitions) 33 | { 34 | FirmwareGen.GPT.GPTPartition part = new() 35 | { 36 | UID = partition.UID, 37 | TypeGUID = partition.TypeGUID, 38 | FirstLBA = partition.FirstLBA, 39 | LastLBA = partition.LastLBA, 40 | Name = new string(partition.Name).Trim('\0'), 41 | Attributes = partition.Attributes 42 | }; 43 | deviceProfilePartitions.Add(part); 44 | } 45 | 46 | DeviceProfile deviceProfile = new() 47 | { 48 | DiskGuid = GPT.Header.DiskGUID, 49 | DiskTotalSize = (GPT.Header.LastUsableLBA + 1) * SectorSize, 50 | DiskSectorSize = SectorSize, 51 | SupplementaryBCDCommands = [], 52 | SplittingStrategy = SplittingStrategy.MaximizedForWindows, 53 | CustomSplittingAndroidDesiredSpace = 4294967296, 54 | PartitionLayout = [.. deviceProfilePartitions], 55 | PlatformIDs = ["Qualcomm.SM_PLACEHOLDER.PLACEHOLDER.*"], 56 | FFUFileName = "PLACEHOLDER_MaximizedForWindows.ffu", 57 | DriverDefinitionPath = "\\definitions\\Desktop\\ARM64\\Internal\\PLACEHOLDER.xml" 58 | }; 59 | 60 | return deviceProfile; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/EpsilonHalfSplit128GB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo.1930 6 | OEMB1.*.OEMB1 Product.* 7 | OEMEP.*.OEMEP Product.* 8 | 9 | OEMEP_128GB_HalfSplit.ffu 10 | \definitions\Desktop\ARM64\Internal\epsilon.xml 11 | 111723675648 12 | 4096 13 | 14 | 15 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 16 | 3e20174c-e289-a56a-39e7-2740b0043d24 17 | 6 18 | 7 19 | 0 20 | ssd 21 | 22 | 23 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 24 | 3c077ac9-fe70-fb01-9fda-3e03153145ea 25 | 8 26 | 8199 27 | 0 28 | persist 29 | 30 | 31 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 32 | b7f39878-935d-ed4b-ead8-48b159a31e04 33 | 8200 34 | 12295 35 | 0 36 | metadata 37 | 38 | 39 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 40 | 04489c96-ae78-c997-efbf-1bc9909cd1ca 41 | 12296 42 | 12423 43 | 0 44 | frp 45 | 46 | 47 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 48 | b2ebcd63-842b-f5ff-bdf6-f630f7148b1f 49 | 12424 50 | 12679 51 | 0 52 | misc 53 | 54 | 55 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 56 | e24f3f91-ed89-c235-d6b4-afada6edb8b7 57 | 12680 58 | 12679 59 | 0 60 | userdata 61 | 62 | 63 | HalfSplit 64 | 4294967296 65 | efa6243a-085f-e745-f2ce-54d39ef34351 66 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/EpsilonHalfSplit256GB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo.1930 6 | OEMB1.*.OEMB1 Product.* 7 | OEMEP.*.OEMEP Product.* 8 | 9 | OEMEP_256GB_HalfSplit.ffu 10 | \definitions\Desktop\ARM64\Internal\epsilon.xml 11 | 239651758080 12 | 4096 13 | 14 | 15 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 16 | 3e20174c-e289-a56a-39e7-2740b0043d24 17 | 6 18 | 7 19 | 0 20 | ssd 21 | 22 | 23 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 24 | 3c077ac9-fe70-fb01-9fda-3e03153145ea 25 | 8 26 | 8199 27 | 0 28 | persist 29 | 30 | 31 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 32 | b7f39878-935d-ed4b-ead8-48b159a31e04 33 | 8200 34 | 12295 35 | 0 36 | metadata 37 | 38 | 39 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 40 | 04489c96-ae78-c997-efbf-1bc9909cd1ca 41 | 12296 42 | 12423 43 | 0 44 | frp 45 | 46 | 47 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 48 | b2ebcd63-842b-f5ff-bdf6-f630f7148b1f 49 | 12424 50 | 12679 51 | 0 52 | misc 53 | 54 | 55 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 56 | e24f3f91-ed89-c235-d6b4-afada6edb8b7 57 | 12680 58 | 12679 59 | 0 60 | userdata 61 | 62 | 63 | HalfSplit 64 | 4294967296 65 | efa6243a-085f-e745-f2ce-54d39ef34351 66 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/EpsilonMaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo.1930 6 | OEMB1.*.OEMB1 Product.* 7 | OEMEP.*.OEMEP Product.* 8 | 9 | OEMEP_MaximizedForWindows.ffu 10 | \definitions\Desktop\ARM64\Internal\epsilon.xml 11 | 111723675648 12 | 4096 13 | 14 | 15 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 16 | 3e20174c-e289-a56a-39e7-2740b0043d24 17 | 6 18 | 7 19 | 0 20 | ssd 21 | 22 | 23 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 24 | 3c077ac9-fe70-fb01-9fda-3e03153145ea 25 | 8 26 | 8199 27 | 0 28 | persist 29 | 30 | 31 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 32 | b7f39878-935d-ed4b-ead8-48b159a31e04 33 | 8200 34 | 12295 35 | 0 36 | metadata 37 | 38 | 39 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 40 | 04489c96-ae78-c997-efbf-1bc9909cd1ca 41 | 12296 42 | 12423 43 | 0 44 | frp 45 | 46 | 47 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 48 | b2ebcd63-842b-f5ff-bdf6-f630f7148b1f 49 | 12424 50 | 12679 51 | 0 52 | misc 53 | 54 | 55 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 56 | e24f3f91-ed89-c235-d6b4-afada6edb8b7 57 | 12680 58 | 12679 59 | 0 60 | userdata 61 | 62 | 63 | MaximizedForWindows 64 | 4294967296 65 | efa6243a-085f-e745-f2ce-54d39ef34351 66 | 67 | -------------------------------------------------------------------------------- /FirmwareGen/FirmwareGen.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0-windows 4 | Exe 5 | win-x86;win-x64;win-arm64 6 | $(SolutionDir)build\$(Platform)\$(Configuration)\FirmwareGen\ 7 | $(SolutionDir)intermediate\$(Platform)\$(Configuration)\FirmwareGen\ 8 | MinimumRecommendedRules.ruleset 9 | AnyCPU;x64;x86;ARM64 10 | app.manifest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Always 25 | 26 | 27 | Always 28 | 29 | 30 | Always 31 | 32 | 33 | Always 34 | 35 | 36 | Always 37 | 38 | 39 | Always 40 | 41 | 42 | Always 43 | 44 | 45 | Always 46 | 47 | 48 | Always 49 | 50 | 51 | Always 52 | 53 | 54 | Always 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /FirmwareGen/CommonLogic.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.GPT; 2 | using FirmwareGen.VirtualDisks; 3 | using System.IO; 4 | 5 | namespace FirmwareGen 6 | { 7 | internal class CommonLogic 8 | { 9 | public static byte[] GetPrimaryGPT(DeviceProfile deviceProfile) 10 | { 11 | ulong DiskSize = deviceProfile.DiskTotalSize; 12 | uint SectorSize = deviceProfile.DiskSectorSize; 13 | 14 | byte[] PrimaryMBR = new byte[SectorSize]; 15 | PrimaryMBR[0x1C0] = 0x01; 16 | PrimaryMBR[0x1C2] = 0xEE; 17 | PrimaryMBR[0x1C3] = 0xFF; 18 | PrimaryMBR[0x1C4] = 0xFF; 19 | PrimaryMBR[0x1C5] = 0xFF; 20 | PrimaryMBR[0x1C6] = 0x01; 21 | PrimaryMBR[0x1CA] = 0xFF; 22 | PrimaryMBR[0x1CB] = 0xFF; 23 | PrimaryMBR[0x1CC] = 0xFF; 24 | PrimaryMBR[0x1CD] = 0xFF; 25 | PrimaryMBR[0x1FE] = 0x55; 26 | PrimaryMBR[0x1FF] = 0xAA; 27 | 28 | return [ 29 | .. PrimaryMBR, 30 | .. GPTUtils.MakeGPT(DiskSize, SectorSize, deviceProfile.PartitionLayout, deviceProfile.DiskGuid, IsBackupGPT: false, SplitInHalf: deviceProfile.SplittingStrategy == SplittingStrategy.HalfSplit, AndroidDesiredSpace: deviceProfile.SplittingStrategy == SplittingStrategy.Custom ? deviceProfile.CustomSplittingAndroidDesiredSpace : 4_294_967_296) 31 | ]; 32 | } 33 | 34 | public static byte[] GetBackupGPT(DeviceProfile deviceProfile) 35 | { 36 | ulong DiskSize = deviceProfile.DiskTotalSize; 37 | uint SectorSize = deviceProfile.DiskSectorSize; 38 | 39 | return GPTUtils.MakeGPT(DiskSize, SectorSize, deviceProfile.PartitionLayout, deviceProfile.DiskGuid, IsBackupGPT: true, SplitInHalf: deviceProfile.SplittingStrategy == SplittingStrategy.HalfSplit, AndroidDesiredSpace: deviceProfile.SplittingStrategy == SplittingStrategy.Custom ? deviceProfile.CustomSplittingAndroidDesiredSpace : 4_294_967_296); 40 | } 41 | 42 | public static string GetBlankVHD(DeviceProfile deviceProfile) 43 | { 44 | ulong DiskSize = deviceProfile.DiskTotalSize; 45 | uint SectorSize = deviceProfile.DiskSectorSize; 46 | 47 | const string tmp = "tmp"; 48 | const string TmpVHD = $@"{tmp}\temp.vhdx"; 49 | 50 | if (!Directory.Exists(tmp)) 51 | { 52 | _ = Directory.CreateDirectory(tmp); 53 | } 54 | 55 | if (File.Exists(TmpVHD)) 56 | { 57 | File.Delete(TmpVHD); 58 | } 59 | 60 | Logging.Log("Generating Primary GPT"); 61 | byte[] PrimaryGPT = GetPrimaryGPT(deviceProfile); 62 | 63 | Logging.Log("Generating Backup GPT"); 64 | byte[] BackupGPT = GetBackupGPT(deviceProfile); 65 | 66 | Logging.Log("Generating Main VHD"); 67 | VHDUtils.CreateVHDX(TmpVHD, SectorSize, DiskSize); 68 | 69 | BlankVHDUtils.PrepareVHD(TmpVHD, PrimaryGPT, BackupGPT); 70 | 71 | return TmpVHD; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP845MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SDM845.MTP.* 6 | Qualcomm.SDA845.MTP.* 7 | 8 | QCOM_MTP_845_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp845.xml 10 | 57923203072 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 9971b734-76a9-6346-867e-51fb7abc233d 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | a80da189-c49e-10d6-8aaf-89b6dffe5241 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | ae86b931-386c-bf21-d34b-564b0d90a3c7 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 9288640b-238f-e01f-7ca6-f0438c8f6cfd 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 18570322-e1d6-dc87-15bd-b47dd8d9e250 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | 8b851c10-c2a6-d2b0-d49e-a2ab2a232c2d 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | 76f08c4f-b35a-ceea-6fd7-d1db8aafa6ca 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 71 | 206713c7-fe92-3bd0-07fc-d20c3d202e62 72 | 1581576 73 | 1581574 74 | 0 75 | userdata 76 | 77 | 78 | MaximizedForWindows 79 | 4294967296 80 | efa6243a-085f-e745-f2ce-54d39ef34351 81 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/HDK8998MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.MSM8998.HDK.* 6 | Qualcomm.APQ8098.HDK.* 7 | 8 | QCOM_HDK_8998_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\hdk8998.xml 10 | 121920008192 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 3df038ac-42b4-6dc0-21d6-d51275ef7bcc 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 17935533-fa21-8667-a019-e599905a1c3a 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 408b7938-6f09-4e95-f6cd-070b4bfb9653 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 1e9e4204-5a7e-6596-da70-520ba4d74e07 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | f170496d-c62d-609b-47a2-87b406b0fcc9 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | f726e1b1-aa3a-727b-b9a3-e287dabf2e17 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | 9ccca6db-fc02-05c9-ab20-54219161a645 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 71 | c9c0ed5b-5a3b-cf3c-b4af-d8a6f531f20f 72 | 1581576 73 | 1581575 74 | 0 75 | userdata 76 | 77 | 78 | MaximizedForWindows 79 | 4294967296 80 | 98101b32-bbe2-4bf2-a06e-2bb33d000c20 81 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP8998MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.MSM8998.HDK.* 6 | Qualcomm.APQ8098.HDK.* 7 | 8 | QCOM_MTP_8998_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp8998.xml 10 | 57939980288 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 0de26d17-4443-9af7-4948-afcbd0c5fd55 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | e7c51f31-10ae-8158-92f9-2284fb4a282b 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 61075db8-1628-b265-44fc-b6e4f1ca94af 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 7b42842d-3227-1e1b-4f6e-bed653d068f5 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 730286b7-c15a-b8d9-008f-837a6080a1b6 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | ef07a89e-5451-e614-6866-71d57e7782ac 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | b5d8f79d-2a86-d5e3-a2a9-c5414dca50e0 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 71 | a0d89f1f-7447-8a4e-18c4-a44f17f30b1e 72 | 1581576 73 | 1581575 74 | 0 75 | userdata 76 | 77 | 78 | MaximizedForWindows 79 | 4294967296 80 | 98101b32-bbe2-4bf2-a06e-2bb33d000c20 81 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/ZetaHalfSplit512GB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo 2.1995 6 | Microsoft Corporation.Surface.Surface Duo 2.1968 7 | OEMC1.*.OEMC1 Product.* 8 | OEMZE.*.OEMZE Product.* 9 | 10 | OEMZE_512GB_HalfSplit.ffu 11 | \definitions\Desktop\ARM64\Internal\zeta.xml 12 | 0 13 | 4096 14 | 15 | 16 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 17 | dd334fea-6336-1cfc-9b54-625a4f119d3b 18 | 6 19 | 7 20 | 0 21 | ssd 22 | 23 | 24 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 25 | 9c508206-a952-e02d-73dd-25b08eda76e4 26 | 8 27 | 8199 28 | 0 29 | persist 30 | 31 | 32 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 33 | 5e514cb8-1151-c29c-830f-5bf399b40c74 34 | 8200 35 | 12295 36 | 0 37 | metadata 38 | 39 | 40 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 41 | dd11345e-4c1f-99ee-afd0-e55e6ecc92d6 42 | 12296 43 | 12423 44 | 0 45 | frp 46 | 47 | 48 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 49 | 035e02e0-4bb9-06ce-4851-a1ec88834507 50 | 12424 51 | 12679 52 | 0 53 | misc 54 | 55 | 56 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 57 | 68733ebb-ef36-f8ca-11e9-893ace2e6585 58 | 12680 59 | 89479 60 | 0 61 | rawdump 62 | 63 | 64 | 21adb864-c9e7-4c76-be68-568e20c58439 65 | d296e468-eba2-dfe6-23d5-3b5cb3a853d9 66 | 89480 67 | 97835 68 | 0 69 | vm-data 70 | 71 | 72 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 73 | 411d7753-d116-25ee-ca31-6436766e9580 74 | 97836 75 | 97835 76 | 0 77 | userdata 78 | 79 | 80 | HalfSplit 81 | 4294967296 82 | efa6243a-085f-e745-f2ce-54d39ef34351 83 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/ZetaHalfSplit128GB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo 2.1995 6 | Microsoft Corporation.Surface.Surface Duo 2.1968 7 | OEMC1.*.OEMC1 Product.* 8 | OEMZE.*.OEMZE Product.* 9 | 10 | OEMZE_128GB_HalfSplit.ffu 11 | \definitions\Desktop\ARM64\Internal\zeta.xml 12 | 110394081280 13 | 4096 14 | 15 | 16 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 17 | dd334fea-6336-1cfc-9b54-625a4f119d3b 18 | 6 19 | 7 20 | 0 21 | ssd 22 | 23 | 24 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 25 | 9c508206-a952-e02d-73dd-25b08eda76e4 26 | 8 27 | 8199 28 | 0 29 | persist 30 | 31 | 32 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 33 | 5e514cb8-1151-c29c-830f-5bf399b40c74 34 | 8200 35 | 12295 36 | 0 37 | metadata 38 | 39 | 40 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 41 | dd11345e-4c1f-99ee-afd0-e55e6ecc92d6 42 | 12296 43 | 12423 44 | 0 45 | frp 46 | 47 | 48 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 49 | 035e02e0-4bb9-06ce-4851-a1ec88834507 50 | 12424 51 | 12679 52 | 0 53 | misc 54 | 55 | 56 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 57 | 68733ebb-ef36-f8ca-11e9-893ace2e6585 58 | 12680 59 | 89479 60 | 0 61 | rawdump 62 | 63 | 64 | 21adb864-c9e7-4c76-be68-568e20c58439 65 | d296e468-eba2-dfe6-23d5-3b5cb3a853d9 66 | 89480 67 | 97835 68 | 0 69 | vm-data 70 | 71 | 72 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 73 | 411d7753-d116-25ee-ca31-6436766e9580 74 | 97836 75 | 97835 76 | 0 77 | userdata 78 | 79 | 80 | HalfSplit 81 | 4294967296 82 | efa6243a-085f-e745-f2ce-54d39ef34351 83 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/ZetaHalfSplit256GB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo 2.1995 6 | Microsoft Corporation.Surface.Surface Duo 2.1968 7 | OEMC1.*.OEMC1 Product.* 8 | OEMZE.*.OEMZE Product.* 9 | 10 | OEMZE_256GB_HalfSplit.ffu 11 | \definitions\Desktop\ARM64\Internal\zeta.xml 12 | 238353907712 13 | 4096 14 | 15 | 16 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 17 | dd334fea-6336-1cfc-9b54-625a4f119d3b 18 | 6 19 | 7 20 | 0 21 | ssd 22 | 23 | 24 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 25 | 9c508206-a952-e02d-73dd-25b08eda76e4 26 | 8 27 | 8199 28 | 0 29 | persist 30 | 31 | 32 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 33 | 5e514cb8-1151-c29c-830f-5bf399b40c74 34 | 8200 35 | 12295 36 | 0 37 | metadata 38 | 39 | 40 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 41 | dd11345e-4c1f-99ee-afd0-e55e6ecc92d6 42 | 12296 43 | 12423 44 | 0 45 | frp 46 | 47 | 48 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 49 | 035e02e0-4bb9-06ce-4851-a1ec88834507 50 | 12424 51 | 12679 52 | 0 53 | misc 54 | 55 | 56 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 57 | 68733ebb-ef36-f8ca-11e9-893ace2e6585 58 | 12680 59 | 89479 60 | 0 61 | rawdump 62 | 63 | 64 | 21adb864-c9e7-4c76-be68-568e20c58439 65 | d296e468-eba2-dfe6-23d5-3b5cb3a853d9 66 | 89480 67 | 97835 68 | 0 69 | vm-data 70 | 71 | 72 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 73 | 411d7753-d116-25ee-ca31-6436766e9580 74 | 97836 75 | 97835 76 | 0 77 | userdata 78 | 79 | 80 | HalfSplit 81 | 4294967296 82 | efa6243a-085f-e745-f2ce-54d39ef34351 83 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/ZetaMaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Microsoft Corporation.Surface.Surface Duo 2.1995 6 | Microsoft Corporation.Surface.Surface Duo 2.1968 7 | OEMC1.*.OEMC1 Product.* 8 | OEMZE.*.OEMZE Product.* 9 | 10 | OEMZE_MaximizedForWindows.ffu 11 | \definitions\Desktop\ARM64\Internal\zeta.xml 12 | 110394081280 13 | 4096 14 | 15 | 16 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 17 | dd334fea-6336-1cfc-9b54-625a4f119d3b 18 | 6 19 | 7 20 | 0 21 | ssd 22 | 23 | 24 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 25 | 9c508206-a952-e02d-73dd-25b08eda76e4 26 | 8 27 | 8199 28 | 0 29 | persist 30 | 31 | 32 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 33 | 5e514cb8-1151-c29c-830f-5bf399b40c74 34 | 8200 35 | 12295 36 | 0 37 | metadata 38 | 39 | 40 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 41 | dd11345e-4c1f-99ee-afd0-e55e6ecc92d6 42 | 12296 43 | 12423 44 | 0 45 | frp 46 | 47 | 48 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 49 | 035e02e0-4bb9-06ce-4851-a1ec88834507 50 | 12424 51 | 12679 52 | 0 53 | misc 54 | 55 | 56 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 57 | 68733ebb-ef36-f8ca-11e9-893ace2e6585 58 | 12680 59 | 89479 60 | 0 61 | rawdump 62 | 63 | 64 | 21adb864-c9e7-4c76-be68-568e20c58439 65 | d296e468-eba2-dfe6-23d5-3b5cb3a853d9 66 | 89480 67 | 97835 68 | 0 69 | vm-data 70 | 71 | 72 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 73 | 411d7753-d116-25ee-ca31-6436766e9580 74 | 97836 75 | 97835 76 | 0 77 | userdata 78 | 79 | 80 | MaximizedForWindows 81 | 4294967296 82 | efa6243a-085f-e745-f2ce-54d39ef34351 83 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/BlankVHDUtils.cs: -------------------------------------------------------------------------------- 1 | using DiscUtils.Vhdx; 2 | using System; 3 | using System.IO; 4 | 5 | namespace FirmwareGen.VirtualDisks 6 | { 7 | internal class BlankVHDUtils 8 | { 9 | private static void WriteGPTToDisk(string TmpVHD, byte[] PrimaryGPT, byte[] BackupGPT) 10 | { 11 | const int chunkSize = 4096; 12 | 13 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(Disk).Assembly); 14 | using DiscUtils.VirtualDisk outDisk = DiscUtils.VirtualDisk.OpenDisk(TmpVHD, FileAccess.ReadWrite); 15 | 16 | DiscUtils.Streams.SparseStream ds = outDisk.Content; 17 | 18 | // Primary GPT 19 | Logging.Log("Writing Primary GPT"); 20 | _ = ds.Seek(0, SeekOrigin.Begin); 21 | int sectors = PrimaryGPT.Length / chunkSize; 22 | DateTime startTime = DateTime.Now; 23 | using (BinaryReader br = new(new MemoryStream(PrimaryGPT))) 24 | { 25 | for (int i = 0; i < sectors; i++) 26 | { 27 | byte[] buff = br.ReadBytes(chunkSize); 28 | ds.Write(buff, 0, chunkSize); 29 | Logging.ShowProgress((ulong)PrimaryGPT.Length, startTime, (ulong)((i + 1) * chunkSize), (ulong)((i + 1) * chunkSize), false); 30 | } 31 | } 32 | Logging.Log(""); 33 | 34 | // Backup GPT 35 | Logging.Log("Writing Backup GPT"); 36 | _ = ds.Seek(-BackupGPT.Length, SeekOrigin.End); 37 | sectors = BackupGPT.Length / chunkSize; 38 | startTime = DateTime.Now; 39 | using (BinaryReader br = new(new MemoryStream(BackupGPT))) 40 | { 41 | for (int i = 0; i < sectors; i++) 42 | { 43 | byte[] buff = br.ReadBytes(chunkSize); 44 | ds.Write(buff, 0, chunkSize); 45 | Logging.ShowProgress((ulong)BackupGPT.Length, startTime, (ulong)((i + 1) * chunkSize), (ulong)((i + 1) * chunkSize), false); 46 | } 47 | } 48 | Logging.Log(""); 49 | 50 | ds.Dispose(); 51 | } 52 | 53 | public static void PrepareVHD(string TmpVHD, byte[] PrimaryGPT, byte[] BackupGPT) 54 | { 55 | const string SystemPartition = "Y:"; 56 | 57 | Logging.Log("Writing GPT"); 58 | WriteGPTToDisk(TmpVHD, PrimaryGPT, BackupGPT); 59 | 60 | Logging.Log("Mounting Main VHD"); 61 | string DiskId = VolumeUtils.MountVirtualHardDisk(TmpVHD, false); 62 | 63 | Logging.Log("Getting Windows Partition Drive Letter"); 64 | string VHDLetter = VolumeUtils.GetVirtualHardDiskLetterFromDiskID(DiskId); 65 | 66 | Logging.Log($"Windows Partition: {VHDLetter}"); 67 | 68 | // Format as NTFS 69 | VolumeUtils.RunProgram("cmd.exe", $"/C format {VHDLetter} /FS:NTFS /V:MainOS /Q /Y"); 70 | 71 | Logging.Log($"Mounting System Partition: {SystemPartition}"); 72 | VolumeUtils.MountSystemPartition(DiskId, SystemPartition); 73 | 74 | // Format as FAT32 75 | VolumeUtils.RunProgram("cmd.exe", $"/C format {SystemPartition} /FS:FAT32 /V:EFIESP /Q /Y"); 76 | 77 | Logging.Log($"Unmounting System Partition: {SystemPartition}"); 78 | VolumeUtils.UnmountSystemPartition(DiskId, SystemPartition); 79 | 80 | Logging.Log("Dismounting Main VHD"); 81 | VolumeUtils.DismountVirtualHardDisk(TmpVHD); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP8996SGMaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.MSM8996SG.MTP.* 6 | 7 | QCOM_MTP_8996SG_MaximizedForWindows.ffu 8 | \definitions\Desktop\ARM64\Internal\mtp8996.xml 9 | 28986699776 10 | 4096 11 | 12 | 13 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 14 | 710f2ad7-f502-64b4-8483-6577359785ac 15 | 6 16 | 7 17 | 0 18 | ssd 19 | 20 | 21 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 22 | 1fde6b12-15ca-3ed5-35fe-336d94dc485a 23 | 8 24 | 8199 25 | 0 26 | persist 27 | 28 | 29 | 5594c694-c871-4b5f-90b1-690a6f68e0f7 30 | cd4353a4-297b-4000-ef31-b112dfbd4ae6 31 | 8200 32 | 73735 33 | 0 34 | cache 35 | 36 | 37 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 38 | 5d64cf4a-5a36-19e0-5f5d-652e71e7967c 39 | 73736 40 | 73991 41 | 0 42 | misc 43 | 44 | 45 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 46 | a065a77b-2430-bed4-016a-1bd5d62204ba 47 | 73992 48 | 74119 49 | 0 50 | keystore 51 | 52 | 53 | f65d4b16-343d-4e25-aafc-be99b6556a6d 54 | b1c0a97b-81b3-a80b-dcfb-9c696982ca76 55 | 74120 56 | 74151 57 | 0 58 | devcfg 59 | 60 | 61 | f65d4b16-343d-4e25-aafc-be99b6556a6d 62 | 24939d44-09d6-284b-f270-0641e55cbde8 63 | 74152 64 | 74183 65 | 0 66 | devcfgbak 67 | 68 | 69 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 70 | 4913f6bd-af02-e5b8-5009-f5af061f0a67 71 | 74184 72 | 74311 73 | 0 74 | frp 75 | 76 | 77 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 78 | b9926f60-aca7-aefc-f8b7-f946f8ebda65 79 | 74312 80 | 74311 81 | 0 82 | userdata 83 | 84 | 85 | MaximizedForWindows 86 | 4294967296 87 | 98101b32-bbe2-4bf2-a06e-2bb33d000c20 88 | -------------------------------------------------------------------------------- /GPTFixer/Img2Ffu/GPT/Partition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the "Software"), 5 | // to deal in the Software without restriction, including without limitation 6 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | // and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | // DEALINGS IN THE SOFTWARE. 20 | 21 | using System; 22 | 23 | namespace GPTFixer.Img2Ffu 24 | { 25 | public partial class GPT 26 | { 27 | public class Partition 28 | { 29 | private ulong _SizeInSectors; 30 | private ulong _FirstSector; 31 | private ulong _LastSector; 32 | 33 | public required string Name; // 0x48 34 | public Guid PartitionTypeGuid; // 0x10 35 | public Guid PartitionGuid; // 0x10 36 | internal ulong Attributes; // 0x08 37 | 38 | internal ulong SizeInSectors 39 | { 40 | get => _SizeInSectors != 0 ? _SizeInSectors : LastSector - FirstSector + 1; 41 | set 42 | { 43 | _SizeInSectors = value; 44 | if (FirstSector != 0) 45 | { 46 | LastSector = FirstSector + _SizeInSectors - 1; 47 | } 48 | } 49 | } 50 | 51 | internal ulong FirstSector // 0x08 52 | { 53 | get => _FirstSector; 54 | set 55 | { 56 | _FirstSector = value; 57 | if (_SizeInSectors != 0) 58 | { 59 | _LastSector = FirstSector + _SizeInSectors - 1; 60 | } 61 | } 62 | } 63 | 64 | internal ulong LastSector // 0x08 65 | { 66 | get => _LastSector; 67 | set 68 | { 69 | _LastSector = value; 70 | _SizeInSectors = 0; 71 | } 72 | } 73 | 74 | public string Volume => @"\\?\Volume" + PartitionGuid.ToString("b") + @"\"; 75 | 76 | public string FirstSectorAsString 77 | { 78 | get => "0x" + FirstSector.ToString("X16"); 79 | set => FirstSector = Convert.ToUInt64(value, 16); 80 | } 81 | 82 | public string LastSectorAsString 83 | { 84 | get => "0x" + LastSector.ToString("X16"); 85 | set => LastSector = Convert.ToUInt64(value, 16); 86 | } 87 | 88 | public string AttributesAsString 89 | { 90 | get => "0x" + Attributes.ToString("X16"); 91 | set => Attributes = Convert.ToUInt64(value, 16); 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/HDK8150MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SDM855.HDK.* 6 | Qualcomm.SDA855.HDK.* 7 | 8 | QCOM_HDK_8150_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\hdk855.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 8dc4ecb7-ff86-3d94-d387-1449399ea505 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 39d67acd-7d30-05bb-9858-2f1aa690bd62 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 8c411442-80d3-c8ae-00d9-d3f00628f36d 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 9221b598-54b0-815f-ddf9-7467e6745997 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | f659c797-c2cc-5219-9960-ed5424adba9d 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | 418a18c4-d030-0ccd-7dc7-1c260cee04d2 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | b39b1b42-b209-c641-ba38-80266326e1a8 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 71 | c8439ac5-0671-413c-7857-f2c0c9a98e6f 72 | 1581576 73 | 1585671 74 | 0 75 | metadata 76 | 77 | 78 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 79 | 52e20a04-5877-fa15-3633-b59d1377370a 80 | 1585672 81 | 1618439 82 | 0 83 | rawdump 84 | 85 | 86 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 87 | 696babed-7e7f-a83f-b200-fe8dcc85f800 88 | 1618440 89 | 1618439 90 | 0 91 | userdata 92 | 93 | 94 | MaximizedForWindows 95 | 4294967296 96 | fa75457c-892f-834c-d7a2-0d2bbca8816c 97 | -------------------------------------------------------------------------------- /GPT2DeviceProfile/GptStudio/GPT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace GptStudio 7 | { 8 | public class GPT 9 | { 10 | public required List Partitions 11 | { 12 | get; set; 13 | } 14 | 15 | public bool IsBackup 16 | { 17 | get; set; 18 | } 19 | 20 | public bool ReflectPartitionEntryCount 21 | { 22 | get; set; 23 | } 24 | 25 | public int SectorSize 26 | { 27 | get; set; 28 | } 29 | 30 | public static T StructureFromBytes(byte[] arr) where T : struct 31 | { 32 | T str = default; 33 | 34 | GCHandle h = default; 35 | 36 | try 37 | { 38 | h = GCHandle.Alloc(arr, GCHandleType.Pinned); 39 | 40 | str = Marshal.PtrToStructure(h.AddrOfPinnedObject()); 41 | 42 | } 43 | finally 44 | { 45 | if (h.IsAllocated) 46 | { 47 | h.Free(); 48 | } 49 | } 50 | 51 | return str; 52 | } 53 | 54 | public static GPT ReadFromStream(Stream stream, int sectorSize) 55 | { 56 | byte[] array = new byte[sectorSize]; 57 | stream.Read(array, 0, array.Length); 58 | GPTHeader gptheader = StructureFromBytes(array); 59 | 60 | while (new string(gptheader.Signature) != "EFI PART") 61 | { 62 | stream.Read(array, 0, array.Length); 63 | gptheader = StructureFromBytes(array); 64 | } 65 | 66 | GPT? gpt; 67 | 68 | if (new string(gptheader.Signature) == "EFI PART") 69 | { 70 | bool isBackupGPT = gptheader.CurrentLBA > gptheader.PartitionArrayLBA; 71 | bool reflectPartitionEntryCount = true; 72 | 73 | if (isBackupGPT) 74 | { 75 | stream.Seek(-sectorSize, SeekOrigin.Current); 76 | } 77 | 78 | List list = []; 79 | 80 | uint num = 0; 81 | 82 | while (num < gptheader.PartitionEntryCount) 83 | { 84 | int num2 = sectorSize / (int)gptheader.PartitionEntrySize; 85 | stream.Read(array, 0, array.Length); 86 | 87 | for (int i = 0; i < num2; i++) 88 | { 89 | int startOffset = i * (int)gptheader.PartitionEntrySize; 90 | int endOffset = (i + 1) * (int)gptheader.PartitionEntrySize; 91 | 92 | byte[] partitionEntryBuffer = array[startOffset..endOffset]; 93 | 94 | GPTPartition gptpartition = StructureFromBytes(partitionEntryBuffer); 95 | 96 | if (gptpartition.TypeGUID == Guid.Empty) 97 | { 98 | num = gptheader.PartitionEntryCount; 99 | reflectPartitionEntryCount = false; 100 | break; 101 | } 102 | 103 | list.Add(gptpartition); 104 | num++; 105 | } 106 | } 107 | 108 | gpt = new GPT 109 | { 110 | Header = gptheader, 111 | Partitions = list, 112 | IsBackup = isBackupGPT, 113 | ReflectPartitionEntryCount = reflectPartitionEntryCount, 114 | SectorSize = sectorSize 115 | }; 116 | } 117 | else 118 | { 119 | gpt = null; 120 | } 121 | 122 | return gpt; 123 | } 124 | 125 | public GPTHeader Header; 126 | } 127 | } -------------------------------------------------------------------------------- /FirmwareGen/MainLogic.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.CommandLine; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | namespace FirmwareGen 6 | { 7 | public static class MainLogic 8 | { 9 | public static bool VerifyAllComponentsArePresent() 10 | { 11 | string toolDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName); 12 | 13 | string wimlib = Path.Combine(toolDirectory, "wimlib-imagex.exe"); 14 | string Img2Ffu = Path.Combine(toolDirectory, "Img2Ffu.exe"); 15 | string DriverUpdater = Path.Combine(toolDirectory, "DriverUpdater.exe"); 16 | 17 | if (!File.Exists(wimlib)) 18 | { 19 | Logging.Log($"Some components could not be found: {wimlib}", Logging.LoggingLevel.Error); 20 | return false; 21 | } 22 | 23 | if (!File.Exists(Img2Ffu)) 24 | { 25 | Logging.Log($"Some components could not be found: {Img2Ffu}", Logging.LoggingLevel.Error); 26 | return false; 27 | } 28 | 29 | if (!File.Exists(DriverUpdater)) 30 | { 31 | Logging.Log($"Some components could not be found: {DriverUpdater}", Logging.LoggingLevel.Error); 32 | return false; 33 | } 34 | 35 | return true; 36 | } 37 | 38 | public static void GenerateWindowsFFU(GenerateWindowsFFUOptions options) 39 | { 40 | string toolDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName); 41 | 42 | string wimlib = Path.Combine(toolDirectory, "wimlib-imagex.exe"); 43 | string Img2Ffu = Path.Combine(toolDirectory, "Img2Ffu.exe"); 44 | string DriverUpdater = Path.Combine(toolDirectory, "DriverUpdater.exe"); 45 | 46 | const string SystemPartition = "Y:"; 47 | 48 | DeviceProfile deviceProfile = XmlUtils.Deserialize(options.DeviceProfile); 49 | 50 | string TmpVHD = CommonLogic.GetBlankVHD(deviceProfile); 51 | string DiskId = VolumeUtils.MountVirtualHardDisk(TmpVHD, false); 52 | string VHDLetter = VolumeUtils.GetVirtualHardDiskLetterFromDiskID(DiskId); 53 | 54 | VolumeUtils.ApplyWindowsImageFromDVD(wimlib, options.WindowsDVD, options.WindowsIndex, VHDLetter); 55 | VolumeUtils.PerformSlabOptimization(VHDLetter); 56 | VolumeUtils.ApplyCompactFlagsToImage(VHDLetter); 57 | VolumeUtils.MountSystemPartition(DiskId, SystemPartition); 58 | VolumeUtils.ConfigureBootManager(VHDLetter, SystemPartition); 59 | VolumeUtils.UnmountSystemPartition(DiskId, SystemPartition); 60 | 61 | if (deviceProfile.SupplementaryBCDCommands.Length > 0) 62 | { 63 | VolumeUtils.MountSystemPartition(DiskId, SystemPartition); 64 | 65 | Logging.Log("Configuring supplemental boot"); 66 | foreach (string command in deviceProfile.SupplementaryBCDCommands) 67 | { 68 | VolumeUtils.RunProgram("bcdedit.exe", $"{$@"/store {SystemPartition}\EFI\Microsoft\Boot\BCD "}{command}"); 69 | } 70 | 71 | VolumeUtils.UnmountSystemPartition(DiskId, SystemPartition); 72 | } 73 | 74 | Logging.Log("Adding drivers"); 75 | VolumeUtils.RunProgram(DriverUpdater, $@"-d ""{options.DriverPack}{deviceProfile.DriverDefinitionPath}"" -r ""{options.DriverPack}"" -p ""{VHDLetter}"""); 76 | 77 | VolumeUtils.DismountVirtualHardDisk(TmpVHD); 78 | 79 | Logging.Log("Making FFU"); 80 | VolumeUtils.RunProgram(Img2Ffu, $@"-i {TmpVHD} -f ""{options.Output}\{deviceProfile.FFUFileName}"" -c {deviceProfile.DiskSectorSize * 4} -s {deviceProfile.DiskSectorSize} -p ""{string.Join(";", deviceProfile.PlatformIDs)}"" -o {options.WindowsVer} -b 4000 -v V2 -d VenHw(860845C1-BE09-4355-8BC1-30D64FF8E63A) -l false -e .\provisioning-partitions.txt -t ""{options.SecureBootSigningCommand}"""); 81 | 82 | Logging.Log("Deleting Temp VHD"); 83 | File.Delete(TmpVHD); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/HHG8350MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SM_LAHAINA.HHG.* 6 | Qualcomm.SMP_LAHAINA.HHG.* 7 | 8 | QCOM_HHG_8350_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\hhg888.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 5c0efacf-c95b-8552-b9c9-1d060a2b3739 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | b7496373-6f5c-e337-a537-df594768fb58 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 7a83b05f-baac-19af-828f-bf7fd7210e79 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 12d14ad6-e1cb-c065-97d0-398b5baa9b93 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 76be6a4f-137c-01d9-9546-cb556c74e41a 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 89a12de1-5e41-4cb3-8b4c-b1441eb5da38 55 | cc6cd14a-83ea-dec5-b78d-fe7e91bcf38d 56 | 8712 57 | 1581575 58 | 0 59 | super 60 | 61 | 62 | 1344859d-3a6a-4c14-a316-9e696b3a5400 63 | 92fbed6b-319b-187c-f0c5-4f351cf8d577 64 | 1581576 65 | 1581591 66 | 1154047404513689600 67 | vbmeta_system_a 68 | 69 | 70 | fe3ab853-5b66-4d4a-bf85-8d90af1c2c4a 71 | a2c44005-d54c-a0e7-9935-953882d972c1 72 | 1581592 73 | 1581607 74 | 1152921504606846976 75 | vbmeta_system_b 76 | 77 | 78 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 79 | a1cf022e-9d11-8039-ef48-9af5c951c0dd 80 | 1581608 81 | 1585703 82 | 0 83 | metadata 84 | 85 | 86 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 87 | 0b708144-873d-0389-401f-e5aaebd85a0a 88 | 1585704 89 | 4782631 90 | 0 91 | rawdump 92 | 93 | 94 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 95 | 39154595-4e32-d057-d362-cbae468477b3 96 | 4782632 97 | 4782631 98 | 0 99 | userdata 100 | 101 | 102 | MaximizedForWindows 103 | 4294967296 104 | efa6243a-085f-e745-f2ce-54d39ef34351 105 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/QRD7325MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SM_KODIAK.QRD.* 6 | Qualcomm.SMP_KODIAK.QRD.* 7 | 8 | QCOM_QRD_7325_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\qrd778g.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 77bcb85a-e775-cb4d-15be-3b65be0cc665 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | a4c7fd42-083f-4ab9-4501-5b7e4fa1ea67 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | fe32a24b-f3a8-8fdf-0012-a3bfd293e044 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | f14191c6-9f6e-b637-4237-5d2c4fffe56a 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 7e216149-0fe1-b760-65a5-fbf475ff77fe 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 89a12de1-5e41-4cb3-8b4c-b1441eb5da38 55 | d798c8eb-c7ff-03c5-8e60-0ccfb198d49c 56 | 8712 57 | 1581575 58 | 0 59 | super 60 | 61 | 62 | 1344859d-3a6a-4c14-a316-9e696b3a5400 63 | 12b50df5-6bc5-c3c0-24d1-f37357836e01 64 | 1581576 65 | 1581591 66 | 1154047404513689600 67 | vbmeta_system_a 68 | 69 | 70 | fe3ab853-5b66-4d4a-bf85-8d90af1c2c4a 71 | fdf460b8-d796-fbfb-1344-8eb3ef8f5621 72 | 1581592 73 | 1581607 74 | 1152921504606846976 75 | vbmeta_system_b 76 | 77 | 78 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 79 | 89528a88-be32-e2c9-2434-bea2b4f77d48 80 | 1581608 81 | 1585703 82 | 0 83 | metadata 84 | 85 | 86 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 87 | a918bfad-504e-1294-f66c-ac20574c5b80 88 | 1585704 89 | 4782631 90 | 0 91 | rawdump 92 | 93 | 94 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 95 | 46805a15-8ef8-9293-f434-ce7b25d56b0e 96 | 4782632 97 | 4782631 98 | 0 99 | userdata 100 | 101 | 102 | MaximizedForWindows 103 | 4294967296 104 | efa6243a-085f-e745-f2ce-54d39ef34351 105 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/QRD8350MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SM_LAHAINA.QRD.* 6 | Qualcomm.SMP_LAHAINA.QRD.* 7 | 8 | QCOM_QRD_8350_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\qrd888.xml 10 | 238353907712 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 4a8ef87a-0492-881c-de48-8baeec066902 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 882c6a35-04dd-54b5-d51d-975e85c32e9d 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | c1b5e06e-269d-311d-b1b0-a2f9492f685d 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | 779309b2-f2d6-1a0b-c09f-dff43ca72187 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | dac14f31-f394-43b5-6a20-caa459371a3c 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 89a12de1-5e41-4cb3-8b4c-b1441eb5da38 55 | 823f6fcc-7a65-c30e-6c5b-57227882fedf 56 | 8712 57 | 2290413 58 | 0 59 | super 60 | 61 | 62 | 1344859d-3a6a-4c14-a316-9e696b3a5400 63 | f3beddc8-1977-b235-4284-9500e39908e9 64 | 2290414 65 | 2290429 66 | 1154047404513689600 67 | vbmeta_system_a 68 | 69 | 70 | fe3ab853-5b66-4d4a-bf85-8d90af1c2c4a 71 | f99273de-e842-bd61-b08a-54b0a33b780e 72 | 2290430 73 | 2290445 74 | 1152921504606846976 75 | vbmeta_system_b 76 | 77 | 78 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 79 | c330b886-5db4-b2f8-1aeb-caf478541739 80 | 2290446 81 | 2294541 82 | 0 83 | metadata 84 | 85 | 86 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 87 | 1301d3f0-25b1-3604-4ab7-f3bcf8e9fbf8 88 | 2294542 89 | 2991469 90 | 0 91 | rawdump 92 | 93 | 94 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 95 | 70d8428d-14ea-0524-d08a-b3e103cd7a77 96 | 2991470 97 | 2991469 98 | 0 99 | userdata 100 | 101 | 102 | MaximizedForWindows 103 | 4294967296 104 | efa6243a-085f-e745-f2ce-54d39ef34351 105 | -------------------------------------------------------------------------------- /FirmwareGen/GPT/CRC32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FirmwareGen.GPT 4 | { 5 | internal static class CRC32 6 | { 7 | private static readonly uint[] CRC32Table = 8 | [ 9 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 10 | 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 11 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 12 | 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 13 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 14 | 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 15 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 16 | 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 17 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 18 | 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 19 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 20 | 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 21 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 22 | 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 23 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 24 | 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 25 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 26 | 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 27 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 28 | 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 29 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 30 | 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 31 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 32 | 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 33 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 34 | 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 35 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 36 | 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 37 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 38 | 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 39 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 40 | 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 41 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 42 | 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 43 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 44 | 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 45 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 46 | 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 47 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 48 | 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 49 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 50 | 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 51 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 52 | ]; 53 | 54 | internal static uint Compute(byte[] Input, uint Offset, uint Length) 55 | { 56 | if (Input == null || Offset + Length > Input.Length) 57 | { 58 | throw new ArgumentException("The provided input buffer is invalid", nameof(Input)); 59 | } 60 | 61 | unchecked 62 | { 63 | uint crc = (uint)((uint)0 ^ -1); 64 | for (uint i = Offset; i < Offset + Length; i++) 65 | { 66 | crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF]; 67 | } 68 | crc = (uint)(crc ^ -1); 69 | 70 | if (crc < 0) 71 | { 72 | crc += (uint)0x100000000; 73 | } 74 | 75 | return crc; 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /GPTFixer/FirmwareGen/GPT/CRC32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GPTFixer.FirmwareGen.GPT 4 | { 5 | internal static class CRC32 6 | { 7 | private static readonly uint[] CRC32Table = 8 | [ 9 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 10 | 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 11 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 12 | 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 13 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 14 | 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 15 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 16 | 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 17 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 18 | 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 19 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 20 | 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 21 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 22 | 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 23 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 24 | 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 25 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 26 | 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 27 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 28 | 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 29 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 30 | 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 31 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 32 | 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 33 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 34 | 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 35 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 36 | 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 37 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 38 | 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 39 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 40 | 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 41 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 42 | 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 43 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 44 | 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 45 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 46 | 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 47 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 48 | 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 49 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 50 | 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 51 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 52 | ]; 53 | 54 | internal static uint Compute(byte[] Input, uint Offset, uint Length) 55 | { 56 | if (Input == null || Offset + Length > Input.Length) 57 | { 58 | throw new ArgumentException("The provided input buffer is invalid", nameof(Input)); 59 | } 60 | 61 | unchecked 62 | { 63 | uint crc = (uint)((uint)0 ^ -1); 64 | for (uint i = Offset; i < Offset + Length; i++) 65 | { 66 | crc = crc >> 8 ^ CRC32Table[(crc ^ Input[i]) & 0xFF]; 67 | } 68 | crc = (uint)(crc ^ -1); 69 | 70 | if (crc < 0) 71 | { 72 | crc += (uint)0x100000000; 73 | } 74 | 75 | return crc; 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /PartitionOffsetsHelperTool/GPT/CRC32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PartitionOffsetsHelperTool.GPT 4 | { 5 | internal static class CRC32 6 | { 7 | private static readonly uint[] CRC32Table = 8 | [ 9 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 10 | 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 11 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 12 | 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 13 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 14 | 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 15 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 16 | 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 17 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 18 | 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 19 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 20 | 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 21 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 22 | 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 23 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 24 | 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 25 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 26 | 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 27 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 28 | 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 29 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 30 | 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 31 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 32 | 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 33 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 34 | 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 35 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 36 | 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 37 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 38 | 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 39 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 40 | 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 41 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 42 | 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 43 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 44 | 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 45 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 46 | 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 47 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 48 | 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 49 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 50 | 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 51 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 52 | ]; 53 | 54 | internal static uint Compute(byte[] Input, uint Offset, uint Length) 55 | { 56 | if (Input == null || Offset + Length > Input.Length) 57 | { 58 | throw new ArgumentException("The provided input buffer is invalid", nameof(Input)); 59 | } 60 | 61 | unchecked 62 | { 63 | uint crc = (uint)((uint)0 ^ -1); 64 | for (uint i = Offset; i < Offset + Length; i++) 65 | { 66 | crc = (crc >> 8) ^ CRC32Table[(crc ^ Input[i]) & 0xFF]; 67 | } 68 | crc = (uint)(crc ^ -1); 69 | 70 | if (crc < 0) 71 | { 72 | crc += (uint)0x100000000; 73 | } 74 | 75 | return crc; 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP50MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SDM855.MTP.* 6 | Qualcomm.SDA855.MTP.* 7 | 8 | QCOM_MTP_8150_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp50.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | e4664002-ccca-c1e6-8d43-1283bf19dada 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 9ae53ef9-8fe5-1f9b-dcef-a044c07a0111 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 1755304d-84e7-e081-d7c2-06e3dd58ba1e 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | bcb1081a-c833-8f9f-f36e-36ec0f204497 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 12d284d7-a08b-166e-e6fa-8958d40a7e5d 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | 7a014fe0-8aeb-40b7-6c53-9ece882dd34f 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | 220f67a2-6c3a-2e4c-5762-a2b1ce46c88f 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | c5f681cc-9742-4641-be4e-976eeb638eee 71 | 6e280891-3254-9666-e767-abdeff5148c7 72 | 1581576 73 | 1614343 74 | 19140298416324608 75 | vm-system_a 76 | 77 | 78 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 79 | 445d2099-5870-5ef3-2a0d-b0e1ed122fac 80 | 1614344 81 | 1647111 82 | 0 83 | vm-system_b 84 | 85 | 86 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 87 | 99d89ebb-23f1-0b5d-468d-4aa0b9dacb24 88 | 1647112 89 | 1651207 90 | 0 91 | metadata 92 | 93 | 94 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 95 | 3050c26a-6e4e-adae-7da4-e5680f9c1a89 96 | 1651208 97 | 1683975 98 | 0 99 | rawdump 100 | 101 | 102 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 103 | 6b977b5e-5ac9-6b48-38b3-f2fc9764e9b8 104 | 1683976 105 | 1683975 106 | 0 107 | userdata 108 | 109 | 110 | MaximizedForWindows 111 | 4294967296 112 | efa6243a-085f-e745-f2ce-54d39ef34351 113 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP8150MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SDM855.MTP.* 6 | Qualcomm.SDA855.MTP.* 7 | 8 | QCOM_MTP_8150_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp855.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | e4664002-ccca-c1e6-8d43-1283bf19dada 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 9ae53ef9-8fe5-1f9b-dcef-a044c07a0111 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 1755304d-84e7-e081-d7c2-06e3dd58ba1e 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | bcb1081a-c833-8f9f-f36e-36ec0f204497 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 12d284d7-a08b-166e-e6fa-8958d40a7e5d 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | 7a014fe0-8aeb-40b7-6c53-9ece882dd34f 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | 220f67a2-6c3a-2e4c-5762-a2b1ce46c88f 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | c5f681cc-9742-4641-be4e-976eeb638eee 71 | 6e280891-3254-9666-e767-abdeff5148c7 72 | 1581576 73 | 1614343 74 | 19140298416324608 75 | vm-system_a 76 | 77 | 78 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 79 | 445d2099-5870-5ef3-2a0d-b0e1ed122fac 80 | 1614344 81 | 1647111 82 | 0 83 | vm-system_b 84 | 85 | 86 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 87 | 99d89ebb-23f1-0b5d-468d-4aa0b9dacb24 88 | 1647112 89 | 1651207 90 | 0 91 | metadata 92 | 93 | 94 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 95 | 3050c26a-6e4e-adae-7da4-e5680f9c1a89 96 | 1651208 97 | 1683975 98 | 0 99 | rawdump 100 | 101 | 102 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 103 | 6b977b5e-5ac9-6b48-38b3-f2fc9764e9b8 104 | 1683976 105 | 1683975 106 | 0 107 | userdata 108 | 109 | 110 | MaximizedForWindows 111 | 4294967296 112 | efa6243a-085f-e745-f2ce-54d39ef34351 113 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/QRD8150MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SDM855.QRD.* 6 | Qualcomm.SDA855.QRD.* 7 | 8 | QCOM_QRD_8150_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\qrd855.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | e4664002-ccca-c1e6-8d43-1283bf19dada 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 9ae53ef9-8fe5-1f9b-dcef-a044c07a0111 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 1755304d-84e7-e081-d7c2-06e3dd58ba1e 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | bcb1081a-c833-8f9f-f36e-36ec0f204497 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 12d284d7-a08b-166e-e6fa-8958d40a7e5d 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 97d7b011-54da-4835-b3c4-917ad6e73d74 55 | 7a014fe0-8aeb-40b7-6c53-9ece882dd34f 56 | 8712 57 | 795143 58 | 19140298416324608 59 | system_a 60 | 61 | 62 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 63 | 220f67a2-6c3a-2e4c-5762-a2b1ce46c88f 64 | 795144 65 | 1581575 66 | 0 67 | system_b 68 | 69 | 70 | c5f681cc-9742-4641-be4e-976eeb638eee 71 | 6e280891-3254-9666-e767-abdeff5148c7 72 | 1581576 73 | 1614343 74 | 19140298416324608 75 | vm-system_a 76 | 77 | 78 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 79 | 445d2099-5870-5ef3-2a0d-b0e1ed122fac 80 | 1614344 81 | 1647111 82 | 0 83 | vm-system_b 84 | 85 | 86 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 87 | 99d89ebb-23f1-0b5d-468d-4aa0b9dacb24 88 | 1647112 89 | 1651207 90 | 0 91 | metadata 92 | 93 | 94 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 95 | 3050c26a-6e4e-adae-7da4-e5680f9c1a89 96 | 1651208 97 | 1683975 98 | 0 99 | rawdump 100 | 101 | 102 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 103 | 6b977b5e-5ac9-6b48-38b3-f2fc9764e9b8 104 | 1683976 105 | 1683975 106 | 0 107 | userdata 108 | 109 | 110 | MaximizedForWindows 111 | 4294967296 112 | efa6243a-085f-e745-f2ce-54d39ef34351 113 | -------------------------------------------------------------------------------- /FirmwareGen/Logging.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Gustave Monce and Contributors 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | using System; 23 | 24 | namespace FirmwareGen 25 | { 26 | internal static class Logging 27 | { 28 | public enum LoggingLevel 29 | { 30 | Information, 31 | Warning, 32 | Error 33 | } 34 | 35 | public static void ShowProgress(ulong totalBytes, DateTime startTime, ulong BytesRead, ulong SourcePosition, bool DisplayRed) 36 | { 37 | DateTime now = DateTime.Now; 38 | TimeSpan timeSoFar = now - startTime; 39 | 40 | TimeSpan remaining = TimeSpan.FromMilliseconds(timeSoFar.TotalMilliseconds / BytesRead * (totalBytes - BytesRead)); 41 | 42 | double speed = Math.Round(SourcePosition / 1024L / 1024L / timeSoFar.TotalSeconds); 43 | 44 | Log(string.Format($"{GetDismLikeProgBar(int.Parse((BytesRead * 100 / totalBytes).ToString()))} {speed}MB/s {Math.Truncate(remaining.TotalHours):00}:{remaining.Minutes:00}:{remaining.Seconds:00}.{remaining.Milliseconds:000}"), severity: DisplayRed ? LoggingLevel.Warning : LoggingLevel.Information, returnline: false); 45 | } 46 | 47 | private static string GetDismLikeProgBar(int perc) 48 | { 49 | int eqsLength = (int)((double)perc / 100 * 55); 50 | string bases = new string('=', eqsLength) + new string(' ', 55 - eqsLength); 51 | bases = bases.Insert(28, perc + "%"); 52 | if (perc == 100) 53 | { 54 | bases = bases[1..]; 55 | } 56 | else if (perc < 10) 57 | { 58 | bases = bases.Insert(28, " "); 59 | } 60 | 61 | return "[" + bases + "]"; 62 | } 63 | 64 | private static readonly ConsoleColor Foreground; 65 | 66 | static Logging() 67 | { 68 | Foreground = Console.ForegroundColor; 69 | } 70 | 71 | private static readonly object lockObj = new(); 72 | 73 | public static void Log(string message, LoggingLevel severity = LoggingLevel.Information, bool returnline = true) 74 | { 75 | lock (lockObj) 76 | { 77 | if (message?.Length == 0) 78 | { 79 | Console.WriteLine(); 80 | return; 81 | } 82 | 83 | string msg = ""; 84 | 85 | switch (severity) 86 | { 87 | case LoggingLevel.Warning: 88 | msg = " Warning "; 89 | Console.ForegroundColor = ConsoleColor.Yellow; 90 | break; 91 | 92 | case LoggingLevel.Error: 93 | msg = " Error "; 94 | Console.ForegroundColor = ConsoleColor.Red; 95 | break; 96 | 97 | case LoggingLevel.Information: 98 | msg = "Information"; 99 | Console.ForegroundColor = Foreground; 100 | break; 101 | } 102 | 103 | if (returnline) 104 | { 105 | Console.WriteLine(DateTime.Now.ToString("'['HH':'mm':'ss']'") + "[" + msg + "] " + message); 106 | } 107 | else 108 | { 109 | Console.Write("\r" + DateTime.Now.ToString("'['HH':'mm':'ss']'") + "[" + msg + "] " + message); 110 | } 111 | 112 | Console.ForegroundColor = Foreground; 113 | } 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /FirmwareGen/VolumeUtils.cs: -------------------------------------------------------------------------------- 1 | using FirmwareGen.Extensions; 2 | using FirmwareGen.VirtualDisks; 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | 7 | namespace FirmwareGen 8 | { 9 | public static class VolumeUtils 10 | { 11 | public static void UnmountSystemPartition(string DiskId, string SystemPartition) 12 | { 13 | Logging.Log("Unmounting SYSTEM"); 14 | RunProgram("powershell.exe", $@"-command ""Get-Partition -DiskNumber {DiskId} | Where {{$_.Type -eq 'System'}} | Remove-PartitionAccessPath -accesspath '{SystemPartition}'"""); 15 | } 16 | 17 | public static void ConfigureBootManager(string VHDLetter, string SystemPartition) 18 | { 19 | Logging.Log("Configuring boot"); 20 | RunProgram("bcdboot.exe", $@"{VHDLetter}\Windows /s {SystemPartition} /f UEFI /l en-us /offline"); 21 | } 22 | 23 | public static void MountSystemPartition(string DiskId, string SystemPartition) 24 | { 25 | Logging.Log("Mounting SYSTEM"); 26 | RunProgram("powershell.exe", $@"-command ""Get-Partition -DiskNumber {DiskId} | Where {{$_.Type -eq 'System'}} | Set-Partition -NewDriveLetter '{SystemPartition}'.Substring(0,1)"""); 27 | } 28 | 29 | public static void ApplyCompactFlagsToImage(string VHDLetter) 30 | { 31 | Logging.Log("Applying compact flags"); 32 | RunProgram("reg.exe", $@"load HKLM\RTSYSTEM {VHDLetter}\Windows\System32\config\SYSTEM"); 33 | RunProgram("reg.exe", @"add HKLM\RTSYSTEM\Setup /v Compact /t REG_DWORD /d 1"); 34 | RunProgram("reg.exe", @"unload HKLM\RTSYSTEM"); 35 | RunProgram("reg.exe", $@"load HKLM\RTSOFTWARE {VHDLetter}\Windows\System32\config\SOFTWARE"); 36 | RunProgram("reg.exe", @"add ""HKLM\RTSOFTWARE\Microsoft\Windows NT\CurrentVersion\Wof"" /v ForceAlgorithm /t REG_DWORD /d 1"); 37 | RunProgram("reg.exe", @"unload HKLM\RTSOFTWARE"); 38 | } 39 | 40 | public static void PerformSlabOptimization(string VHDLetter) 41 | { 42 | Logging.Log("Slab optimization"); 43 | RunProgram("defrag.exe", $"{VHDLetter} /K /X"); 44 | } 45 | 46 | public static void RunProgram(string Program, string Arguments) 47 | { 48 | Process proc = new() 49 | { 50 | StartInfo = new ProcessStartInfo(Program, Arguments) 51 | { 52 | WindowStyle = ProcessWindowStyle.Hidden, 53 | UseShellExecute = false 54 | } 55 | }; 56 | _ = proc.Start(); 57 | proc.WaitForExit(); 58 | } 59 | 60 | public static void ApplyWindowsImageFromDVD(string wimlib, string WindowsDVD, string WindowsIndex, string VHDLetter) 61 | { 62 | Logging.Log("Applying image"); 63 | RunProgram(wimlib, $@"apply {WindowsDVD}\sources\install.wim {WindowsIndex} {VHDLetter} --compact=LZX"); 64 | } 65 | 66 | public static void CopyFile(string Source, string Dest) 67 | { 68 | FileInfo _source = new(Source); 69 | FileInfo _destination = new(Dest); 70 | 71 | DateTime startTime = DateTime.Now; 72 | _source.CopyTo(_destination, x => Logging.ShowProgress(100, startTime, (ulong)x, (ulong)x, false)); 73 | Logging.Log(""); 74 | } 75 | 76 | public static string MountVirtualHardDisk(string VHDPath, bool readOnly) 77 | { 78 | Logging.Log($"Mounting {VHDPath}{(readOnly ? " as read only" : "")}..."); 79 | string id = VHDUtils.MountVHD(VHDPath, readOnly); 80 | Logging.Log($@"Mounted VHD at \\.\PhysicalDisk{id}", Logging.LoggingLevel.Warning); 81 | return id; 82 | } 83 | 84 | public static void DismountVirtualHardDisk(string VHDPath) 85 | { 86 | Logging.Log($"Dismounting {VHDPath}..."); 87 | VHDUtils.UnmountVHD(VHDPath); 88 | } 89 | 90 | public static string GetVirtualHardDiskLetterFromDiskID(string DiskId) 91 | { 92 | string TVHDLetter = null; 93 | Process proc = new() 94 | { 95 | StartInfo = new ProcessStartInfo("powershell.exe", $@"-command ""(Get-Partition -DiskNumber {DiskId} | Where {{$_.DriveLetter}}).DriveLetter""") 96 | { 97 | UseShellExecute = false, 98 | RedirectStandardOutput = true, 99 | CreateNoWindow = true 100 | } 101 | }; 102 | _ = proc.Start(); 103 | while (!proc.StandardOutput.EndOfStream) 104 | { 105 | string line = proc.StandardOutput.ReadLine(); 106 | Logging.Log($"VHD mounted at: {line}"); 107 | TVHDLetter = $"{line}:"; 108 | } 109 | proc.WaitForExit(); 110 | return TVHDLetter; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP8350MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SM_LAHAINA.MTP.* 6 | Qualcomm.SMP_LAHAINA.MTP.* 7 | 8 | QCOM_MTP_8350_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp888.xml 10 | 238353907712 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 0b91fdde-4d58-0d66-900b-db9500404fb9 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 0348e2c8-d32a-7678-3ed3-cd1cff6bef65 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 36c64d19-3908-cd82-e31d-7f06f5d2f61c 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | a9b8f475-bb90-7fc0-c0b7-867dea3cd286 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | d5e013ea-86fd-498e-95eb-061cbd7e8533 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | d504d6db-fa92-4853-b59e-c7f292e2ea19 55 | 7c0d112f-f4c4-94cf-01a6-5d834ce486e6 56 | 8712 57 | 39431 58 | 1125899906842624 59 | recovery_a 60 | 61 | 62 | 352b8083-9c0c-4bed-9917-cb5eabd64d41 63 | 292602e7-2384-a0a2-6c20-218fa734f08f 64 | 39432 65 | 70151 66 | 0 67 | recovery_b 68 | 69 | 70 | 89a12de1-5e41-4cb3-8b4c-b1441eb5da38 71 | 1eae51cc-5558-47c1-4076-bd1a005fcd8a 72 | 70152 73 | 1643015 74 | 0 75 | super 76 | 77 | 78 | 1344859d-3a6a-4c14-a316-9e696b3a5400 79 | 74f716bb-a2ea-a811-6dc0-a4aea4761ffa 80 | 1643016 81 | 1643031 82 | 1154047404513689600 83 | vbmeta_system_a 84 | 85 | 86 | fe3ab853-5b66-4d4a-bf85-8d90af1c2c4a 87 | 0ff59d4f-06d0-6b4a-91e6-367bf3578ec1 88 | 1643032 89 | 1643047 90 | 1152921504606846976 91 | vbmeta_system_b 92 | 93 | 94 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 95 | e3e2ab4e-7827-098c-4af3-1ec7e055ca3e 96 | 1643048 97 | 1647143 98 | 0 99 | metadata 100 | 101 | 102 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 103 | 9e64e187-de4d-b5e7-a7ef-d100402cbaa9 104 | 1647144 105 | 2169071 106 | 0 107 | rawdump 108 | 109 | 110 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 111 | cb12cb7a-f2db-4128-b15d-2e5cc87b17da 112 | 2169072 113 | 2169071 114 | 0 115 | userdata 116 | 117 | 118 | MaximizedForWindows 119 | 4294967296 120 | efa6243a-085f-e745-f2ce-54d39ef34351 121 | -------------------------------------------------------------------------------- /PartitionOffsetsHelperTool/DeviceProfiles/Constants.cs: -------------------------------------------------------------------------------- 1 | using PartitionOffsetsHelperTool.GPT; 2 | using System; 3 | 4 | namespace PartitionOffsetsHelperTool.DeviceProfiles 5 | { 6 | internal static class Constants 7 | { 8 | // OEMEP DV UFS LUN 0 Partition Layout 9 | internal static readonly GPTPartition[] OEMEP_UFS_LUN_0_PARTITIONS = 10 | [ 11 | new() 12 | { 13 | TypeGUID = new Guid("2c86e742-745e-4fdd-bfd8-b6a7ac638772"), 14 | UID = new Guid("3e20174c-e289-a56a-39e7-2740b0043d24"), 15 | FirstLBA = 6, 16 | LastLBA = 7, 17 | Attributes = 0, 18 | Name = "ssd" 19 | }, 20 | new() 21 | { 22 | TypeGUID = new Guid("6c95e238-e343-4ba8-b489-8681ed22ad0b"), 23 | UID = new Guid("3c077ac9-fe70-fb01-9fda-3e03153145ea"), 24 | FirstLBA = 8, 25 | LastLBA = 8199, 26 | Attributes = 0, 27 | Name = "persist" 28 | }, 29 | new() 30 | { 31 | TypeGUID = new Guid("988a98c9-2910-4123-aaec-1cf6b1bc28f9"), 32 | UID = new Guid("b7f39878-935d-ed4b-ead8-48b159a31e04"), 33 | FirstLBA = 8200, 34 | LastLBA = 12295, 35 | Attributes = 0, 36 | Name = "metadata" 37 | }, 38 | new() 39 | { 40 | TypeGUID = new Guid("91b72d4d-71e0-4cbf-9b8e-236381cff17a"), 41 | UID = new Guid("04489c96-ae78-c997-efbf-1bc9909cd1ca"), 42 | FirstLBA = 12296, 43 | LastLBA = 12423, 44 | Attributes = 0, 45 | Name = "frp" 46 | }, 47 | new() 48 | { 49 | TypeGUID = new Guid("82acc91f-357c-4a68-9c8f-689e1b1a23a1"), 50 | UID = new Guid("b2ebcd63-842b-f5ff-bdf6-f630f7148b1f"), 51 | FirstLBA = 12424, 52 | LastLBA = 12679, 53 | Attributes = 0, 54 | Name = "misc" 55 | }, 56 | new() 57 | { 58 | TypeGUID = new Guid("1b81e7e6-f50d-419b-a739-2aeef8da3335"), 59 | UID = new Guid("e24f3f91-ed89-c235-d6b4-afada6edb8b7"), 60 | FirstLBA = 12680, 61 | LastLBA = 12679, 62 | Attributes = 0, 63 | Name = "userdata" 64 | } 65 | ]; 66 | 67 | // OEMZE MP UFS LUN 0 Partition Layout 68 | internal static readonly GPTPartition[] OEMZE_UFS_LUN_0_PARTITIONS = 69 | [ 70 | new() 71 | { 72 | TypeGUID = new Guid("2c86e742-745e-4fdd-bfd8-b6a7ac638772"), 73 | UID = new Guid("dd334fea-6336-1cfc-9b54-625a4f119d3b"), 74 | FirstLBA = 6, 75 | LastLBA = 7, 76 | Attributes = 0, 77 | Name = "ssd" 78 | }, 79 | new() 80 | { 81 | TypeGUID = new Guid("6c95e238-e343-4ba8-b489-8681ed22ad0b"), 82 | UID = new Guid("9c508206-a952-e02d-73dd-25b08eda76e4"), 83 | FirstLBA = 8, 84 | LastLBA = 8199, 85 | Attributes = 0, 86 | Name = "persist" 87 | }, 88 | new() 89 | { 90 | TypeGUID = new Guid("988a98c9-2910-4123-aaec-1cf6b1bc28f9"), 91 | UID = new Guid("5e514cb8-1151-c29c-830f-5bf399b40c74"), 92 | FirstLBA = 8200, 93 | LastLBA = 12295, 94 | Attributes = 0, 95 | Name = "metadata" 96 | }, 97 | new() 98 | { 99 | TypeGUID = new Guid("91b72d4d-71e0-4cbf-9b8e-236381cff17a"), 100 | UID = new Guid("dd11345e-4c1f-99ee-afd0-e55e6ecc92d6"), 101 | FirstLBA = 12296, 102 | LastLBA = 12423, 103 | Attributes = 0, 104 | Name = "frp" 105 | }, 106 | new() 107 | { 108 | TypeGUID = new Guid("82acc91f-357c-4a68-9c8f-689e1b1a23a1"), 109 | UID = new Guid("035e02e0-4bb9-06ce-4851-a1ec88834507"), 110 | FirstLBA = 12424, 111 | LastLBA = 12679, 112 | Attributes = 0, 113 | Name = "misc" 114 | }, 115 | new() 116 | { 117 | TypeGUID = new Guid("66c9b323-f7fc-48b6-bf96-6f32e335a428"), 118 | UID = new Guid("68733ebb-ef36-f8ca-11e9-893ace2e6585"), 119 | FirstLBA = 12680, 120 | LastLBA = 89479, 121 | Attributes = 0, 122 | Name = "rawdump" 123 | }, 124 | new() 125 | { 126 | TypeGUID = new Guid("21adb864-c9e7-4c76-be68-568e20c58439"), 127 | UID = new Guid("d296e468-eba2-dfe6-23d5-3b5cb3a853d9"), 128 | FirstLBA = 89480, 129 | LastLBA = 97835, 130 | Attributes = 0, 131 | Name = "vm-data" 132 | }, 133 | new() 134 | { 135 | TypeGUID = new Guid("1b81e7e6-f50d-419b-a739-2aeef8da3335"), 136 | UID = new Guid("411d7753-d116-25ee-ca31-6436766e9580"), 137 | FirstLBA = 97836, 138 | LastLBA = 97835, 139 | Attributes = 0, 140 | Name = "userdata" 141 | } 142 | ]; 143 | } 144 | } -------------------------------------------------------------------------------- /FirmwareGen/DeviceProfiles/MTP8250MaximizedForWindows.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Qualcomm.SM_KONA.MTP.* 6 | Qualcomm.SMP_KONA.MTP.* 7 | 8 | QCOM_MTP_8250_MaximizedForWindows.ffu 9 | \definitions\Desktop\ARM64\Internal\mtp865.xml 10 | 110394081280 11 | 4096 12 | 13 | 14 | 2c86e742-745e-4fdd-bfd8-b6a7ac638772 15 | 56cf17c9-80f8-983b-144c-d11d89eeb732 16 | 6 17 | 7 18 | 0 19 | ssd 20 | 21 | 22 | 6c95e238-e343-4ba8-b489-8681ed22ad0b 23 | 4059a1fb-295d-20e9-de0d-166b7d7f5caf 24 | 8 25 | 8199 26 | 0 27 | persist 28 | 29 | 30 | 82acc91f-357c-4a68-9c8f-689e1b1a23a1 31 | 7f864171-3919-5e40-5776-f18466a80985 32 | 8200 33 | 8455 34 | 0 35 | misc 36 | 37 | 38 | de7d4029-0f5b-41c8-ae7e-f6c023a02b33 39 | e90d105e-d54d-73d6-5ba6-8777e1207853 40 | 8456 41 | 8583 42 | 0 43 | keystore 44 | 45 | 46 | 91b72d4d-71e0-4cbf-9b8e-236381cff17a 47 | 6b69be73-6fec-8e1f-1658-95ae6cda3583 48 | 8584 49 | 8711 50 | 0 51 | frp 52 | 53 | 54 | 89a12de1-5e41-4cb3-8b4c-b1441eb5da38 55 | 7385292f-f0d7-a6d7-ab3b-bab7f0bb82a2 56 | 8712 57 | 3154439 58 | 0 59 | super 60 | 61 | 62 | d504d6db-fa92-4853-b59e-c7f292e2ea19 63 | 8f9af1c5-f24d-b877-0f9a-49142d2ba2de 64 | 3154440 65 | 3180039 66 | 1125899906842624 67 | recovery_a 68 | 69 | 70 | 352b8083-9c0c-4bed-9917-cb5eabd64d41 71 | 997cc5bf-2b88-47df-4b16-6dd32f6ab84a 72 | 3180040 73 | 3205639 74 | 0 75 | recovery_b 76 | 77 | 78 | 1344859d-3a6a-4c14-a316-9e696b3a5400 79 | 13e8dba6-2ef0-499b-8bdb-d28982388dba 80 | 3205640 81 | 3205655 82 | 1154047404513689600 83 | vbmeta_system_a 84 | 85 | 86 | fe3ab853-5b66-4d4a-bf85-8d90af1c2c4a 87 | d4f02047-b672-51c0-c448-83a26f537e04 88 | 3205656 89 | 3205671 90 | 1152921504606846976 91 | vbmeta_system_b 92 | 93 | 94 | 988a98c9-2910-4123-aaec-1cf6b1bc28f9 95 | 132ef315-6944-a979-c1b2-5eb0879a927d 96 | 3205672 97 | 3209767 98 | 0 99 | metadata 100 | 101 | 102 | c5f681cc-9742-4641-be4e-976eeb638eee 103 | bede0f2a-7be5-c669-2f83-74c6df382410 104 | 3209768 105 | 3242535 106 | 1125899906842624 107 | vm-system_a 108 | 109 | 110 | 77036cd4-03d5-42bb-8ed1-37e5a88baa34 111 | 34ed13d1-5617-b3ff-d0a9-a87f6d4f3e56 112 | 3242536 113 | 3275303 114 | 0 115 | vm-system_b 116 | 117 | 118 | 66c9b323-f7fc-48b6-bf96-6f32e335a428 119 | 4e218584-b7c1-c04b-00c3-8ef0bb225e2b 120 | 3275304 121 | 3308071 122 | 0 123 | rawdump 124 | 125 | 126 | 1b81e7e6-f50d-419b-a739-2aeef8da3335 127 | 24b62523-8a13-2b76-31c6-237173072557 128 | 3308072 129 | 3308071 130 | 0 131 | userdata 132 | 133 | 134 | MaximizedForWindows 135 | 4294967296 136 | efa6243a-085f-e745-f2ce-54d39ef34351 137 | -------------------------------------------------------------------------------- /FirmwareGen/VirtualDisks/VHDUtils.cs: -------------------------------------------------------------------------------- 1 | using DiscUtils.Streams; 2 | using DiscUtils.Vhdx; 3 | using System; 4 | using System.IO; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | 8 | namespace FirmwareGen.VirtualDisks 9 | { 10 | internal static partial class VHDUtils 11 | { 12 | /// 13 | /// Mounts FFU or VHD files on a target system. 14 | /// 15 | /// A path as a string to a FFU or VHD file to mount on the current system. 16 | /// If set to true, the function will mount a FFU image and not a VHD image. 17 | /// 18 | /// A string array containing for the first parameter the full path to the junction linked to the image, and for 19 | /// the second parameter the Physical disk id path. 20 | /// 21 | public static string MountVHD(string vhdfile, bool readOnly) 22 | { 23 | OPEN_VIRTUAL_DISK_PARAMETERS openParameters = new() 24 | { 25 | Version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1 26 | }; 27 | openParameters.Version1.RWDepth = NativeMethods.OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT; 28 | 29 | VIRTUAL_STORAGE_TYPE openStorageType = new() 30 | { 31 | DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN, 32 | VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN 33 | }; 34 | 35 | ATTACH_VIRTUAL_DISK_PARAMETERS attachParameters = new() 36 | { 37 | Version = ATTACH_VIRTUAL_DISK_VERSION.ATTACH_VIRTUAL_DISK_VERSION_1 38 | }; 39 | 40 | IntPtr handle = IntPtr.Zero; 41 | 42 | int openResult = NativeMethods.OpenVirtualDisk(ref openStorageType, vhdfile, VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref openParameters, ref handle); 43 | 44 | if (openResult != NativeMethods.ERROR_SUCCESS) 45 | { 46 | throw new InvalidOperationException($"Native error {openResult}."); 47 | } 48 | 49 | ATTACH_VIRTUAL_DISK_FLAG flags = ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME; 50 | 51 | if (readOnly) 52 | { 53 | flags |= ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY; 54 | } 55 | 56 | int attachResult = NativeMethods.AttachVirtualDisk(handle, IntPtr.Zero, flags, 0, ref attachParameters, IntPtr.Zero); 57 | 58 | if (attachResult != NativeMethods.ERROR_SUCCESS) 59 | { 60 | throw new InvalidOperationException($"Native error {attachResult}."); 61 | } 62 | 63 | int bufferSize = 260; 64 | StringBuilder vhdPhysicalPath = new(bufferSize); 65 | 66 | if (NativeMethods.GetVirtualDiskPhysicalPath(handle, ref bufferSize, vhdPhysicalPath) != NativeMethods.ERROR_SUCCESS) 67 | { 68 | throw new InvalidOperationException($"Native error {attachResult}."); 69 | } 70 | 71 | _ = NativeMethods.CloseHandle(handle); 72 | 73 | return VHDRegex().Match(vhdPhysicalPath.ToString()).Value; 74 | } 75 | 76 | public static void UnmountVHD(string vhdfile) 77 | { 78 | OPEN_VIRTUAL_DISK_PARAMETERS openParameters = new() 79 | { 80 | Version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1 81 | }; 82 | openParameters.Version1.RWDepth = NativeMethods.OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT; 83 | 84 | VIRTUAL_STORAGE_TYPE openStorageType = new() 85 | { 86 | DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN, 87 | VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN 88 | }; 89 | 90 | IntPtr handle = IntPtr.Zero; 91 | 92 | int openResult = NativeMethods.OpenVirtualDisk(ref openStorageType, vhdfile, VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref openParameters, ref handle); 93 | 94 | if (openResult != NativeMethods.ERROR_SUCCESS) 95 | { 96 | throw new InvalidOperationException($"Native error {openResult}."); 97 | } 98 | 99 | int dettachResult = NativeMethods.DetachVirtualDisk(handle, DETACH_VIRTUAL_DISK_FLAG.DETACH_VIRTUAL_DISK_FLAG_NONE, 0); 100 | 101 | if (dettachResult != NativeMethods.ERROR_SUCCESS) 102 | { 103 | throw new InvalidOperationException($"Native error {dettachResult}."); 104 | } 105 | 106 | _ = NativeMethods.CloseHandle(handle); 107 | } 108 | 109 | public static void CreateVHDX(string vhdfile, uint SectorSize, ulong DiskSize) 110 | { 111 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(Disk).Assembly); 112 | 113 | using Stream fs = new FileStream(vhdfile, FileMode.CreateNew, FileAccess.ReadWrite); 114 | using DiscUtils.VirtualDisk outDisk = Disk.InitializeDynamic(fs, Ownership.None, (long)DiskSize, DiscUtils.Geometry.FromCapacity((long)DiskSize, (int)SectorSize)); 115 | } 116 | 117 | /// 118 | /// \d+ 119 | /// \d matches a digit (equivalent to [0-9]) 120 | /// + matches the previous token between one and unlimited times, as many times as possible, giving back as needed (greedy) 121 | /// 122 | /// 123 | [GeneratedRegex(@"\d+")] 124 | private static partial Regex VHDRegex(); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /GPTFixer/Img2Ffu/GPT/GPT.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the "Software"), 5 | // to deal in the Software without restriction, including without limitation 6 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | // and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | // DEALINGS IN THE SOFTWARE. 20 | 21 | using GPTFixer.Img2Ffu.Helpers; 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | 26 | namespace GPTFixer.Img2Ffu 27 | { 28 | public partial class GPT 29 | { 30 | public byte[] GPTBuffer; 31 | private readonly uint HeaderOffset; 32 | private readonly uint HeaderSize; 33 | private uint TableOffset; 34 | private uint TableSize; 35 | private readonly uint PartitionEntrySize; 36 | private readonly uint MaxPartitions; 37 | internal ulong FirstUsableSector; 38 | internal ulong LastUsableSector; 39 | internal bool HasChanged = false; 40 | public readonly Guid DiskGuid; 41 | 42 | public List Partitions = []; 43 | 44 | internal static uint GetGPTSize(byte[] GPTBuffer, uint SectorSize) 45 | { 46 | uint? TempHeaderOffset = ByteOperations.FindAscii(GPTBuffer, "EFI PART") ?? throw new Exception("Bad GPT"); 47 | 48 | uint HeaderOffset = (uint)TempHeaderOffset; 49 | uint TableOffset = HeaderOffset + SectorSize; 50 | uint MaxPartitions = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x50); 51 | uint PartitionEntrySize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x54); 52 | uint TableSize = MaxPartitions * PartitionEntrySize; 53 | 54 | return TableOffset + TableSize; 55 | } 56 | 57 | internal GPT(byte[] GPTBuffer, uint SectorSize) 58 | { 59 | this.GPTBuffer = GPTBuffer; 60 | uint? TempHeaderOffset = ByteOperations.FindAscii(GPTBuffer, "EFI PART") ?? throw new Exception("Bad GPT"); 61 | 62 | HeaderOffset = (uint)TempHeaderOffset; 63 | HeaderSize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x0C); 64 | TableOffset = HeaderOffset + SectorSize; 65 | FirstUsableSector = ByteOperations.ReadUInt64(GPTBuffer, HeaderOffset + 0x28); 66 | LastUsableSector = ByteOperations.ReadUInt64(GPTBuffer, HeaderOffset + 0x30); 67 | DiskGuid = ByteOperations.ReadGuid(GPTBuffer, HeaderOffset + 0x38); 68 | MaxPartitions = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x50); 69 | PartitionEntrySize = ByteOperations.ReadUInt32(GPTBuffer, HeaderOffset + 0x54); 70 | TableSize = MaxPartitions * PartitionEntrySize; 71 | if ((TableOffset + TableSize) > GPTBuffer.Length) 72 | { 73 | throw new Exception("Bad GPT"); 74 | } 75 | 76 | uint PartitionOffset = TableOffset; 77 | 78 | while (PartitionOffset < (TableOffset + TableSize)) 79 | { 80 | string Name = ByteOperations.ReadUnicodeString(GPTBuffer, PartitionOffset + 0x38, 0x48).TrimEnd([(char)0, ' ']); 81 | if (Name.Length == 0) 82 | { 83 | break; 84 | } 85 | 86 | Partition CurrentPartition = new() 87 | { 88 | Name = Name, 89 | FirstSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x20), 90 | LastSector = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x28), 91 | PartitionTypeGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x00), 92 | PartitionGuid = ByteOperations.ReadGuid(GPTBuffer, PartitionOffset + 0x10), 93 | Attributes = ByteOperations.ReadUInt64(GPTBuffer, PartitionOffset + 0x30) 94 | }; 95 | Partitions.Add(CurrentPartition); 96 | PartitionOffset += PartitionEntrySize; 97 | } 98 | 99 | HasChanged = false; 100 | } 101 | 102 | internal Partition GetPartition(string Name) 103 | { 104 | return Partitions.Where(p => string.Compare(p.Name, Name, true) == 0).FirstOrDefault(); 105 | } 106 | 107 | internal byte[] Rebuild(uint SectorSize) 108 | { 109 | if (GPTBuffer == null) 110 | { 111 | TableSize = 0x21 * SectorSize; 112 | TableOffset = 0; 113 | GPTBuffer = new byte[TableSize]; 114 | } 115 | else 116 | { 117 | Array.Clear(GPTBuffer, (int)TableOffset, (int)TableSize); 118 | } 119 | 120 | uint PartitionOffset = TableOffset; 121 | foreach (Partition CurrentPartition in Partitions) 122 | { 123 | ByteOperations.WriteGuid(GPTBuffer, PartitionOffset + 0x00, CurrentPartition.PartitionTypeGuid); 124 | ByteOperations.WriteGuid(GPTBuffer, PartitionOffset + 0x10, CurrentPartition.PartitionGuid); 125 | ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x20, CurrentPartition.FirstSector); 126 | ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x28, CurrentPartition.LastSector); 127 | ByteOperations.WriteUInt64(GPTBuffer, PartitionOffset + 0x30, CurrentPartition.Attributes); 128 | ByteOperations.WriteUnicodeString(GPTBuffer, PartitionOffset + 0x38, CurrentPartition.Name, 0x48); 129 | 130 | PartitionOffset += PartitionEntrySize; 131 | } 132 | 133 | ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x58, ByteOperations.CRC32(GPTBuffer, TableOffset, TableSize)); 134 | ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x10, 0); 135 | ByteOperations.WriteUInt32(GPTBuffer, HeaderOffset + 0x10, ByteOperations.CRC32(GPTBuffer, HeaderOffset, HeaderSize)); 136 | 137 | return GPTBuffer; 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /GPTFixer/FirmwareGen/GPT/GPTUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace GPTFixer.FirmwareGen.GPT 6 | { 7 | internal class GPTUtils 8 | { 9 | internal static byte[] MakeGPT(ulong DiskSize, ulong SectorSize, GPTPartition[] DefaultPartitionTable, Guid DiskGuid, bool IsBackupGPT = false) 10 | { 11 | ulong FirstLBA = 1; 12 | ulong LastLBA = DiskSize / SectorSize - 1; 13 | 14 | ulong PartitionArrayLBACount = 4; 15 | 16 | if ((ulong)DefaultPartitionTable.Length * 128 > PartitionArrayLBACount * SectorSize) 17 | { 18 | throw new Exception("Unsupported Configuration, too many partitions to fit. File an issue"); 19 | } 20 | 21 | return MakeGPT(FirstLBA, LastLBA, SectorSize, DefaultPartitionTable, DiskGuid, PartitionArrayLBACount: PartitionArrayLBACount, IsBackupGPT: IsBackupGPT); 22 | } 23 | 24 | private static byte[] MakeGPT(ulong FirstLBA, ulong LastLBA, ulong SectorSize, GPTPartition[] Partitions, Guid DiskGuid, ulong PartitionArrayLBACount = 4, bool IsBackupGPT = false) 25 | { 26 | // ------------------- 27 | // 0: Reserved/MBR 28 | // ------------------- 29 | // 1: GPT Header 30 | // ------------------- 31 | // 2: Partition Table 32 | // 3: Partition Table 33 | // 4: Partition Table 34 | // 5: Partition Table 35 | // ------------------- 36 | // 6: First Usable LBA 37 | // ... 38 | // -5: Last Usable LBA 39 | // ------------------- 40 | // -4: Partition Table 41 | // -3: Partition Table 42 | // -2: Partition Table 43 | // -1: Partition Table 44 | // ------------------- 45 | // -0: Backup GPT Header 46 | // ------------------- 47 | 48 | ulong TotalGPTLBACount = 1 /* GPT Header */ + PartitionArrayLBACount /* Partition Table */; 49 | 50 | ulong FirstUsableLBA = FirstLBA + TotalGPTLBACount; 51 | ulong LastUsableLBA = LastLBA - TotalGPTLBACount; 52 | 53 | uint PartitionEntryCount; 54 | 55 | if ((uint)Partitions.Length > 128) 56 | { 57 | throw new Exception("Unsupported Configuration, too many partitions than supported, please file an issue."); 58 | } 59 | else 60 | { 61 | PartitionEntryCount = (uint)Partitions.Length > 64 ? 128 : (uint)Partitions.Length > 32 ? 64 : (uint)32; 62 | } 63 | 64 | GPTHeader Header = new() 65 | { 66 | Signature = "EFI PART", 67 | Revision = 0x10000, 68 | Size = 92, 69 | CRC32 = 0, 70 | Reserved = 0, 71 | CurrentLBA = IsBackupGPT ? LastLBA : FirstLBA, 72 | BackupLBA = IsBackupGPT ? FirstLBA : LastLBA, 73 | FirstUsableLBA = FirstUsableLBA, 74 | LastUsableLBA = LastUsableLBA, 75 | DiskGUID = DiskGuid, 76 | PartitionArrayLBA = IsBackupGPT ? LastLBA - TotalGPTLBACount + 1 : FirstLBA + 1, 77 | PartitionEntryCount = PartitionEntryCount, 78 | PartitionEntrySize = 128, 79 | PartitionArrayCRC32 = 0 80 | }; 81 | 82 | List PartitionTableBuffer = []; 83 | for (int i = 0; i < Partitions.Length; i++) 84 | { 85 | PartitionTableBuffer.AddRange(Partitions[i].TypeGUID.ToByteArray()); 86 | PartitionTableBuffer.AddRange(Partitions[i].UID.ToByteArray()); 87 | PartitionTableBuffer.AddRange(BitConverter.GetBytes(Partitions[i].FirstLBA)); 88 | PartitionTableBuffer.AddRange(BitConverter.GetBytes(Partitions[i].LastLBA)); 89 | PartitionTableBuffer.AddRange(BitConverter.GetBytes(Partitions[i].Attributes)); 90 | PartitionTableBuffer.AddRange(Encoding.Unicode.GetBytes(Partitions[i].Name)); 91 | PartitionTableBuffer.AddRange(new byte[Header.PartitionEntrySize * (ulong)(long)(i + 1) - (ulong)(long)PartitionTableBuffer.Count]); 92 | } 93 | PartitionTableBuffer.AddRange(new byte[Header.PartitionEntrySize * Header.PartitionEntryCount - (ulong)(long)PartitionTableBuffer.Count]); 94 | 95 | uint PartitionTableCRC32 = CRC32.Compute([.. PartitionTableBuffer], 0, (uint)PartitionTableBuffer.Count); 96 | Header.PartitionArrayCRC32 = PartitionTableCRC32; 97 | 98 | byte[] HeaderBuffer = 99 | [ 100 | .. Encoding.ASCII.GetBytes(Header.Signature), 101 | .. BitConverter.GetBytes(Header.Revision), 102 | .. BitConverter.GetBytes(Header.Size), 103 | .. BitConverter.GetBytes(Header.CRC32), 104 | .. BitConverter.GetBytes(Header.Reserved), 105 | .. BitConverter.GetBytes(Header.CurrentLBA), 106 | .. BitConverter.GetBytes(Header.BackupLBA), 107 | .. BitConverter.GetBytes(Header.FirstUsableLBA), 108 | .. BitConverter.GetBytes(Header.LastUsableLBA), 109 | .. Header.DiskGUID.ToByteArray(), 110 | .. BitConverter.GetBytes(Header.PartitionArrayLBA), 111 | .. BitConverter.GetBytes(Header.PartitionEntryCount), 112 | .. BitConverter.GetBytes(Header.PartitionEntrySize), 113 | .. BitConverter.GetBytes(Header.PartitionArrayCRC32), 114 | ]; 115 | 116 | Header.CRC32 = CRC32.Compute(HeaderBuffer, 0, (uint)HeaderBuffer.Length); 117 | byte[] bytes = BitConverter.GetBytes(Header.CRC32); 118 | 119 | HeaderBuffer[16] = bytes[0]; 120 | HeaderBuffer[17] = bytes[1]; 121 | HeaderBuffer[18] = bytes[2]; 122 | HeaderBuffer[19] = bytes[3]; 123 | 124 | byte[] HeaderPaddingBuffer = new byte[(int)(SectorSize - (uint)HeaderBuffer.Length)]; 125 | byte[] PartitionTablePaddingBuffer = new byte[(int)(PartitionArrayLBACount * SectorSize - (uint)PartitionTableBuffer.Count)]; 126 | 127 | List GPTBuffer = []; 128 | if (IsBackupGPT) 129 | { 130 | GPTBuffer.AddRange(PartitionTableBuffer); 131 | GPTBuffer.AddRange(PartitionTablePaddingBuffer); 132 | 133 | GPTBuffer.AddRange(HeaderBuffer); 134 | GPTBuffer.AddRange(HeaderPaddingBuffer); 135 | } 136 | else 137 | { 138 | GPTBuffer.AddRange(HeaderBuffer); 139 | GPTBuffer.AddRange(HeaderPaddingBuffer); 140 | 141 | GPTBuffer.AddRange(PartitionTableBuffer); 142 | GPTBuffer.AddRange(PartitionTablePaddingBuffer); 143 | } 144 | 145 | return [.. GPTBuffer]; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /GPTFixer/Program.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | using DiscUtils; 3 | using GPTFixer.FirmwareGen; 4 | using GPTFixer.Img2Ffu; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | 10 | namespace GPTFixer 11 | { 12 | internal class Program 13 | { 14 | private static (Stream InputStream, VirtualDisk? InputDisk) OpenInput(string InputFile) 15 | { 16 | Stream InputStream; 17 | VirtualDisk? InputDisk = null; 18 | 19 | if (File.Exists(InputFile) && Path.GetExtension(InputFile).Equals(".vhd", StringComparison.InvariantCultureIgnoreCase)) 20 | { 21 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhd.Disk).Assembly); 22 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhdx.Disk).Assembly); 23 | InputDisk = VirtualDisk.OpenDisk(InputFile, FileAccess.ReadWrite); 24 | InputStream = InputDisk.Content; 25 | } 26 | else if (File.Exists(InputFile) && Path.GetExtension(InputFile).Equals(".vhdx", StringComparison.InvariantCultureIgnoreCase)) 27 | { 28 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhd.Disk).Assembly); 29 | DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(DiscUtils.Vhdx.Disk).Assembly); 30 | InputDisk = VirtualDisk.OpenDisk(InputFile, FileAccess.ReadWrite); 31 | InputStream = InputDisk.Content; 32 | } 33 | else if (File.Exists(InputFile)) 34 | { 35 | InputStream = new FileStream(InputFile, FileMode.Open, FileAccess.ReadWrite); 36 | } 37 | else 38 | { 39 | Console.WriteLine("Unknown input specified"); 40 | throw new Exception($"Unknown Input Specified: {InputFile}"); 41 | } 42 | 43 | return (InputStream, InputDisk); 44 | } 45 | 46 | private static GPT GetGPT(Stream stream, uint sectorSize) 47 | { 48 | uint BlockSize = 16384; 49 | 50 | byte[] GPTBuffer = new byte[BlockSize]; 51 | stream.Seek(0, SeekOrigin.Begin); 52 | _ = stream.Read(GPTBuffer); 53 | 54 | uint requiredGPTBufferSize = Img2Ffu.GPT.GetGPTSize(GPTBuffer, sectorSize); 55 | if (BlockSize < requiredGPTBufferSize) 56 | { 57 | 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"; 58 | Console.WriteLine(errorMessage); 59 | //throw new Exception(errorMessage); 60 | BlockSize = requiredGPTBufferSize; 61 | GPTBuffer = new byte[BlockSize]; 62 | stream.Seek(0, SeekOrigin.Begin); 63 | _ = stream.Read(GPTBuffer); 64 | } 65 | 66 | uint sectorsInABlock = BlockSize / sectorSize; 67 | 68 | GPT GPT = new(GPTBuffer, sectorSize); 69 | 70 | IOrderedEnumerable orderedGPTPartitions = GPT.Partitions.OrderBy(x => x.FirstSector); 71 | 72 | if (BlockSize > requiredGPTBufferSize && orderedGPTPartitions.Any(x => x.FirstSector < sectorsInABlock)) 73 | { 74 | GPT.Partition conflictingPartition = orderedGPTPartitions.First(x => x.FirstSector < sectorsInABlock); 75 | 76 | 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}"; 77 | Console.WriteLine(errorMessage); 78 | //throw new Exception(errorMessage); 79 | } 80 | 81 | return GPT; 82 | } 83 | 84 | static void Main(string[] args) 85 | { 86 | Console.WriteLine("GPTFixer"); 87 | Console.WriteLine("Copyright (c) 2019-2024, Gustave Monce - gus33000.me - @gus33000"); 88 | Console.WriteLine("Released under the MIT license at github.com/WOA-Project/FirmwareGen"); 89 | Console.WriteLine(""); 90 | 91 | try 92 | { 93 | _ = Parser.Default.ParseArguments(args).WithParsed(Program.FixDisk); 94 | } 95 | catch (Exception ex) 96 | { 97 | Console.WriteLine("Something happened."); 98 | Console.WriteLine(ex.Message); 99 | Console.WriteLine(ex.StackTrace); 100 | Environment.Exit(1); 101 | } 102 | } 103 | 104 | private static void FixDisk(Options args) 105 | { 106 | string InputFile = args.InputFile; 107 | 108 | Console.WriteLine("Opening input file..."); 109 | (Stream InputStream, VirtualDisk? InputDisk) = OpenInput(InputFile); 110 | 111 | uint SectorSize = args.SectorSize; 112 | 113 | Console.WriteLine("Getting GPT from input..."); 114 | GPT GPT = GetGPT(InputStream, SectorSize); 115 | 116 | Console.WriteLine("Constructing new partition list..."); 117 | List gptPartitions = []; 118 | 119 | foreach (GPT.Partition partition in GPT.Partitions) 120 | { 121 | string Name = partition.Name; 122 | 123 | if (Name == "BS_EFIESP") 124 | { 125 | Name = "esp"; 126 | } 127 | else if (Name == "OSPool") 128 | { 129 | Name = "win"; 130 | } 131 | 132 | FirmwareGen.GPT.GPTPartition gptPartition = new() 133 | { 134 | Attributes = partition.Attributes, 135 | FirstLBA = partition.FirstSector, 136 | LastLBA = partition.LastSector, 137 | Name = Name, 138 | UID = partition.PartitionGuid, 139 | TypeGUID = partition.PartitionTypeGuid 140 | }; 141 | 142 | gptPartitions.Add(gptPartition); 143 | } 144 | 145 | ulong TotalDiskSize = (ulong)InputStream.Length; 146 | Console.WriteLine($"Total Disk Size {TotalDiskSize:X}"); 147 | 148 | Console.WriteLine("Constructing Primary GPT binary..."); 149 | byte[] PrimaryGPT = CommonLogic.GetPrimaryGPT(TotalDiskSize, SectorSize, GPT.DiskGuid, [.. gptPartitions]); 150 | 151 | Console.WriteLine("Constructing Backup GPT binary..."); 152 | byte[] BackupGPT = CommonLogic.GetBackupGPT(TotalDiskSize, SectorSize, GPT.DiskGuid, [.. gptPartitions]); 153 | 154 | Console.WriteLine("Writing Primary GPT binary..."); 155 | InputStream.Seek(0, SeekOrigin.Begin); 156 | InputStream.Write(PrimaryGPT); 157 | 158 | Console.WriteLine("Writing Backup GPT binary..."); 159 | 160 | InputStream.Seek((long)(TotalDiskSize - (ulong)BackupGPT.Length), SeekOrigin.Begin); 161 | InputStream.Write(BackupGPT); 162 | 163 | Console.WriteLine("Closing Input..."); 164 | InputStream.Flush(); 165 | InputDisk?.Dispose(); 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /FirmwareGen.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34407.89 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FirmwareGen", "FirmwareGen\FirmwareGen.csproj", "{85918ACF-6909-45DA-B56D-3D5113B7EA6C}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PartitionOffsetsHelperTool", "PartitionOffsetsHelperTool\PartitionOffsetsHelperTool.csproj", "{AC699AC2-883A-4278-B2A8-F0F693DC8643}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPT2DeviceProfile", "GPT2DeviceProfile\GPT2DeviceProfile.csproj", "{A743AF3C-1D03-4B75-BACE-5F357CD07ADF}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPTFixer", "GPTFixer\GPTFixer.csproj", "{E7C55206-E9D9-B034-483E-4AF14F558837}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|ARM32 = Debug|ARM32 18 | Debug|ARM64 = Debug|ARM64 19 | Debug|x64 = Debug|x64 20 | Debug|x86 = Debug|x86 21 | Release|Any CPU = Release|Any CPU 22 | Release|ARM32 = Release|ARM32 23 | Release|ARM64 = Release|ARM64 24 | Release|x64 = Release|x64 25 | Release|x86 = Release|x86 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|ARM32.ActiveCfg = Debug|Any CPU 31 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|ARM32.Build.0 = Debug|Any CPU 32 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|ARM64.ActiveCfg = Debug|ARM64 33 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|ARM64.Build.0 = Debug|ARM64 34 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|x64.ActiveCfg = Debug|Any CPU 35 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|x64.Build.0 = Debug|Any CPU 36 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|x86.ActiveCfg = Debug|x86 37 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Debug|x86.Build.0 = Debug|x86 38 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|ARM32.ActiveCfg = Release|Any CPU 41 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|ARM32.Build.0 = Release|Any CPU 42 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|ARM64.ActiveCfg = Release|arm64 43 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|ARM64.Build.0 = Release|arm64 44 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|x64.ActiveCfg = Release|x64 45 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|x64.Build.0 = Release|x64 46 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|x86.ActiveCfg = Release|x86 47 | {85918ACF-6909-45DA-B56D-3D5113B7EA6C}.Release|x86.Build.0 = Release|x86 48 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|ARM32.ActiveCfg = Debug|Any CPU 51 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|ARM32.Build.0 = Debug|Any CPU 52 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|ARM64.ActiveCfg = Debug|Any CPU 53 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|ARM64.Build.0 = Debug|Any CPU 54 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|x64.ActiveCfg = Debug|Any CPU 55 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|x64.Build.0 = Debug|Any CPU 56 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|x86.ActiveCfg = Debug|Any CPU 57 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Debug|x86.Build.0 = Debug|Any CPU 58 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|ARM32.ActiveCfg = Release|Any CPU 61 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|ARM32.Build.0 = Release|Any CPU 62 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|ARM64.ActiveCfg = Release|ARM64 63 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|ARM64.Build.0 = Release|ARM64 64 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|x64.ActiveCfg = Release|Any CPU 65 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|x64.Build.0 = Release|Any CPU 66 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|x86.ActiveCfg = Release|Any CPU 67 | {AC699AC2-883A-4278-B2A8-F0F693DC8643}.Release|x86.Build.0 = Release|Any CPU 68 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 69 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|Any CPU.Build.0 = Debug|Any CPU 70 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|ARM32.ActiveCfg = Debug|Any CPU 71 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|ARM32.Build.0 = Debug|Any CPU 72 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|ARM64.ActiveCfg = Debug|Any CPU 73 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|ARM64.Build.0 = Debug|Any CPU 74 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|x64.ActiveCfg = Debug|Any CPU 75 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|x64.Build.0 = Debug|Any CPU 76 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|x86.ActiveCfg = Debug|Any CPU 77 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Debug|x86.Build.0 = Debug|Any CPU 78 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|Any CPU.ActiveCfg = Release|Any CPU 79 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|Any CPU.Build.0 = Release|Any CPU 80 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|ARM32.ActiveCfg = Release|Any CPU 81 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|ARM32.Build.0 = Release|Any CPU 82 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|ARM64.ActiveCfg = Release|Any CPU 83 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|ARM64.Build.0 = Release|Any CPU 84 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|x64.ActiveCfg = Release|Any CPU 85 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|x64.Build.0 = Release|Any CPU 86 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|x86.ActiveCfg = Release|Any CPU 87 | {A743AF3C-1D03-4B75-BACE-5F357CD07ADF}.Release|x86.Build.0 = Release|Any CPU 88 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|Any CPU.ActiveCfg = Debug|x64 89 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|Any CPU.Build.0 = Debug|x64 90 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|ARM32.ActiveCfg = Debug|ARM32 91 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|ARM32.Build.0 = Debug|ARM32 92 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|ARM64.ActiveCfg = Debug|ARM64 93 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|ARM64.Build.0 = Debug|ARM64 94 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|x64.ActiveCfg = Debug|x64 95 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|x64.Build.0 = Debug|x64 96 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|x86.ActiveCfg = Debug|x86 97 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Debug|x86.Build.0 = Debug|x86 98 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|Any CPU.ActiveCfg = Release|x64 99 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|Any CPU.Build.0 = Release|x64 100 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|ARM32.ActiveCfg = Release|ARM32 101 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|ARM32.Build.0 = Release|ARM32 102 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|ARM64.ActiveCfg = Release|ARM64 103 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|ARM64.Build.0 = Release|ARM64 104 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|x64.ActiveCfg = Release|x64 105 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|x64.Build.0 = Release|x64 106 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|x86.ActiveCfg = Release|x86 107 | {E7C55206-E9D9-B034-483E-4AF14F558837}.Release|x86.Build.0 = Release|x86 108 | EndGlobalSection 109 | GlobalSection(SolutionProperties) = preSolution 110 | HideSolutionNode = FALSE 111 | EndGlobalSection 112 | GlobalSection(ExtensibilityGlobals) = postSolution 113 | SolutionGuid = {3797BA97-8D14-4125-97B3-334C91E27977} 114 | EndGlobalSection 115 | EndGlobal 116 | -------------------------------------------------------------------------------- /GPTFixer/Img2Ffu/Helpers/ByteOperations.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the "Software"), 5 | // to deal in the Software without restriction, including without limitation 6 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | // and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | // DEALINGS IN THE SOFTWARE. 20 | 21 | // These functions assume same endianness for the CPU architecture and the raw data it reads from or writes to. 22 | 23 | using System; 24 | 25 | namespace GPTFixer.Img2Ffu.Helpers 26 | { 27 | internal static class ByteOperations 28 | { 29 | internal static string ReadUnicodeString(byte[] ByteArray, uint Offset, uint Length) 30 | { 31 | byte[] Bytes = new byte[Length]; 32 | Buffer.BlockCopy(ByteArray, (int)Offset, Bytes, 0, (int)Length); 33 | return System.Text.Encoding.Unicode.GetString(Bytes); 34 | } 35 | 36 | internal static void WriteAsciiString(byte[] ByteArray, uint Offset, string Text, uint? MaxBufferLength = null) 37 | { 38 | if (MaxBufferLength != null) 39 | { 40 | Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength); 41 | } 42 | 43 | byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(Text); 44 | int WriteLength = TextBytes.Length; 45 | if (WriteLength > MaxBufferLength) 46 | { 47 | WriteLength = (int)MaxBufferLength; 48 | } 49 | 50 | Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength); 51 | } 52 | 53 | internal static void WriteUnicodeString(byte[] ByteArray, uint Offset, string Text, uint? MaxBufferLength = null) 54 | { 55 | if (MaxBufferLength != null) 56 | { 57 | Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength); 58 | } 59 | 60 | byte[] TextBytes = System.Text.Encoding.Unicode.GetBytes(Text); 61 | int WriteLength = TextBytes.Length; 62 | if (WriteLength > MaxBufferLength) 63 | { 64 | WriteLength = (int)MaxBufferLength; 65 | } 66 | 67 | Buffer.BlockCopy(TextBytes, 0, ByteArray, (int)Offset, WriteLength); 68 | } 69 | 70 | internal static uint ReadUInt32(byte[] ByteArray, uint Offset) 71 | { 72 | return BitConverter.ToUInt32(ByteArray, (int)Offset); 73 | } 74 | 75 | internal static void WriteUInt32(byte[] ByteArray, uint Offset, uint Value) 76 | { 77 | Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4); 78 | } 79 | 80 | internal static ulong ReadUInt64(byte[] ByteArray, uint Offset) 81 | { 82 | return BitConverter.ToUInt64(ByteArray, (int)Offset); 83 | } 84 | 85 | internal static void WriteUInt64(byte[] ByteArray, uint Offset, ulong Value) 86 | { 87 | Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8); 88 | } 89 | 90 | internal static Guid ReadGuid(byte[] ByteArray, uint Offset) 91 | { 92 | byte[] GuidBuffer = new byte[0x10]; 93 | Buffer.BlockCopy(ByteArray, (int)Offset, GuidBuffer, 0, 0x10); 94 | return new Guid(GuidBuffer); 95 | } 96 | 97 | internal static void WriteGuid(byte[] ByteArray, uint Offset, Guid Value) 98 | { 99 | Buffer.BlockCopy(Value.ToByteArray(), 0, ByteArray, (int)Offset, 0x10); 100 | } 101 | 102 | internal static uint? FindAscii(byte[] SourceBuffer, string Pattern) 103 | { 104 | return FindPattern(SourceBuffer, System.Text.Encoding.ASCII.GetBytes(Pattern), null, null); 105 | } 106 | 107 | internal static uint? FindPattern(byte[] SourceBuffer, byte[] Pattern, byte[]? Mask, byte[]? OutPattern) 108 | { 109 | return FindPattern(SourceBuffer, 0, null, Pattern, Mask, OutPattern); 110 | } 111 | 112 | internal static bool Compare(byte[] Array1, byte[] Array2) 113 | { 114 | return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Array1, Array2); 115 | } 116 | 117 | internal static uint? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern) 118 | { 119 | // The mask is optional. 120 | // In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard. 121 | 122 | uint? Result = null; 123 | 124 | uint SearchPosition = SourceOffset; 125 | int i; 126 | 127 | while (SearchPosition <= SourceBuffer.Length - Pattern.Length && (SourceSize == null || SearchPosition <= SourceOffset + SourceSize - Pattern.Length)) 128 | { 129 | bool Match = true; 130 | for (i = 0; i < Pattern.Length; i++) 131 | { 132 | if (SourceBuffer[SearchPosition + i] != Pattern[i]) 133 | { 134 | if (Mask == null || Mask[i] == 0) 135 | { 136 | Match = false; 137 | break; 138 | } 139 | } 140 | } 141 | 142 | if (Match) 143 | { 144 | Result = SearchPosition; 145 | 146 | if (OutPattern != null) 147 | { 148 | Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length); 149 | } 150 | 151 | break; 152 | } 153 | 154 | SearchPosition++; 155 | } 156 | 157 | return Result; 158 | } 159 | 160 | private static readonly uint[] CRC32Table = [ 161 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 162 | 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 163 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 164 | 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 165 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 166 | 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 167 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 168 | 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 169 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 170 | 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 171 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 172 | 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 173 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 174 | 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 175 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 176 | 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 177 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 178 | 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 179 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 180 | 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 181 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 182 | 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 183 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 184 | 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 185 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 186 | 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 187 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 188 | 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 189 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 190 | 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 191 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 192 | 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 193 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 194 | 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 195 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 196 | 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 197 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 198 | 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 199 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 200 | 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 201 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 202 | 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 203 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 204 | ]; 205 | 206 | internal static uint CRC32(byte[] Input, uint Offset, uint Length) 207 | { 208 | if (Input == null || Offset + Length > Input.Length) 209 | { 210 | throw new ArgumentException(); 211 | } 212 | 213 | unchecked 214 | { 215 | uint crc = (uint)((uint)0 ^ -1); 216 | for (uint i = Offset; i < Offset + Length; i++) 217 | { 218 | crc = crc >> 8 ^ CRC32Table[(crc ^ Input[i]) & 0xFF]; 219 | } 220 | crc = (uint)(crc ^ -1); 221 | 222 | if (crc < 0) 223 | { 224 | crc += (uint)4294967296; 225 | } 226 | 227 | return crc; 228 | } 229 | } 230 | } 231 | } 232 | --------------------------------------------------------------------------------