Embrace nullables

This commit is contained in:
Gustave Monce
2024-06-23 09:17:00 +02:00
parent 8006585c4e
commit beef784483
8 changed files with 185 additions and 264 deletions
+1 -1
View File
@@ -255,7 +255,7 @@ namespace UnifiedFlashingPlatform
return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Array1, Array2);
}
internal static uint? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[] Mask, byte[] OutPattern)
internal static uint? FindPattern(byte[] SourceBuffer, uint SourceOffset, uint? SourceSize, byte[] Pattern, byte[]? Mask, byte[]? OutPattern)
{
// The mask is optional.
// In the mask 0x00 means the value must match, and 0xFF means that this position is a wildcard.
+11
View File
@@ -0,0 +1,11 @@
namespace UnifiedFlashingPlatform
{
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
}
+4 -69
View File
@@ -30,7 +30,7 @@ namespace UnifiedFlashingPlatform
[XmlType("Partitions")]
public class GPT
{
private byte[] GPTBuffer;
private byte[]? GPTBuffer;
private readonly uint HeaderOffset;
private readonly uint HeaderSize;
private uint TableOffset;
@@ -98,76 +98,11 @@ namespace UnifiedFlashingPlatform
HasChanged = false;
}
internal Partition GetPartition(string Name)
internal Partition? GetPartition(string Name)
{
return Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
}
// Magic!
// SecureBoot hack for Bootloader Spec A starts here
internal byte[] InsertHack()
{
Partition HackPartition = Partitions.Find(p => p.Name == "HACK");
Partition SBL1 = Partitions.Find(p => p.Name == "SBL1");
Partition SBL2 = Partitions.Find(p => p.Name == "SBL2");
if ((SBL1 == null) || (SBL2 == null))
{
throw new WPinternalsException("Bad GPT", "Can't patch GPT for the Secure Boot hack for Spec A devices. The provided GPT does not include a SBL1 and/or SBL2 partition.");
}
if (HackPartition == null)
{
HackPartition = new Partition
{
Name = "HACK",
Attributes = SBL2.Attributes,
FirstSector = SBL1.LastSector,
LastSector = SBL1.LastSector,
PartitionTypeGuid = SBL2.PartitionTypeGuid,
PartitionGuid = SBL2.PartitionGuid
};
Partitions.Add(HackPartition);
SBL1.LastSector--;
SBL2.PartitionTypeGuid = new Guid(new byte[] { 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74 });
SBL2.PartitionGuid = new Guid(new byte[] { 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74 });
}
HasChanged = true;
return Rebuild();
}
internal byte[] RemoveHack()
{
Partition HackPartition = Partitions.Find(p => p.Name == "HACK");
Partition SBL1 = Partitions.Find(p => p.Name == "SBL1");
Partition SBL2 = Partitions.Find(p => p.Name == "SBL2");
if ((SBL1 == null) || (SBL2 == null))
{
throw new WPinternalsException("Bad GPT", "Can't un-patch GPT for the Secure Boot hack for Spec A devices. The provided GPT does not include a SBL1 and/or SBL2 partition.");
}
if (HackPartition != null)
{
SBL2.PartitionTypeGuid = HackPartition.PartitionTypeGuid;
SBL2.PartitionGuid = HackPartition.PartitionGuid;
_ = Partitions.Remove(HackPartition);
SBL1.LastSector++;
}
HasChanged = true;
return Rebuild();
}
internal byte[] Rebuild()
{
if (GPTBuffer == null)
@@ -373,7 +308,7 @@ namespace UnifiedFlashingPlatform
// Existing partitions, which are overwritten by the new partitions will be removed from the existing GPT.
// Existing partition with the same name in the existing GPT is reused (guids and attribs remain, if not specified).
ulong LowestSector = 0;
Partition DPP = GetPartition("DPP");
Partition? DPP = GetPartition("DPP");
if (DPP != null)
{
LowestSector = DPP.LastSector + 1;
@@ -613,7 +548,7 @@ namespace UnifiedFlashingPlatform
private ulong _FirstSector;
private ulong _LastSector;
public string Name; // 0x48
public string? Name; // 0x48
public Guid PartitionTypeGuid; // 0x10
public Guid PartitionGuid; // 0x10
[XmlIgnore]
+66
View File
@@ -0,0 +1,66 @@
using System;
using System.Diagnostics;
namespace UnifiedFlashingPlatform
{
public class ProgressUpdater
{
private readonly DateTime InitTime;
private DateTime LastUpdateTime;
private readonly ulong MaxValue;
private readonly Action<int, TimeSpan?> ProgressUpdateCallback;
public int ProgressPercentage;
public ProgressUpdater(ulong MaxValue, Action<int, TimeSpan?> ProgressUpdateCallback)
{
InitTime = DateTime.Now;
LastUpdateTime = DateTime.Now;
this.MaxValue = MaxValue;
this.ProgressUpdateCallback = ProgressUpdateCallback;
SetProgress(0);
}
private ulong _Progress;
public ulong Progress
{
get
{
return _Progress;
}
}
public void SetProgress(ulong NewValue)
{
if (_Progress != NewValue)
{
int PreviousProgressPercentage = (int)((double)_Progress / MaxValue * 100);
ProgressPercentage = (int)((double)NewValue / MaxValue * 100);
_Progress = NewValue;
if (((DateTime.Now - LastUpdateTime) > TimeSpan.FromSeconds(0.5)) || (ProgressPercentage == 100))
{
#if DEBUG
Debug.WriteLine("Init time: " + InitTime.ToShortTimeString() + " / Now: " + DateTime.Now.ToString() + " / NewValue: " + NewValue.ToString() + " / MaxValue: " + MaxValue.ToString() + " ->> Percentage: " + ProgressPercentage.ToString() + " / Remaining: " + TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - ((double)NewValue / MaxValue)))).ToString());
#endif
if (((DateTime.Now - InitTime) < TimeSpan.FromSeconds(30)) && (ProgressPercentage < 15))
{
ProgressUpdateCallback(ProgressPercentage, null);
}
else
{
ProgressUpdateCallback(ProgressPercentage, TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - ((double)NewValue / MaxValue)))));
}
LastUpdateTime = DateTime.Now;
}
}
}
public void IncreaseProgress(ulong Progress)
{
SetProgress(_Progress + Progress);
}
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ namespace Img2Ffu.Reader.Data
public ulong TotalChunkCount => Image.GetImageBlockCount();
public readonly List<byte[]> BlockHashes = [];
public X509Certificate Certificate;
public X509Certificate? Certificate;
private readonly Stream Stream;
+45 -45
View File
@@ -6,7 +6,7 @@ namespace UnifiedFlashingPlatform
{
public partial class UnifiedFlashingPlatformTransport
{
public byte[] ReadParam(string Param)
public byte[]? ReadParam(string Param)
{
byte[] Request = new byte[0x0B];
string Header = ReadParamSignature; // NOKXFR
@@ -14,7 +14,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -25,21 +25,21 @@ namespace UnifiedFlashingPlatform
return Result;
}
public string ReadStringParam(string Param)
public string? ReadStringParam(string Param)
{
byte[] Bytes = ReadParam(Param);
byte[]? Bytes = ReadParam(Param);
return Bytes == null ? null : Encoding.ASCII.GetString(Bytes).Trim('\0');
}
public AppType ReadAppType()
{
byte[] Bytes = ReadParam("APPT");
byte[]? Bytes = ReadParam("APPT");
return Bytes == null ? AppType.Min : Bytes[0] == 1 ? AppType.UEFI : AppType.Min;
}
public ResetProtectionInfo? ReadResetProtection()
{
byte[] Bytes = ReadParam("ATRP");
byte[]? Bytes = ReadParam("ATRP");
return Bytes == null
? null
: new ResetProtectionInfo()
@@ -52,24 +52,24 @@ namespace UnifiedFlashingPlatform
public bool? ReadBitlocker()
{
byte[] Bytes = ReadParam("BITL");
byte[]? Bytes = ReadParam("BITL");
return Bytes == null ? null : Bytes[0] == 1;
}
public string ReadBuildInfo()
public string? ReadBuildInfo()
{
return ReadStringParam("BNFO");
}
public ushort? ReadCurrentBootOption()
{
byte[] Bytes = ReadParam("CUFO");
byte[]? Bytes = ReadParam("CUFO");
return Bytes == null || Bytes.Length != 2 ? null : BitConverter.ToUInt16(Bytes.Reverse().ToArray());
}
public bool? ReadDeviceAsyncSupport()
{
byte[] Bytes = ReadParam("DAS\0");
byte[]? Bytes = ReadParam("DAS\0");
return Bytes == null || Bytes.Length != 2 ? null : BitConverter.ToUInt16(Bytes.Reverse().ToArray()) == 1;
}
@@ -93,7 +93,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(PartitionNameBuffer, 0, Request, 15, PartitionNameBuffer.Length);
Buffer.BlockCopy(DirectoryNameBuffer, 0, Request, 87, DirectoryNameBuffer.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -105,7 +105,7 @@ namespace UnifiedFlashingPlatform
return BitConverter.ToUInt64(Result.Reverse().ToArray());
}
public string ReadDevicePlatformID()
public string? ReadDevicePlatformID()
{
return ReadStringParam("DPI\0");
}
@@ -114,14 +114,14 @@ namespace UnifiedFlashingPlatform
// Reads the device properties from the UEFI Variable "MSRuntimeDeviceProperties"
// in the g_guidMSRuntimeDeviceProperties namespace and returns it as a string.
//
public string ReadDeviceProperties()
public string? ReadDeviceProperties()
{
return ReadStringParam("DPR\0");
}
public DeviceTargetingInfo? ReadDeviceTargetInfo()
{
byte[] Bytes = ReadParam("DTI\0");
byte[]? Bytes = ReadParam("DTI\0");
if (Bytes == null)
{
return null;
@@ -173,19 +173,19 @@ namespace UnifiedFlashingPlatform
//
public uint? ReadDataVerifySpeed()
{
byte[] Bytes = ReadParam("DTSP");
byte[]? Bytes = ReadParam("DTSP");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
public Guid? ReadDeviceID()
{
byte[] Bytes = ReadParam("DUI\0");
byte[]? Bytes = ReadParam("DUI\0");
return Bytes == null || Bytes.Length != 16 ? null : new Guid(Bytes);
}
public uint? ReadEmmcTestResult()
{
byte[] Bytes = ReadParam("EMMT");
byte[]? Bytes = ReadParam("EMMT");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
@@ -194,7 +194,7 @@ namespace UnifiedFlashingPlatform
//
public uint? ReadEmmcSize()
{
byte[] Bytes = ReadParam("EMS\0");
byte[]? Bytes = ReadParam("EMS\0");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
@@ -203,13 +203,13 @@ namespace UnifiedFlashingPlatform
//
public uint? ReadEmmcWriteSpeed()
{
byte[] Bytes = ReadParam("EMWS");
byte[]? Bytes = ReadParam("EMWS");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
public FlashAppInfo? ReadFlashAppInfo()
{
byte[] Bytes = ReadParam("FAI\0");
byte[]? Bytes = ReadParam("FAI\0");
return Bytes == null || Bytes.Length != 6 || Bytes[0] != 2
? null
: new FlashAppInfo()
@@ -225,14 +225,14 @@ namespace UnifiedFlashingPlatform
// Reads the device properties from the UEFI Variable "FfuConfigurationOptions"
// in the g_guidLumiaGuid namespace and returns it as a string.
//
public string ReadFlashOptions()
public string? ReadFlashOptions()
{
return ReadStringParam("FO\0\0");
}
public uint? ReadFlashingStatus()
{
byte[] Bytes = ReadParam("FS\0\0");
byte[]? Bytes = ReadParam("FS\0\0");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
@@ -256,7 +256,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(PartitionNameBuffer, 0, Request, 15, PartitionNameBuffer.Length);
Buffer.BlockCopy(FileNameBuffer, 0, Request, 87, FileNameBuffer.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -270,7 +270,7 @@ namespace UnifiedFlashingPlatform
public bool? ReadSecureBootStatus()
{
byte[] Bytes = ReadParam("GSBS");
byte[]? Bytes = ReadParam("GSBS");
return Bytes == null ? null : Bytes[0] == 1;
}
@@ -290,7 +290,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(BitConverter.GetBytes((Name.Length + 1) * 2).Reverse().ToArray(), 0, Request, 35, 4);
Buffer.BlockCopy(VariableNameBuffer, 0, Request, 39, VariableNameBuffer.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -323,7 +323,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(BitConverter.GetBytes((Name.Length + 1) * 2).Reverse().ToArray(), 0, Request, 35, 4);
Buffer.BlockCopy(VariableNameBuffer, 0, Request, 39, VariableNameBuffer.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -339,7 +339,7 @@ namespace UnifiedFlashingPlatform
//
public ulong? ReadLargestMemoryRegion()
{
byte[] Bytes = ReadParam("LGMR");
byte[]? Bytes = ReadParam("LGMR");
return Bytes == null || Bytes.Length != 8 ? null : BitConverter.ToUInt64(Bytes.Reverse().ToArray());
}
@@ -354,7 +354,7 @@ namespace UnifiedFlashingPlatform
Request[15] = (byte)LogType;
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return 0;
@@ -369,7 +369,7 @@ namespace UnifiedFlashingPlatform
//
// Reads the MAC Address in the following format: "%02x-%02x-%02x-%02x-%02x-%02x"
//
public string ReadMacAddress()
public string? ReadMacAddress()
{
return ReadStringParam("MAC\0");
}
@@ -385,7 +385,7 @@ namespace UnifiedFlashingPlatform
Request[15] = (byte)Mode;
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
{
return null;
@@ -396,7 +396,7 @@ namespace UnifiedFlashingPlatform
return Result == null || Result.Length != 4 ? null : BitConverter.ToUInt32(Result.Reverse().ToArray());
}
public string ReadProcessorManufacturer()
public string? ReadProcessorManufacturer()
{
return ReadStringParam("pm\0\0");
}
@@ -406,17 +406,17 @@ namespace UnifiedFlashingPlatform
//
public uint? ReadSDCardSize()
{
byte[] Bytes = ReadParam("SDS\0");
byte[]? Bytes = ReadParam("SDS\0");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
public string ReadSupportedFFUProtocolInfo()
public string? ReadSupportedFFUProtocolInfo()
{
// TODO
return ReadStringParam("SFPI");
}
public string ReadSMBIOSData()
public string? ReadSMBIOSData()
{
// TODO
return ReadStringParam("SMBD");
@@ -424,7 +424,7 @@ namespace UnifiedFlashingPlatform
public Guid? ReadSerialNumber()
{
byte[] Bytes = ReadParam("SN\0\0");
byte[]? Bytes = ReadParam("SN\0\0");
return Bytes == null || Bytes.Length != 16 ? null : new Guid(Bytes);
}
@@ -433,17 +433,17 @@ namespace UnifiedFlashingPlatform
//
public ulong? ReadSizeOfSystemMemory()
{
byte[] Bytes = ReadParam("SOSM");
byte[]? Bytes = ReadParam("SOSM");
return Bytes == null || Bytes.Length != 8 ? null : BitConverter.ToUInt64(Bytes.Reverse().ToArray());
}
public string ReadSecurityStatus()
public string? ReadSecurityStatus()
{
// TODO
return ReadStringParam("SS\0\0");
}
public string ReadTelemetryLogSize()
public string? ReadTelemetryLogSize()
{
// TODO
return ReadStringParam("TELS");
@@ -451,19 +451,19 @@ namespace UnifiedFlashingPlatform
public uint? ReadTransferSize()
{
byte[] Bytes = ReadParam("TS\0\0");
byte[]? Bytes = ReadParam("TS\0\0");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
//
// Reads the UEFI Boot Flag variable content and returns it as a string.
//
public string ReadUEFIBootFlag()
public string? ReadUEFIBootFlag()
{
return ReadStringParam("UBF\0");
}
public string ReadUEFIBootOptions()
public string? ReadUEFIBootOptions()
{
// TODO
return ReadStringParam("UEBO");
@@ -473,12 +473,12 @@ namespace UnifiedFlashingPlatform
// Reads the device properties from the UEFI Variable "UnlockID"
// in the g_guidOfflineDUIdEfiNamespace namespace and returns it as a string.
//
public string ReadUnlockID()
public string? ReadUnlockID()
{
return ReadStringParam("UKID");
}
public string ReadUnlockTokenFiles()
public string? ReadUnlockTokenFiles()
{
// TODO
return ReadStringParam("UKTF");
@@ -486,7 +486,7 @@ namespace UnifiedFlashingPlatform
public USBSpeed? ReadUSBSpeed()
{
byte[] Bytes = ReadParam("USBS");
byte[]? Bytes = ReadParam("USBS");
return Bytes == null || Bytes.Length != 2
? null
: new USBSpeed()
@@ -498,7 +498,7 @@ namespace UnifiedFlashingPlatform
public uint? ReadWriteBufferSize()
{
byte[] Bytes = ReadParam("WBS\0");
byte[]? Bytes = ReadParam("WBS\0");
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
}
}
+48 -139
View File
@@ -8,15 +8,6 @@ using System.Text;
namespace UnifiedFlashingPlatform
{
internal enum FfuProtocol
{
ProtocolSyncV1 = 1,
ProtocolAsyncV1 = 2,
ProtocolSyncV2 = 4,
ProtocolAsyncV2 = 8,
ProtocolAsyncV3 = 16
}
public partial class UnifiedFlashingPlatformTransport
{
private readonly PhoneInfo Info = new();
@@ -45,11 +36,7 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, HelloSignature);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
if (ByteOperations.ReadAsciiString(Response, 0, 4) != HelloSignature)
{
@@ -94,7 +81,7 @@ namespace UnifiedFlashingPlatform
System.Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
byte[] Buffer = ExecuteRawMethod(Request);
byte[]? Buffer = ExecuteRawMethod(Request);
if ((Buffer == null) || (Buffer.Length < 0x4408))
{
throw new InvalidOperationException("Unable to read GPT!");
@@ -103,7 +90,7 @@ namespace UnifiedFlashingPlatform
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
if (Error > 0)
{
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
throw new NotSupportedException($"ReadGPT: Error 0x{Error:X4}");
}
// Length: 0x4400 for 512 (0x200) Sector Size (from sector 0 to sector 34)
@@ -114,7 +101,7 @@ namespace UnifiedFlashingPlatform
? 512
: Buffer.Length == 0x6008
? (uint)4096
: throw new NotSupportedException("ReadGPT: Unsupported output size! 0x" + ReturnedGPTBufferLength.ToString("X4"));
: throw new NotSupportedException($"ReadGPT: Unsupported output size! 0x{ReturnedGPTBufferLength:X4}");
byte[] GPTBuffer = new byte[ReturnedGPTBufferLength - SectorSize];
System.Buffer.BlockCopy(Buffer, 8 + (int)SectorSize, GPTBuffer, 0, (int)ReturnedGPTBufferLength - (int)SectorSize);
@@ -134,7 +121,7 @@ namespace UnifiedFlashingPlatform
return new GPT(GPTBuffer, SectorSize); // NOKT message header and MBR are ignored
}
private void ThrowFlashError(int ErrorCode)
private static void ThrowFlashError(int ErrorCode)
{
string SubMessage = ErrorCode switch
{
@@ -177,8 +164,11 @@ namespace UnifiedFlashingPlatform
0x0002 => "Flash read failed",
_ => "Unknown error",
};
WPinternalsException Ex = new("Flash failed!");
Ex.SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage;
WPinternalsException Ex = new("Flash failed!")
{
SubMessage = $"Error 0x{ErrorCode:X4}: {SubMessage}"
};
throw Ex;
}
@@ -187,10 +177,10 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[FfuHeader.Length + 0x20];
const string Header = "NOKXFS";
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
string Header = SecureFlashSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes(0x0001, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Request[0x08] = 0; // Progress = 0%
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
Buffer.BlockCopy(BigEndian.GetBytes(0x0000000B, 4), 0, Request, 0x0C, 4); // Subblock type for header = 0x0B
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of header + 0x0C
@@ -200,11 +190,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(FfuHeader, 0, Request, 0x20, FfuHeader.Length);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
int ResultCode = (Response[6] << 8) + Response[7];
if (ResultCode != 0)
@@ -217,10 +203,10 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[FfuHeader.Length + 0x3C];
const string Header = "NOKXFS";
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
string Header = SecureFlashSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes(0x0002, 2), 0, Request, 0x06, 2); // Protocol version = 0x0002
Request[0x08] = 0; // Progress = 0%
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
Buffer.BlockCopy(BigEndian.GetBytes(0x00000021, 4), 0, Request, 0x0C, 4); // Subblock type for header v2 = 0x21
@@ -236,11 +222,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(FfuHeader, 0, Request, 0x3C, FfuHeader.Length);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
if (Response.Length == 4)
{
@@ -258,8 +240,8 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[FfuChunk.Length + 0x1C];
const string Header = "NOKXFS";
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
string Header = SecureFlashSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV1, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
@@ -272,11 +254,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(FfuChunk, 0, Request, 0x1C, FfuChunk.Length);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
int ResultCode = (Response[6] << 8) + Response[7];
if (ResultCode != 0)
@@ -289,8 +267,8 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[FfuChunk.Length + 0x20];
const string Header = "NOKXFS";
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
string Header = SecureFlashSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV2, 2), 0, Request, 0x06, 2); // Protocol
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
@@ -303,11 +281,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(FfuChunk, 0, Request, 0x20, FfuChunk.Length);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
int ResultCode = (Response[6] << 8) + Response[7];
if (ResultCode != 0)
@@ -320,8 +294,8 @@ namespace UnifiedFlashingPlatform
{
byte[] Request = new byte[FfuChunk.Length + 0x20];
const string Header = "NOKXFS";
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
string Header = SecureFlashSignature;
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolAsyncV3, 2), 0, Request, 0x06, 2); // Protocol
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
@@ -336,11 +310,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(FfuChunk, 0, Request, 0x40, FfuChunk.Length);
byte[] Response = ExecuteRawMethod(Request);
if (Response == null)
{
throw new BadConnectionException();
}
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
int ResultCode = (Response[6] << 8) + Response[7];
if (ResultCode != 0)
@@ -349,67 +319,6 @@ namespace UnifiedFlashingPlatform
}
}
public class ProgressUpdater
{
private readonly DateTime InitTime;
private DateTime LastUpdateTime;
private readonly ulong MaxValue;
private readonly Action<int, TimeSpan?> ProgressUpdateCallback;
public int ProgressPercentage;
public ProgressUpdater(ulong MaxValue, Action<int, TimeSpan?> ProgressUpdateCallback)
{
InitTime = DateTime.Now;
LastUpdateTime = DateTime.Now;
this.MaxValue = MaxValue;
this.ProgressUpdateCallback = ProgressUpdateCallback;
SetProgress(0);
}
private ulong _Progress;
public ulong Progress
{
get
{
return _Progress;
}
}
public void SetProgress(ulong NewValue)
{
if (_Progress != NewValue)
{
int PreviousProgressPercentage = (int)((double)_Progress / MaxValue * 100);
ProgressPercentage = (int)((double)NewValue / MaxValue * 100);
_Progress = NewValue;
if (((DateTime.Now - LastUpdateTime) > TimeSpan.FromSeconds(0.5)) || (ProgressPercentage == 100))
{
#if DEBUG
Debug.WriteLine("Init time: " + InitTime.ToShortTimeString() + " / Now: " + DateTime.Now.ToString() + " / NewValue: " + NewValue.ToString() + " / MaxValue: " + MaxValue.ToString() + " ->> Percentage: " + ProgressPercentage.ToString() + " / Remaining: " + TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - ((double)NewValue / MaxValue)))).ToString());
#endif
if (((DateTime.Now - InitTime) < TimeSpan.FromSeconds(30)) && (ProgressPercentage < 15))
{
ProgressUpdateCallback(ProgressPercentage, null);
}
else
{
ProgressUpdateCallback(ProgressPercentage, TimeSpan.FromTicks((long)((DateTime.Now - InitTime).Ticks / ((double)NewValue / MaxValue) * (1 - ((double)NewValue / MaxValue)))));
}
LastUpdateTime = DateTime.Now;
}
}
}
public void IncreaseProgress(ulong Progress)
{
SetProgress(_Progress + Progress);
}
}
public void FlashFFU(string FFUPath, bool ResetAfterwards = true, byte Options = 0)
{
using FileStream FfuFile = new(FFUPath, FileMode.Open, FileAccess.Read);
@@ -421,9 +330,9 @@ namespace UnifiedFlashingPlatform
FlashFFU(FfuFile, null, ResetAfterwards, Options);
}
public void FlashFFU(FileStream FfuFile, ProgressUpdater UpdaterPerChunk, bool ResetAfterwards = true, byte Options = 0)
public void FlashFFU(FileStream FfuFile, ProgressUpdater? UpdaterPerChunk, bool ResetAfterwards = true, byte Options = 0)
{
ProgressUpdater Progress = UpdaterPerChunk;
ProgressUpdater? Progress = UpdaterPerChunk;
PhoneInfo Info = ReadPhoneInfo();
if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV1 | (ushort)FfuProtocol.ProtocolSyncV2)) == 0)
@@ -526,8 +435,8 @@ namespace UnifiedFlashingPlatform
if (Result.State == PhoneInfoState.Empty)
{
byte[] Request = new byte[4];
ByteOperations.WriteAsciiString(Request, 0, "NOKV");
byte[] Response = ExecuteRawMethod(Request);
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
{
Result.App = (FlashAppType)Response[5];
@@ -569,7 +478,7 @@ namespace UnifiedFlashingPlatform
}
break;
case 0x05:
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim(new char[] { ' ', '\0' });
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim([' ', '\0']);
break;
case 0x0D:
Result.AsyncSupport = Response[SubblockPayloadOffset + 1] == 1;
@@ -600,7 +509,7 @@ namespace UnifiedFlashingPlatform
ushort FlashType = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 8);
ushort FlashTypeIndex = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 10);
uint Unknown = BigEndian.ToUInt32(Response, SubblockPayloadOffset + 12);
string DevicePath = ByteOperations.ReadUnicodeString(Response, (uint)SubblockPayloadOffset + 16, (uint)SubblockLength - 16).Trim(new char[] { ' ', '\0' });
string DevicePath = ByteOperations.ReadUnicodeString(Response, (uint)SubblockPayloadOffset + 16, (uint)SubblockLength - 16).Trim([' ', '\0']);
Result.BootDevices.Add((SectorCount, SectorSize, FlashType, FlashTypeIndex, Unknown, DevicePath));
break;
case 0x23:
@@ -683,7 +592,7 @@ namespace UnifiedFlashingPlatform
public uint SdCardSizeInSectors;
public uint WriteBufferSize;
public uint EmmcSizeInSectors;
public string PlatformID;
public string? PlatformID;
public ushort SecureFfuSupportedProtocolMask;
public bool AsyncSupport;
@@ -695,16 +604,16 @@ namespace UnifiedFlashingPlatform
public bool UefiSecureBootEnabled;
public bool SecondaryHardwareKeyPresent;
public string Manufacturer;
public string Family;
public string ProductName;
public string ProductVersion;
public string SKUNumber;
public string BaseboardManufacturer;
public string BaseboardProduct;
public string? Manufacturer;
public string? Family;
public string? ProductName;
public string? ProductVersion;
public string? SKUNumber;
public string? BaseboardManufacturer;
public string? BaseboardProduct;
public ulong LargestMemoryRegion;
public AppType AppType;
public List<(uint SectorCount, uint SectorSize, ushort FlashType, ushort FlashIndex, uint Unknown, string DevicePath)> BootDevices = new();
public List<(uint SectorCount, uint SectorSize, ushort FlashType, ushort FlashIndex, uint Unknown, string DevicePath)> BootDevices = [];
public bool IsBootloaderSecure;
@@ -713,18 +622,18 @@ namespace UnifiedFlashingPlatform
switch (App)
{
case FlashAppType.FlashApp:
Debug.WriteLine("Flash app: " + FlashAppVersionMajor + "." + FlashAppVersionMinor);
Debug.WriteLine("Flash protocol: " + FlashAppProtocolVersionMajor + "." + FlashAppProtocolVersionMinor);
Debug.WriteLine($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}");
Debug.WriteLine($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}");
break;
}
Debug.WriteLine("SecureBoot: " + ((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled") + " (Platform Secure Boot: " + (PlatformSecureBootEnabled ? "Enabled" : "Disabled") + ", UEFI Secure Boot: " + (UefiSecureBootEnabled ? "Enabled" : "Disabled") + ")");
Debug.WriteLine($"SecureBoot: {((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})");
Debug.WriteLine("Flash app security: " + (!IsBootloaderSecure ? "Disabled" : "Enabled"));
Debug.WriteLine($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")}");
Debug.WriteLine("Flash app security: " + (!IsBootloaderSecure ? "Disabled" : "Enabled") + " (FFU security: " + (SecureFfuEnabled ? "Enabled" : "Disabled") + ", RDC: " + (RdcPresent ? "Present" : "Not found") + ", Authenticated: " + (Authenticated ? "True" : "False") + ")");
Debug.WriteLine($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")} (FFU security: {(SecureFfuEnabled ? "Enabled" : "Disabled")}, RDC: {(RdcPresent ? "Present" : "Not found")}, Authenticated: {(Authenticated ? "True" : "False")})");
Debug.WriteLine("JTAG: " + (JtagDisabled ? "Disabled" : "Enabled"));
Debug.WriteLine($"JTAG: {(JtagDisabled ? "Disabled" : "Enabled")}");
}
}
+9 -9
View File
@@ -31,9 +31,9 @@ namespace UnifiedFlashingPlatform
public partial class UnifiedFlashingPlatformTransport : IDisposable
{
private bool Disposed = false;
private readonly USBDevice? USBDevice = null;
private readonly USBPipe? InputPipe = null;
private readonly USBPipe? OutputPipe = null;
private readonly USBDevice USBDevice;
private readonly USBPipe InputPipe;
private readonly USBPipe OutputPipe;
private readonly object UsbLock = new();
public UnifiedFlashingPlatformTransport(string DevicePath)
@@ -59,12 +59,12 @@ namespace UnifiedFlashingPlatform
}
}
public byte[] ExecuteRawMethod(byte[] RawMethod)
public byte[]? ExecuteRawMethod(byte[] RawMethod)
{
return ExecuteRawMethod(RawMethod, RawMethod.Length);
}
public byte[] ExecuteRawMethod(byte[] RawMethod, int 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;
@@ -172,7 +172,7 @@ namespace UnifiedFlashingPlatform
_ = ExecuteRawMethod(Request);
}
public byte[] Echo(byte[] DataPayload)
public byte[]? Echo(byte[] DataPayload)
{
byte[] Request = new byte[10 + DataPayload.Length];
string Header = EchoSignature; // NOKXCE
@@ -181,7 +181,7 @@ namespace UnifiedFlashingPlatform
Buffer.BlockCopy(BitConverter.GetBytes(DataPayload.Length).Reverse().ToArray(), 0, Request, 6, 4);
Buffer.BlockCopy(DataPayload, 0, Request, 10, DataPayload.Length);
byte[] Response = ExecuteRawMethod(Request);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 6 + DataPayload.Length))
{
return null;
@@ -209,7 +209,7 @@ namespace UnifiedFlashingPlatform
}
// WIP!
public string ReadLog()
public string? ReadLog()
{
PhoneInfo Info = ReadPhoneInfo();
@@ -238,7 +238,7 @@ namespace UnifiedFlashingPlatform
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);
byte[]? Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0xC))
{
return null;