2024-03-04 00:20:01 +01:00
|
|
|
/*
|
|
|
|
|
* MIT License
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2024 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 MadWizard.WinUSBNet;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
2024-03-05 23:19:49 +01:00
|
|
|
using System.Text;
|
2024-03-04 00:20:01 +01:00
|
|
|
|
|
|
|
|
namespace UnifiedFlashingPlatform
|
|
|
|
|
{
|
2024-03-04 21:50:33 +01:00
|
|
|
public partial class UnifiedFlashingPlatformTransport : IDisposable
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
|
|
|
|
private bool Disposed = false;
|
|
|
|
|
private readonly USBDevice USBDevice = null;
|
|
|
|
|
private USBPipe InputPipe = null;
|
|
|
|
|
private USBPipe OutputPipe = null;
|
|
|
|
|
private object UsbLock = new();
|
|
|
|
|
|
|
|
|
|
public UnifiedFlashingPlatformTransport(string DevicePath)
|
|
|
|
|
{
|
|
|
|
|
USBDevice = new USBDevice(DevicePath);
|
|
|
|
|
|
|
|
|
|
foreach (USBPipe Pipe in USBDevice.Pipes)
|
|
|
|
|
{
|
|
|
|
|
if (Pipe.IsIn)
|
|
|
|
|
{
|
|
|
|
|
InputPipe = Pipe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Pipe.IsOut)
|
|
|
|
|
{
|
|
|
|
|
OutputPipe = Pipe;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (InputPipe == null || OutputPipe == null)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Invalid USB device!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] ExecuteRawMethod(byte[] RawMethod)
|
|
|
|
|
{
|
|
|
|
|
return ExecuteRawMethod(RawMethod, RawMethod.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] ExecuteRawMethod(byte[] RawMethod, int Length)
|
|
|
|
|
{
|
|
|
|
|
byte[] Buffer = new byte[0xF000]; // Should be at least 0x4408 for receiving the GPT packet.
|
|
|
|
|
byte[] Result = null;
|
|
|
|
|
lock (UsbLock)
|
|
|
|
|
{
|
|
|
|
|
OutputPipe.Write(RawMethod, 0, Length);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
int OutputLength = InputPipe.Read(Buffer);
|
|
|
|
|
Result = new byte[OutputLength];
|
|
|
|
|
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
|
|
|
|
|
}
|
|
|
|
|
catch { } // Reboot command looses connection
|
|
|
|
|
}
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ExecuteRawVoidMethod(byte[] RawMethod)
|
|
|
|
|
{
|
|
|
|
|
ExecuteRawVoidMethod(RawMethod, RawMethod.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ExecuteRawVoidMethod(byte[] RawMethod, int Length)
|
|
|
|
|
{
|
|
|
|
|
lock (UsbLock)
|
|
|
|
|
{
|
|
|
|
|
OutputPipe.Write(RawMethod, 0, Length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] ReadParam(string Param)
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
//Console.WriteLine();
|
|
|
|
|
//Console.WriteLine($"Reading {Param}");
|
|
|
|
|
|
2024-03-04 00:20:01 +01:00
|
|
|
byte[] Request = new byte[0x0B];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = ReadParamSignature; // NOKXFR
|
2024-03-04 00:20:01 +01:00
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 0x10))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] Result = new byte[Response[0x10]];
|
|
|
|
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
2024-03-06 00:38:04 +01:00
|
|
|
|
|
|
|
|
//Console.WriteLine($"Result (as bytes): {BitConverter.ToString(Result).Replace("-", "")}");
|
|
|
|
|
|
2024-03-04 00:20:01 +01:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadStringParam(string Param)
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam(Param);
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
string result = Encoding.ASCII.GetString(Bytes).Trim('\0');
|
2024-03-06 00:38:04 +01:00
|
|
|
//Console.WriteLine($"Result (fl string): {Encoding.ASCII.GetString(Bytes).Replace("\0", "\\0")}");
|
|
|
|
|
//Console.WriteLine($"Result (as string): {result}");
|
2024-03-05 23:19:49 +01:00
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum FlashAppType
|
|
|
|
|
{
|
|
|
|
|
UFP = 1,
|
|
|
|
|
Unknown
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public FlashAppType ReadAppType()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("APPT");
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return FlashAppType.Unknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Bytes[0] == 1)
|
|
|
|
|
{
|
|
|
|
|
return FlashAppType.UFP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FlashAppType.Unknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct ResetProtectionInfo
|
|
|
|
|
{
|
|
|
|
|
public bool IsResetProtectionEnabled;
|
|
|
|
|
public uint MajorVersion;
|
|
|
|
|
public uint MinorVersion;
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public override readonly string ToString()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
return "IsResetProtectionEnabled: " + IsResetProtectionEnabled +
|
|
|
|
|
" - MajorVersion: " + MajorVersion +
|
2024-03-05 23:19:49 +01:00
|
|
|
" - MinorVersion: " + MinorVersion;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ResetProtectionInfo? ReadResetProtection()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("ATRP");
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ResetProtectionInfo()
|
|
|
|
|
{
|
|
|
|
|
IsResetProtectionEnabled = Bytes[0] == 1,
|
|
|
|
|
MajorVersion = BitConverter.ToUInt32(Bytes[1..5].Reverse().ToArray()),
|
|
|
|
|
MinorVersion = BitConverter.ToUInt32(Bytes[5..9].Reverse().ToArray())
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool? ReadBitlocker()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("BITL");
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Bytes[0] == 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadBuildInfo()
|
|
|
|
|
{
|
|
|
|
|
return ReadStringParam("BNFO");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ushort? ReadCurrentBootOption()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("CUFO");
|
2024-03-06 00:38:04 +01:00
|
|
|
if (Bytes == null || Bytes.Length != 2)
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt16(Bytes.Reverse().ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool? ReadDeviceAsyncSupport()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("DAS\0");
|
2024-03-06 00:38:04 +01:00
|
|
|
if (Bytes == null || Bytes.Length != 2)
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt16(Bytes.Reverse().ToArray()) == 1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt64? ReadDirectoryEntriesSize(string PartitionName, string DirectoryName)
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
|
|
|
|
if (PartitionName.Length > 35)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] PartitionNameBuffer = Encoding.Unicode.GetBytes(PartitionName);
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] DirectoryNameBuffer = Encoding.Unicode.GetBytes(DirectoryName);
|
2024-03-05 23:19:49 +01:00
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Request = new byte[87 + DirectoryNameBuffer.Length + 2];
|
2024-03-05 23:19:49 +01:00
|
|
|
string Header = ReadParamSignature; // NOKXFR
|
|
|
|
|
const string Param = "DES\0";
|
|
|
|
|
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
|
|
|
|
|
|
|
|
|
Buffer.BlockCopy(PartitionNameBuffer, 0, Request, 15, PartitionNameBuffer.Length);
|
2024-03-06 00:38:04 +01:00
|
|
|
Buffer.BlockCopy(DirectoryNameBuffer, 0, Request, 87, DirectoryNameBuffer.Length);
|
2024-03-05 23:19:49 +01:00
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 0x10))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] Result = new byte[Response[0x10]];
|
|
|
|
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt64(Result.Reverse().ToArray());
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadDevicePlatformID()
|
|
|
|
|
{
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("DPI\0");
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
//
|
|
|
|
|
// Reads the device properties from the UEFI Variable "MSRuntimeDeviceProperties"
|
|
|
|
|
// in the g_guidMSRuntimeDeviceProperties namespace and returns it as a string.
|
|
|
|
|
//
|
|
|
|
|
public string ReadDeviceProperties()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("DPR\0");
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
public struct DeviceTargetingInfo
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
2024-03-05 23:19:49 +01:00
|
|
|
public string Manufacturer;
|
|
|
|
|
public string Family;
|
|
|
|
|
public string ProductName;
|
|
|
|
|
public string ProductVersion;
|
|
|
|
|
public string SKUNumber;
|
|
|
|
|
public string BaseboardManufacturer;
|
|
|
|
|
public string BaseboardProduct;
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public override readonly string ToString()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
return "Manufacturer: " + Manufacturer +
|
|
|
|
|
" - Family: " + Family +
|
|
|
|
|
" - Product Name: " + ProductName +
|
|
|
|
|
" - Product Version: " + ProductVersion +
|
|
|
|
|
" - SKU Number: " + SKUNumber +
|
|
|
|
|
" - Baseboard Manufacturer: " + BaseboardManufacturer +
|
2024-03-05 23:19:49 +01:00
|
|
|
" - Baseboard Product: " + BaseboardProduct;
|
|
|
|
|
}
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
public DeviceTargetingInfo? ReadDeviceTargetInfo()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
2024-03-05 23:19:49 +01:00
|
|
|
byte[] Bytes = ReadParam("DTI\0");
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UInt16 ManufacturerLength = BitConverter.ToUInt16(Bytes[0..2].Reverse().ToArray());
|
|
|
|
|
UInt16 FamilyLength = BitConverter.ToUInt16(Bytes[2..4].Reverse().ToArray());
|
|
|
|
|
UInt16 ProductNameLength = BitConverter.ToUInt16(Bytes[4..6].Reverse().ToArray());
|
|
|
|
|
UInt16 ProductVersionLength = BitConverter.ToUInt16(Bytes[6..8].Reverse().ToArray());
|
|
|
|
|
UInt16 SKUNumberLength = BitConverter.ToUInt16(Bytes[8..10].Reverse().ToArray());
|
|
|
|
|
UInt16 BaseboardManufacturerLength = BitConverter.ToUInt16(Bytes[10..12].Reverse().ToArray());
|
|
|
|
|
UInt16 BaseboardProductLength = BitConverter.ToUInt16(Bytes[12..14].Reverse().ToArray());
|
|
|
|
|
|
|
|
|
|
Int32 CurrentOffset = 14;
|
|
|
|
|
string Manufacturer = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ManufacturerLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += ManufacturerLength;
|
|
|
|
|
string Family = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + FamilyLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += FamilyLength;
|
|
|
|
|
string ProductName = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ProductNameLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += ProductNameLength;
|
|
|
|
|
string ProductVersion = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ProductVersionLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += ProductVersionLength;
|
|
|
|
|
string SKUNumber = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + SKUNumberLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += SKUNumberLength;
|
|
|
|
|
string BaseboardManufacturer = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + BaseboardManufacturerLength)]);
|
|
|
|
|
|
|
|
|
|
CurrentOffset += BaseboardManufacturerLength;
|
|
|
|
|
string BaseboardProduct = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + BaseboardProductLength)]);
|
|
|
|
|
|
|
|
|
|
return new DeviceTargetingInfo()
|
|
|
|
|
{
|
|
|
|
|
Manufacturer = Manufacturer,
|
|
|
|
|
Family = Family,
|
|
|
|
|
ProductName = ProductName,
|
|
|
|
|
ProductVersion = ProductVersion,
|
|
|
|
|
SKUNumber = SKUNumber,
|
|
|
|
|
BaseboardManufacturer = BaseboardManufacturer,
|
|
|
|
|
BaseboardProduct = BaseboardProduct
|
|
|
|
|
};
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Gets the last FFU Flash Operation Data verify speed in KB/s
|
|
|
|
|
//
|
|
|
|
|
public UInt32? ReadDataVerifySpeed()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("DTSP");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public Guid? ReadDeviceID()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("DUI\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 16)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new Guid(Bytes);
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt32? ReadEmmcTestResult()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("EMMT");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Gets the eMMC Size in sectors, if present
|
|
|
|
|
//
|
|
|
|
|
public UInt32? ReadEmmcSize()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("EMS\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Gets the eMMC Write speed in KB/s
|
|
|
|
|
//
|
|
|
|
|
public UInt32? ReadEmmcWriteSpeed()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("EMWS");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public struct FlashAppInfo
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
public byte ProtocolMajorVersion;
|
|
|
|
|
public byte ProtocolMinorVersion;
|
|
|
|
|
public byte MajorVersion;
|
|
|
|
|
public byte MinorVersion;
|
|
|
|
|
|
|
|
|
|
public override readonly string ToString()
|
|
|
|
|
{
|
|
|
|
|
return "ProtocolMajorVersion: " + ProtocolMajorVersion +
|
|
|
|
|
" - ProtocolMinorVersion: " + ProtocolMinorVersion +
|
|
|
|
|
" - MajorVersion: " + MajorVersion +
|
|
|
|
|
" - MinorVersion: " + MinorVersion;
|
|
|
|
|
}
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public FlashAppInfo? ReadFlashAppInfo()
|
|
|
|
|
{
|
|
|
|
|
byte[] Bytes = ReadParam("FAI\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 6 || Bytes[0] != 2)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new FlashAppInfo()
|
|
|
|
|
{
|
|
|
|
|
ProtocolMajorVersion = Bytes[1],
|
|
|
|
|
ProtocolMinorVersion = Bytes[2],
|
|
|
|
|
MajorVersion = Bytes[3],
|
|
|
|
|
MinorVersion = Bytes[4]
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads the device properties from the UEFI Variable "FfuConfigurationOptions"
|
|
|
|
|
// in the g_guidLumiaGuid namespace and returns it as a string.
|
|
|
|
|
//
|
2024-03-05 23:19:49 +01:00
|
|
|
public string ReadFlashOptions()
|
|
|
|
|
{
|
|
|
|
|
return ReadStringParam("FO\0\0");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt32? ReadFlashingStatus()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("FS\0\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt64? ReadFileSize(string PartitionName, string FileName)
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
if (PartitionName.Length > 35)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] PartitionNameBuffer = Encoding.Unicode.GetBytes(PartitionName);
|
|
|
|
|
byte[] FileNameBuffer = Encoding.Unicode.GetBytes(FileName);
|
|
|
|
|
|
|
|
|
|
byte[] Request = new byte[87 + FileNameBuffer.Length + 2];
|
|
|
|
|
string Header = ReadParamSignature; // NOKXFR
|
|
|
|
|
const string Param = "FZ\0\0";
|
|
|
|
|
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
|
|
|
|
|
|
|
|
|
Buffer.BlockCopy(PartitionNameBuffer, 0, Request, 15, PartitionNameBuffer.Length);
|
|
|
|
|
Buffer.BlockCopy(FileNameBuffer, 0, Request, 87, FileNameBuffer.Length);
|
|
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 0x10))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] Result = new byte[Response[0x10]];
|
|
|
|
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt64(Result.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public bool? ReadSecureBootStatus()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("GSBS");
|
|
|
|
|
if (Bytes == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Bytes[0] == 1;
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadUEFIVariable()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO: Implement
|
|
|
|
|
//
|
|
|
|
|
// Pseudo code:
|
|
|
|
|
//
|
|
|
|
|
// DebugPrintFormatted(2i64, "HandleReadParamReq", 4298i64, "Read UEFI variable...\r\n");
|
|
|
|
|
// LogWrite("INFO", "HandleReadParamReq", "Read UEFI variable...\r\n");
|
|
|
|
|
// v81 = *(unsigned __int8 *)(a1 + 35);
|
|
|
|
|
// v82 = *(unsigned __int8 *)(a1 + 36);
|
|
|
|
|
// v169 = (const char *)(*(unsigned __int8 *)(a1 + 34) | ((*(unsigned __int8 *)(a1 + 33) | ((*(unsigned // __int8 *)(a1 + 32) | ((unsigned __int64)*(unsigned __int8 *)(a1 + 31) << 8)) << 8)) << 8));
|
|
|
|
|
// ZeroPool = (const char *)AllocatePool(*(unsigned __int8 *)(a1 + 38) | ((*(unsigned __int8 *)(a1 + 37) | // ((v82 | (v81 << 8)) << 8)) << 8));
|
|
|
|
|
// memmove(ZeroPool);
|
|
|
|
|
// Pool = (const char *)AllocatePool(v169);
|
|
|
|
|
// v83 = VariableGet(ZeroPool, a1 + 15, &v165, &v169, Pool, 1i64, &v163);
|
|
|
|
|
//
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("GUFV");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadUEFIVariableSize()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO: Implement
|
|
|
|
|
//
|
|
|
|
|
// Pseudo code:
|
|
|
|
|
//
|
|
|
|
|
// v105 = *(unsigned __int8 *)(a1 + 35);
|
|
|
|
|
// v106 = *(unsigned __int8 *)(a1 + 36);
|
|
|
|
|
// v165 = *(unsigned __int8 *)(a1 + 34) | ((*(unsigned __int8 *)(a1 + 33) | ((*(unsigned __int8 *)(a1 + // 32) | (*(unsigned __int8 *)(a1 + 31) << 8)) << 8)) << 8);
|
|
|
|
|
// Pool = (const char *)AllocatePool(*(unsigned __int8 *)(a1 + 38) | ((*(unsigned __int8 *)(a1 + 37) | // ((v106 | (v105 << 8)) << 8)) << 8));
|
|
|
|
|
// memmove(Pool);
|
|
|
|
|
// v107 = VariableGetSize(Pool, a1 + 15, &v165, 1i64, &v163);
|
|
|
|
|
// v108 = v107;
|
|
|
|
|
//
|
|
|
|
|
// Returns:
|
|
|
|
|
//
|
|
|
|
|
// v109 = BYTE1(v165);
|
|
|
|
|
// v9 = 4;
|
|
|
|
|
// v110 = HIWORD(v165);
|
|
|
|
|
// *(_BYTE *)(a3 + 20) = v165;
|
|
|
|
|
// *(_BYTE *)(a3 + 18) = v110;
|
|
|
|
|
// *(_BYTE *)(a3 + 17) = BYTE1(v110);
|
|
|
|
|
// *(_BYTE *)(a3 + 19) = v109;
|
|
|
|
|
//
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("GUVS");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Returns the largest memory region in bytes available for use by UFP
|
|
|
|
|
//
|
|
|
|
|
public UInt64? ReadLargestMemoryRegion()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("LGMR");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 8)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt64(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public enum LogType
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
Flashing = 1,
|
|
|
|
|
Servicing = 2,
|
|
|
|
|
Unknown
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt64? ReadLogSize(LogType LogType)
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[0x10];
|
|
|
|
|
string Header = ReadParamSignature; // NOKXFR
|
|
|
|
|
const string Param = "LZ\0\0";
|
|
|
|
|
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
|
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
|
|
|
|
|
|
|
|
|
Request[15] = (byte)LogType;
|
|
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 0x10))
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] Result = new byte[Response[0x10]];
|
|
|
|
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt64(Result.Reverse().ToArray(), 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads the MAC Address in the following format: "%02x-%02x-%02x-%02x-%02x-%02x"
|
|
|
|
|
//
|
2024-03-05 23:19:49 +01:00
|
|
|
public string ReadMacAddress()
|
|
|
|
|
{
|
|
|
|
|
return ReadStringParam("MAC\0");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt32? ReadModeData()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("MODE");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadProcessorManufacturer()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
2024-03-04 23:24:28 +01:00
|
|
|
return ReadStringParam("pm\0\0");
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Gets the SD Card Size in sectors, if present
|
|
|
|
|
//
|
|
|
|
|
public UInt32? ReadSDCardSize()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("SDS\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadSupportedFFUProtocolInfo()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("SFPI");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadSMBIOSData()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("SMBD");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public Guid? ReadSerialNumber()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("SN\0\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 16)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new Guid(Bytes);
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Returns the size of system memory in kB
|
|
|
|
|
//
|
|
|
|
|
public UInt64? ReadSizeOfSystemMemory()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("SOSM");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 8)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt64(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadSecurityStatus()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("SS\0\0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadTelemetryLogSize()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("TELS");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt32? ReadTransferSize()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("TS\0\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Reads the UEFI Boot Flag variable content and returns it as a string.
|
|
|
|
|
//
|
2024-03-05 23:19:49 +01:00
|
|
|
public string ReadUEFIBootFlag()
|
|
|
|
|
{
|
|
|
|
|
return ReadStringParam("UBF\0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string ReadUEFIBootOptions()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("UEBO");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
//
|
|
|
|
|
// Reads the device properties from the UEFI Variable "UnlockID"
|
|
|
|
|
// in the g_guidOfflineDUIdEfiNamespace namespace and returns it as a string.
|
|
|
|
|
//
|
2024-03-04 00:20:01 +01:00
|
|
|
public string ReadUnlockID()
|
|
|
|
|
{
|
|
|
|
|
return ReadStringParam("UKID");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
public string ReadUnlockTokenFiles()
|
|
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
// TODO
|
2024-03-05 23:19:49 +01:00
|
|
|
return ReadStringParam("UKTF");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt16? ReadUSBSpeed()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("USBS");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 2)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt16(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
public UInt32? ReadWriteBufferSize()
|
2024-03-05 23:19:49 +01:00
|
|
|
{
|
2024-03-06 00:38:04 +01:00
|
|
|
byte[] Bytes = ReadParam("WBS\0");
|
|
|
|
|
if (Bytes == null || Bytes.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
2024-03-05 23:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-04 00:20:01 +01:00
|
|
|
public void Relock()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = RelockSignature; // NOKXFO
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 23:24:28 +01:00
|
|
|
public void MassStorage()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = MassStorageSignature; // NOKM
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 23:24:28 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RebootPhone()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
|
|
|
|
string Header = $"{SwitchModeSignature}R"; // NOKXCBR
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 23:24:28 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SwitchToUFP()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
|
|
|
|
string Header = $"{SwitchModeSignature}U"; // NOKXCBU
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ContinueBoot()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = $"{SwitchModeSignature}W"; // NOKXCBW
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 23:24:28 +01:00
|
|
|
public void PowerOff()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = $"{SwitchModeSignature}Z"; // NOKXCBZ
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
ExecuteRawVoidMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 23:24:28 +01:00
|
|
|
public void TransitionToUFPBootApp()
|
2024-03-04 00:20:01 +01:00
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[7];
|
2024-03-04 23:24:28 +01:00
|
|
|
string Header = $"{SwitchModeSignature}T"; // NOKXCBT
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 23:24:28 +01:00
|
|
|
ExecuteRawVoidMethod(Request);
|
2024-03-04 00:20:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 00:30:22 +01:00
|
|
|
public void DisplayCustomMessage(string Message, ushort Row)
|
|
|
|
|
{
|
2024-03-05 23:19:49 +01:00
|
|
|
byte[] MessageBuffer = Encoding.Unicode.GetBytes(Message);
|
2024-03-05 00:30:22 +01:00
|
|
|
byte[] Request = new byte[8 + MessageBuffer.Length];
|
|
|
|
|
string Header = DisplayCustomMessageSignature; // NOKXCM
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-05 00:30:22 +01:00
|
|
|
Buffer.BlockCopy(BitConverter.GetBytes(Row).Reverse().ToArray(), 0, Request, 6, 2);
|
|
|
|
|
Buffer.BlockCopy(MessageBuffer, 0, Request, 8, MessageBuffer.Length);
|
|
|
|
|
|
|
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 20:34:12 +01:00
|
|
|
public void ClearScreen()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[6];
|
|
|
|
|
string Header = ClearScreenSignature; // NOKXCC
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-05 20:34:12 +01:00
|
|
|
ExecuteRawMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] Echo(byte[] DataPayload)
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[10 + DataPayload.Length];
|
|
|
|
|
string Header = EchoSignature; // NOKXCE
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-05 20:34:12 +01:00
|
|
|
Buffer.BlockCopy(BitConverter.GetBytes(DataPayload.Length).Reverse().ToArray(), 0, Request, 6, 4);
|
|
|
|
|
Buffer.BlockCopy(DataPayload, 0, Request, 10, DataPayload.Length);
|
|
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 6 + DataPayload.Length))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] Result = new byte[DataPayload.Length];
|
|
|
|
|
Buffer.BlockCopy(Response, 6, Result, 0, DataPayload.Length);
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void TelemetryStart()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[4];
|
|
|
|
|
string Header = TelemetryStartSignature; // NOKS
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-05 20:34:12 +01:00
|
|
|
ExecuteRawVoidMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void TelemetryEnd()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[4];
|
|
|
|
|
string Header = TelemetryEndSignature; // NOKN
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-05 20:34:12 +01:00
|
|
|
ExecuteRawVoidMethod(Request);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 00:20:01 +01:00
|
|
|
// WIP!
|
|
|
|
|
public string ReadLog()
|
|
|
|
|
{
|
|
|
|
|
byte[] Request = new byte[0x13];
|
2024-03-04 21:30:40 +01:00
|
|
|
string Header = GetLogsSignature;
|
2024-03-04 00:20:01 +01:00
|
|
|
ulong BufferSize = 0xF000 - 0xC;
|
|
|
|
|
|
2024-03-06 00:38:04 +01:00
|
|
|
ulong Length = ReadLogSize(LogType.Flashing)!.Value;
|
2024-03-04 00:20:01 +01:00
|
|
|
if (Length == 0)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string LogContent = "";
|
|
|
|
|
|
|
|
|
|
for (ulong i = 0; i < Length; i += BufferSize)
|
|
|
|
|
{
|
|
|
|
|
if (i + BufferSize > Length)
|
|
|
|
|
{
|
|
|
|
|
BufferSize = Length - i;
|
|
|
|
|
}
|
|
|
|
|
uint BufferSizeInt = (uint)BufferSize;
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
2024-03-04 00:20:01 +01:00
|
|
|
Request[6] = 1;
|
|
|
|
|
Buffer.BlockCopy(BitConverter.GetBytes(BufferSizeInt).Reverse().ToArray(), 0, Request, 7, 4);
|
|
|
|
|
Buffer.BlockCopy(BitConverter.GetBytes(i).Reverse().ToArray(), 0, Request, 11, 8);
|
|
|
|
|
|
|
|
|
|
byte[] Response = ExecuteRawMethod(Request);
|
|
|
|
|
if ((Response == null) || (Response.Length < 0xC))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ResultLength = Response.Length - 0xC;
|
|
|
|
|
byte[] Result = new byte[ResultLength];
|
|
|
|
|
Buffer.BlockCopy(Response, 0xC, Result, 0, ResultLength);
|
|
|
|
|
|
2024-03-05 23:19:49 +01:00
|
|
|
string PartialLogContent = Encoding.ASCII.GetString(Result);
|
2024-03-04 00:20:01 +01:00
|
|
|
|
|
|
|
|
LogContent += PartialLogContent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LogContent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Dispose(true);
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~UnifiedFlashingPlatformTransport()
|
|
|
|
|
{
|
|
|
|
|
Dispose(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Close()
|
|
|
|
|
{
|
|
|
|
|
USBDevice?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
if (Disposed)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (disposing)
|
|
|
|
|
{
|
|
|
|
|
// Other disposables
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clean unmanaged resources here.
|
|
|
|
|
Close();
|
|
|
|
|
|
|
|
|
|
Disposed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|