/* * MIT License * * Copyright (c) 2026 The DuoWOA authors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ using CommandLine; using MadWizard.WinUSBNet; using SimpleIO; using System; using System.Linq; namespace SioTool { public class Program { static int Main(string[] args) { Console.WriteLine("SimpleIO Tool"); Console.WriteLine("Copyright (c) 2026 Gustave Monce"); Console.WriteLine(); return Parser.Default.ParseArguments< CLIOptions.DumpStorageOptions, CLIOptions.DumpStorageUIDOptions, CLIOptions.DumpStorageNameOptions>(args) .MapResult( (CLIOptions.DumpStorageOptions opts) => RunDumpStorageAndReturnExitCode(opts), (CLIOptions.DumpStorageUIDOptions opts) => RunDumpStorageUidAndReturnExitCode(opts), (CLIOptions.DumpStorageNameOptions opts) => RunDumpStorageNameAndReturnExitCode(opts), errs => 1); } private static int RunDumpStorageNameAndReturnExitCode(CLIOptions.DumpStorageNameOptions opts) { string DevicePath = ""; /*for (int i = 1; i < args.Length; i++) { string arg = args[i]; if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase)) { if (i + 1 >= args.Length) { Console.WriteLine("Insufficient number of arguments"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } i++; DevicePath = args[i]; } else { Console.WriteLine($"Unknown argument: {arg}"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } }*/ if (string.IsNullOrEmpty(DevicePath)) { USBDeviceInfo[] details = USBDevice.GetDevices("{82809dd0-51f5-11e1-b86c-0800200c9a66}"); if (details.Length == 0) { Console.WriteLine("No SimpleIO devices found"); Environment.Exit(1); } if (details.Length > 1) { Console.WriteLine("Multiple SimpleIO devices found. Please specify the device path"); Console.WriteLine(); Console.WriteLine("Available SimpleIO devices:"); for (int i = 0; i < details.Length; i++) { Console.WriteLine($"[Device {i}]"); Console.WriteLine($"Device Path: {details[i].DevicePath}"); Console.WriteLine($"Can Flash: True"); Console.WriteLine(); } Environment.Exit(1); } DevicePath = details[0].DevicePath; } Dump.Dump.SimpleIODumpStoragePartitionByName(DevicePath, opts.VhdxOutputPath, opts.Name).Wait(); return 0; } private static int RunDumpStorageUidAndReturnExitCode(CLIOptions.DumpStorageUIDOptions opts) { string DevicePath = ""; /*for (int i = 1; i < args.Length; i++) { string arg = args[i]; if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase)) { if (i + 1 >= args.Length) { Console.WriteLine("Insufficient number of arguments"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } i++; DevicePath = args[i]; } else { Console.WriteLine($"Unknown argument: {arg}"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } }*/ if (string.IsNullOrEmpty(DevicePath)) { USBDeviceInfo[] details = USBDevice.GetDevices("{82809dd0-51f5-11e1-b86c-0800200c9a66}"); if (details.Length == 0) { Console.WriteLine("No SimpleIO devices found"); Environment.Exit(1); } if (details.Length > 1) { Console.WriteLine("Multiple SimpleIO devices found. Please specify the device path"); Console.WriteLine(); Console.WriteLine("Available SimpleIO devices:"); for (int i = 0; i < details.Length; i++) { Console.WriteLine($"[Device {i}]"); Console.WriteLine($"Device Path: {details[i].DevicePath}"); Console.WriteLine($"Can Flash: True"); Console.WriteLine(); } Environment.Exit(1); } DevicePath = details[0].DevicePath; } Dump.Dump.SimpleIODumpStoragePartitionByUID(DevicePath, opts.VhdxOutputPath, opts.Uid).Wait(); return 0; } private static int RunDumpStorageAndReturnExitCode(CLIOptions.DumpStorageOptions opts) { string DevicePath = ""; /*for (int i = 1; i < args.Length; i++) { string arg = args[i]; if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase)) { if (i + 1 >= args.Length) { Console.WriteLine("Insufficient number of arguments"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } i++; DevicePath = args[i]; } else { Console.WriteLine($"Unknown argument: {arg}"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } }*/ if (string.IsNullOrEmpty(DevicePath)) { USBDeviceInfo[] details = USBDevice.GetDevices("{82809dd0-51f5-11e1-b86c-0800200c9a66}"); if (details.Length == 0) { Console.WriteLine("No SimpleIO devices found"); Environment.Exit(1); } if (details.Length > 1) { Console.WriteLine("Multiple SimpleIO devices found. Please specify the device path"); Console.WriteLine(); Console.WriteLine("Available SimpleIO devices:"); for (int i = 0; i < details.Length; i++) { Console.WriteLine($"[Device {i}]"); Console.WriteLine($"Device Path: {details[i].DevicePath}"); Console.WriteLine($"Can Flash: True"); Console.WriteLine(); } Environment.Exit(1); } DevicePath = details[0].DevicePath; } Dump.Dump.SimpleIODumpStorage(DevicePath, opts.VhdxOutputPath).Wait(); return 0; } public static void Main2(string[] args) { if (args.Contains("-?")) { //PrintRebootDeviceHelp(); Environment.Exit(0); } string DevicePath = ""; for (int i = 1; i < args.Length; i++) { string arg = args[i]; if (arg.Equals("-DevicePath", StringComparison.InvariantCultureIgnoreCase)) { if (i + 1 >= args.Length) { Console.WriteLine("Insufficient number of arguments"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } i++; DevicePath = args[i]; } else { Console.WriteLine($"Unknown argument: {arg}"); Console.WriteLine(); //PrintRebootDeviceHelp(); Environment.Exit(1); } } if (string.IsNullOrEmpty(DevicePath)) { USBDeviceInfo[] details = USBDevice.GetDevices("{82809dd0-51f5-11e1-b86c-0800200c9a66}"); if (details.Length == 0) { Console.WriteLine("No SimpleIO devices found"); Environment.Exit(1); } if (details.Length > 1) { Console.WriteLine("Multiple SimpleIO devices found. Please specify the device path"); Console.WriteLine(); Console.WriteLine("Available SimpleIO devices:"); for (int i = 0; i < details.Length; i++) { Console.WriteLine($"[Device {i}]"); Console.WriteLine($"Device Path: {details[i].DevicePath}"); Console.WriteLine($"Can Flash: True"); Console.WriteLine(); } Environment.Exit(1); } DevicePath = details[0].DevicePath; } using SimpleIOTransport transport = new(DevicePath); transport.ContinueBoot(); //Dump.SimpleIODumpStorage(DevicePath, ".").Wait(); //Dump.SimpleIODumpStoragePartitionByName(DevicePath, "DPP.img", "DPP").Wait(); /*using SimpleIOTransport transport = new(DevicePath); Console.WriteLine("Getting Device ID..."); // Get ID (long curPosition, Guid guid, bool supportsFastFlash, bool supportsCompatFastFlash, int clientVersion, Guid DeviceUniqueID, string DeviceFriendlyName) = transport.GetIdV2(); Console.WriteLine("=================="); Console.WriteLine("Current Position: " + curPosition); Console.WriteLine("Guid: " + guid); Console.WriteLine("Supports Fast Flash: " + supportsFastFlash); Console.WriteLine("Supports Compat Fast Flash: " + supportsCompatFastFlash); Console.WriteLine("Client Version: " + clientVersion); Console.WriteLine("Device Unique ID: " + DeviceUniqueID); Console.WriteLine("Device Friendly Name: " + DeviceFriendlyName); Console.WriteLine("=================="); Console.WriteLine("Querying supported command state..."); Console.WriteLine($"SioId supported?: {transport.QueryForCommandAvailable(SioOpcode.SioId)}"); Console.WriteLine($"SioFlash supported?: {transport.QueryForCommandAvailable(SioOpcode.SioFlash)}"); Console.WriteLine($"SioAck supported?: {transport.QueryForCommandAvailable(SioOpcode.SioAck)}"); Console.WriteLine($"SioNack supported?: {transport.QueryForCommandAvailable(SioOpcode.SioNack)}"); Console.WriteLine($"SioLog supported?: {transport.QueryForCommandAvailable(SioOpcode.SioLog)}"); Console.WriteLine($"SioErr supported?: {transport.QueryForCommandAvailable(SioOpcode.SioErr)}"); Console.WriteLine($"SioSkip supported?: {transport.QueryForCommandAvailable(SioOpcode.SioSkip)}"); Console.WriteLine($"SioReset supported?: {transport.QueryForCommandAvailable(SioOpcode.SioReset)}"); Console.WriteLine($"SioFile supported?: {transport.QueryForCommandAvailable(SioOpcode.SioFile)}"); Console.WriteLine($"SioReboot supported?: {transport.QueryForCommandAvailable(SioOpcode.SioReboot)}"); Console.WriteLine($"SioMassStorage supported?: {transport.QueryForCommandAvailable(SioOpcode.SioMassStorage)}"); Console.WriteLine($"SioGetDiskInfo supported?: {transport.QueryForCommandAvailable(SioOpcode.SioGetDiskInfo)}"); Console.WriteLine($"SioReadDisk supported?: {transport.QueryForCommandAvailable(SioOpcode.SioReadDisk)}"); Console.WriteLine($"SioWriteDisk supported?: {transport.QueryForCommandAvailable(SioOpcode.SioWriteDisk)}"); Console.WriteLine($"SioClearIdOverride supported?: {transport.QueryForCommandAvailable(SioOpcode.SioClearIdOverride)}"); Console.WriteLine($"SioWim supported?: {transport.QueryForCommandAvailable(SioOpcode.SioWim)}"); Console.WriteLine($"SioSerialNumber supported?: {transport.QueryForCommandAvailable(SioOpcode.SioSerialNumber)}"); Console.WriteLine($"SioExternalWim supported?: {transport.QueryForCommandAvailable(SioOpcode.SioExternalWim)}"); Console.WriteLine($"SioSetBootMode supported?: {transport.QueryForCommandAvailable(SioOpcode.SioSetBootMode)}"); Console.WriteLine($"SioFastFlash supported?: {transport.QueryForCommandAvailable(SioOpcode.SioFastFlash)}"); Console.WriteLine($"SioDeviceParams supported?: {transport.QueryForCommandAvailable(SioOpcode.SioDeviceParams)}"); Console.WriteLine($"SioDeviceVersion supported?: {transport.QueryForCommandAvailable(SioOpcode.SioDeviceVersion)}"); Console.WriteLine($"SioQueryForCmd supported?: {transport.QueryForCommandAvailable(SioOpcode.SioQueryForCmd)}"); Console.WriteLine($"SioGetUpdateLogs supported?: {transport.QueryForCommandAvailable(SioOpcode.SioGetUpdateLogs)}"); Console.WriteLine($"SioQueryDeviceUnlockId supported?: {transport.QueryForCommandAvailable(SioOpcode.SioQueryDeviceUnlockId)}"); Console.WriteLine($"SioRelockDeviceUnlockId supported?: {transport.QueryForCommandAvailable(SioOpcode.SioRelockDeviceUnlockId)}"); Console.WriteLine($"SioQueryUnlockTokenFiles supported?: {transport.QueryForCommandAvailable(SioOpcode.SioQueryUnlockTokenFiles)}"); Console.WriteLine($"SioWriteUnlockTokenFile supported?: {transport.QueryForCommandAvailable(SioOpcode.SioWriteUnlockTokenFile)}"); Console.WriteLine($"SioQueryBitlockerState supported?: {transport.QueryForCommandAvailable(SioOpcode.SioQueryBitlockerState)}"); // Skip //bool result = transport.ContinueBoot(); //Console.WriteLine(result); /*transport.ReadDiskInfo(out int transferSize, out uint blockSize, out ulong lastBlock); Console.WriteLine($"transferSize: {transferSize} blockSize: {blockSize} lastBlock: {lastBlock}"); byte[] startOfGPT = new byte[blockSize * 2]; transport.ReadDataToBuffer(0, startOfGPT, 0, 1024, transferSize); System.IO.File.WriteAllBytes("StartGPT.bin", startOfGPT);*/ //transport.ContinueBoot(); //transport.WriteWim(@"C:\Users\Gus\Downloads\Telegram Desktop\RM1116_1078_0050_10586_13169_207_45_enosw_wim_signed_638639.secwim", DeviceFriendlyName); /*var reader = new SimpleIO.DeviceSectorBasedReader(transport); var strm = new SimpleIO.PartStream(reader, 0, reader.GetMaxSectors() - 1); strm.Seek(0, System.IO.SeekOrigin.Begin); byte[] buff = new byte[8400000]; strm.Read(buff); System.IO.File.WriteAllBytes("testing.bin", buff);*/ //transport.ContinueBoot(); } } }