mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16:40 +10:00
Preliminary support for UFP
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public enum AppType : byte
|
||||||
|
{
|
||||||
|
Min,
|
||||||
|
UEFI,
|
||||||
|
BOOT,
|
||||||
|
Max
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public enum DeviceLogType
|
||||||
|
{
|
||||||
|
Min,
|
||||||
|
Flashing,
|
||||||
|
Servicing,
|
||||||
|
Max
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public struct DeviceTargetingInfo
|
||||||
|
{
|
||||||
|
public string Manufacturer;
|
||||||
|
public string Family;
|
||||||
|
public string ProductName;
|
||||||
|
public string ProductVersion;
|
||||||
|
public string SKUNumber;
|
||||||
|
public string BaseboardManufacturer;
|
||||||
|
public string BaseboardProduct;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "Manufacturer: " + Manufacturer +
|
||||||
|
" - Family: " + Family +
|
||||||
|
" - Product Name: " + ProductName +
|
||||||
|
" - Product Version: " + ProductVersion +
|
||||||
|
" - SKU Number: " + SKUNumber +
|
||||||
|
" - Baseboard Manufacturer: " + BaseboardManufacturer +
|
||||||
|
" - Baseboard Product: " + BaseboardProduct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
internal enum FfuProtocol
|
||||||
|
{
|
||||||
|
ProtocolSyncV1 = 1,
|
||||||
|
ProtocolAsyncV1 = 2,
|
||||||
|
ProtocolSyncV2 = 4,
|
||||||
|
ProtocolAsyncV2 = 8,
|
||||||
|
ProtocolAsyncV3 = 16
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public struct FlashAppInfo
|
||||||
|
{
|
||||||
|
public byte ProtocolMajorVersion;
|
||||||
|
public byte ProtocolMinorVersion;
|
||||||
|
public byte ImplementationMajorVersion;
|
||||||
|
public byte ImplementationMinorVersion;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "ProtocolMajorVersion: " + ProtocolMajorVersion +
|
||||||
|
" - ProtocolMinorVersion: " + ProtocolMinorVersion +
|
||||||
|
" - ImplementationMajorVersion: " + ImplementationMajorVersion +
|
||||||
|
" - ImplementationMinorVersion: " + ImplementationMinorVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public enum Mode : byte
|
||||||
|
{
|
||||||
|
DiagnosticMode,
|
||||||
|
Max
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public struct ResetProtectionInfo
|
||||||
|
{
|
||||||
|
public bool IsResetProtectionEnabled;
|
||||||
|
public uint MajorVersion;
|
||||||
|
public uint MinorVersion;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "IsResetProtectionEnabled: " + IsResetProtectionEnabled +
|
||||||
|
" - MajorVersion: " + MajorVersion +
|
||||||
|
" - MinorVersion: " + MinorVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
public struct BOOT_OPTION
|
||||||
|
{
|
||||||
|
public byte BootOrderIndex;
|
||||||
|
public ushort BootOption;
|
||||||
|
public LoadOptionAttribute Attributes;
|
||||||
|
public string Description;
|
||||||
|
public string DevicePath;
|
||||||
|
public string CommandLine;
|
||||||
|
|
||||||
|
public ushort DescriptionStringOffset;
|
||||||
|
public ushort DevicePathStringOffset;
|
||||||
|
public ushort CommandLineStringOffset;
|
||||||
|
public ushort TotalSize;
|
||||||
|
|
||||||
|
public static BOOT_OPTION ReadFromBuffer(byte[] Buffer, int offset)
|
||||||
|
{
|
||||||
|
byte BootOrderIndex = Buffer[offset];
|
||||||
|
var Attributes = (LoadOptionAttribute)BigEndian.ToUInt32(Buffer, offset + 1);
|
||||||
|
ushort BootOption = BigEndian.ToUInt16(Buffer, offset + 5);
|
||||||
|
// Latest
|
||||||
|
ushort DescriptionStringOffset = BigEndian.ToUInt16(Buffer, offset + 7);
|
||||||
|
ushort DevicePathStringOffset = BigEndian.ToUInt16(Buffer, offset + 9);
|
||||||
|
ushort CommandLineStringOffset = BigEndian.ToUInt16(Buffer, offset + 11);
|
||||||
|
ushort TotalSize = BigEndian.ToUInt16(Buffer, offset + 13);
|
||||||
|
|
||||||
|
string Description = Encoding.Unicode.GetString(Buffer, offset + DescriptionStringOffset, DevicePathStringOffset - DescriptionStringOffset);
|
||||||
|
string DevicePath;
|
||||||
|
string CommandLine = "";
|
||||||
|
|
||||||
|
if (CommandLineStringOffset == 0)
|
||||||
|
{
|
||||||
|
DevicePath = Encoding.Unicode.GetString(Buffer, offset + DevicePathStringOffset, TotalSize - DevicePathStringOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DevicePath = Encoding.Unicode.GetString(Buffer, offset + DevicePathStringOffset, CommandLineStringOffset - DevicePathStringOffset);
|
||||||
|
CommandLine = Encoding.Unicode.GetString(Buffer, offset + CommandLineStringOffset, TotalSize - CommandLineStringOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Older
|
||||||
|
/*ushort DescriptionStringLength = BigEndian.ToUInt16(Buffer, offset + 7);
|
||||||
|
ushort DevicePathStringLength = BigEndian.ToUInt16(Buffer, offset + 9);
|
||||||
|
|
||||||
|
string Description = Encoding.Unicode.GetString(Buffer, offset + 11, DescriptionStringLength);
|
||||||
|
string DevicePath = Encoding.Unicode.GetString(Buffer, offset + 11 + DescriptionStringLength, DevicePathStringLength);
|
||||||
|
string CommandLine = "";
|
||||||
|
|
||||||
|
ushort DescriptionStringOffset = 11;
|
||||||
|
ushort DevicePathStringOffset = (ushort)(11 + DescriptionStringLength);
|
||||||
|
ushort CommandLineStringOffset = 0;
|
||||||
|
ushort TotalSize = (ushort)(11 + DescriptionStringLength + DevicePathStringLength);*/
|
||||||
|
|
||||||
|
return new BOOT_OPTION()
|
||||||
|
{
|
||||||
|
BootOrderIndex = BootOrderIndex,
|
||||||
|
Attributes = Attributes,
|
||||||
|
BootOption = BootOption,
|
||||||
|
Description = Description,
|
||||||
|
DevicePath = DevicePath,
|
||||||
|
CommandLine = CommandLine,
|
||||||
|
DescriptionStringOffset = DescriptionStringOffset,
|
||||||
|
DevicePathStringOffset = DevicePathStringOffset,
|
||||||
|
CommandLineStringOffset = CommandLineStringOffset,
|
||||||
|
TotalSize = TotalSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "BootOrderIndex: " + BootOrderIndex +
|
||||||
|
" - Attributes: " + Attributes +
|
||||||
|
" - BootOption: " + BootOption +
|
||||||
|
" - Description: " + Description +
|
||||||
|
" - DevicePath: " + DevicePath +
|
||||||
|
" - CommandLine: " + CommandLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
public struct FILE_INFO
|
||||||
|
{
|
||||||
|
public ulong Size;
|
||||||
|
public ulong FileSize;
|
||||||
|
public ulong PhysicalSize;
|
||||||
|
public UefiDateTime CreateTime;
|
||||||
|
public UefiDateTime LastAccessTime;
|
||||||
|
public UefiDateTime ModificationTime;
|
||||||
|
public FileAttribute Attribute;
|
||||||
|
public string FileName;
|
||||||
|
|
||||||
|
public static FILE_INFO ReadFromBuffer(byte[] Buffer, int offset)
|
||||||
|
{
|
||||||
|
ulong size = BitConverter.ToUInt64(Buffer, offset);
|
||||||
|
ulong fileSize = BitConverter.ToUInt64(Buffer, offset + 8);
|
||||||
|
ulong physicalSize = BitConverter.ToUInt64(Buffer, offset + 16);
|
||||||
|
UefiDateTime createTime = UefiDateTime.ReadFromBuffer(Buffer, offset + 24);
|
||||||
|
UefiDateTime lastAccessTime = UefiDateTime.ReadFromBuffer(Buffer, offset + 40);
|
||||||
|
UefiDateTime modificationTime = UefiDateTime.ReadFromBuffer(Buffer, offset + 56);
|
||||||
|
ulong attribute = BitConverter.ToUInt64(Buffer, offset + 72);
|
||||||
|
string fileName = Encoding.Unicode.GetString(Buffer, offset + 80, (int)(size - 80));
|
||||||
|
|
||||||
|
return new FILE_INFO()
|
||||||
|
{
|
||||||
|
Size = size,
|
||||||
|
FileSize = fileSize,
|
||||||
|
PhysicalSize = physicalSize,
|
||||||
|
CreateTime = createTime,
|
||||||
|
LastAccessTime = lastAccessTime,
|
||||||
|
ModificationTime = modificationTime,
|
||||||
|
Attribute = (FileAttribute)attribute,
|
||||||
|
FileName = fileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "Size: " + Size +
|
||||||
|
"- File Size: " + FileSize +
|
||||||
|
"- Physical Size: " + PhysicalSize +
|
||||||
|
"- Create Time: " + CreateTime.ToDateTime() +
|
||||||
|
"- Last Access Time: " + LastAccessTime.ToDateTime() +
|
||||||
|
"- Modification Time: " + ModificationTime.ToDateTime() +
|
||||||
|
"- Attribute: " + Attribute +
|
||||||
|
"- FileName: " + FileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum FileAttribute : ulong
|
||||||
|
{
|
||||||
|
EfiFileReadOnly = 1UL,
|
||||||
|
EfiFileHidden = 2UL,
|
||||||
|
EfiFileSystem = 4UL,
|
||||||
|
EfiFileReserved = 8UL,
|
||||||
|
EfiFileDirectory = 16UL,
|
||||||
|
EfiFileArchive = 32UL,
|
||||||
|
EfiFileValidAttr = 55UL
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum LoadOptionAttribute : uint
|
||||||
|
{
|
||||||
|
LoadOptionCategoryBoot = 0U,
|
||||||
|
LoadOptionActive = 1U,
|
||||||
|
LoadOptionForceReconnect = 2U,
|
||||||
|
LoadOptionHidden = 8U,
|
||||||
|
LoadOptionCategoryApp = 256U,
|
||||||
|
LoadOptionCategory = 7936U
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
public struct UefiDateTime
|
||||||
|
{
|
||||||
|
public ushort year;
|
||||||
|
public byte month;
|
||||||
|
public byte day;
|
||||||
|
public byte hour;
|
||||||
|
public byte minute;
|
||||||
|
public byte second;
|
||||||
|
public uint nanosecond;
|
||||||
|
public short timezone;
|
||||||
|
public byte daylight;
|
||||||
|
|
||||||
|
public static UefiDateTime ReadFromBuffer(byte[] Buffer, int offset)
|
||||||
|
{
|
||||||
|
ushort year = BitConverter.ToUInt16(Buffer, offset);
|
||||||
|
byte month = Buffer[offset + 2];
|
||||||
|
byte day = Buffer[offset + 3];
|
||||||
|
byte hour = Buffer[offset + 4];
|
||||||
|
byte minute = Buffer[offset + 5];
|
||||||
|
byte second = Buffer[offset + 6];
|
||||||
|
uint nanosecond = BitConverter.ToUInt32(Buffer, offset + 8);
|
||||||
|
short timezone = BitConverter.ToInt16(Buffer, offset + 12);
|
||||||
|
byte daylight = Buffer[offset + 14];
|
||||||
|
|
||||||
|
return new UefiDateTime()
|
||||||
|
{
|
||||||
|
year = year,
|
||||||
|
month = month,
|
||||||
|
day = day,
|
||||||
|
hour = hour,
|
||||||
|
minute = minute,
|
||||||
|
second = second,
|
||||||
|
nanosecond = nanosecond,
|
||||||
|
timezone = timezone,
|
||||||
|
daylight = daylight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly DateTime ToDateTime()
|
||||||
|
{
|
||||||
|
DateTime dateTime;
|
||||||
|
|
||||||
|
byte month = this.month == 0 ? (byte)1 : this.month;
|
||||||
|
byte day = this.day == 0 ? (byte)1 : this.day;
|
||||||
|
|
||||||
|
if (timezone == 2047)
|
||||||
|
{
|
||||||
|
dateTime = new DateTime(year, month, day, hour, minute, second, Convert.ToInt32(nanosecond / 1000000U), DateTimeKind.Local);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dateTime = new DateTime(year, month, day, hour, minute, second, Convert.ToInt32(nanosecond / 1000000U), DateTimeKind.Utc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 System;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform.UEFI
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum UefiVariableAttributes : uint
|
||||||
|
{
|
||||||
|
EfiVariableNone,
|
||||||
|
EfiVariableNonVolatile,
|
||||||
|
EfiVariableBootServiceAccess,
|
||||||
|
EfiVariableRuntimeAccess = 4U,
|
||||||
|
EfiVariableHardwareErrorRecord = 8U,
|
||||||
|
EfiVariableAuthenticatedWriteAccess = 16U,
|
||||||
|
EfiVariableTimeBasedAuthenticatedWriteAccess = 32U,
|
||||||
|
EfiVariableAppendWrite = 64U,
|
||||||
|
EfiVariableEnhancedAuthenticatedAccess = 128U
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public struct USBSpeed
|
||||||
|
{
|
||||||
|
public byte CurrentUSBSpeed;
|
||||||
|
public byte MaxUSBSpeed;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "CurrentUSBSpeed: " + CurrentUSBSpeed +
|
||||||
|
" - MaxUSBSpeed: " + MaxUSBSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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 System;
|
||||||
|
using UnifiedFlashingPlatform.UEFI;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public struct UefiVariable
|
||||||
|
{
|
||||||
|
public UefiVariableAttributes Attributes;
|
||||||
|
public uint DataSize;
|
||||||
|
public byte[] Data;
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return "Attributes: " + Attributes +
|
||||||
|
" - DataSize: " + DataSize +
|
||||||
|
" - Data: " + BitConverter.ToString(Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public partial class UnifiedFlashingPlatformModel
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Not valid commands
|
||||||
|
//
|
||||||
|
/* NOK */
|
||||||
|
private const string Signature = "NOK";
|
||||||
|
/* NOKX */
|
||||||
|
private const string ExtendedMessageSignature = $"{Signature}X";
|
||||||
|
/* NOKXC */
|
||||||
|
private const string CommonExtendedMessageSignature = $"{ExtendedMessageSignature}C";
|
||||||
|
/* NOKXF */
|
||||||
|
private const string UFPExtendedMessageSignature = $"{ExtendedMessageSignature}F";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Normal commands
|
||||||
|
//
|
||||||
|
/* NOKF */
|
||||||
|
private const string FlashSignature = $"{Signature}F";
|
||||||
|
/* NOKI */
|
||||||
|
private const string HelloSignature = $"{Signature}I";
|
||||||
|
/* NOKM */
|
||||||
|
private const string MassStorageSignature = $"{Signature}M";
|
||||||
|
/* NOKN */
|
||||||
|
private const string TelemetryEndSignature = $"{Signature}N";
|
||||||
|
/* NOKR */
|
||||||
|
private const string RebootSignature = $"{Signature}R";
|
||||||
|
/* NOKS */
|
||||||
|
private const string TelemetryStartSignature = $"{Signature}S";
|
||||||
|
/* NOKT */
|
||||||
|
private const string GetGPTSignature = $"{Signature}T";
|
||||||
|
/* NOKV */
|
||||||
|
private const string InfoQuerySignature = $"{Signature}V";
|
||||||
|
/* NOKZ */
|
||||||
|
private const string ShutdownSignature = $"{Signature}Z";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Common extended commands
|
||||||
|
//
|
||||||
|
/* NOKXCB */
|
||||||
|
private const string SwitchModeSignature = $"{CommonExtendedMessageSignature}B";
|
||||||
|
/* NOKXCC */
|
||||||
|
private const string ClearScreenSignature = $"{CommonExtendedMessageSignature}C";
|
||||||
|
/* NOKXCD */
|
||||||
|
private const string GetDirectoryEntriesSignature = $"{CommonExtendedMessageSignature}D";
|
||||||
|
/* NOKXCE */
|
||||||
|
private const string EchoSignature = $"{CommonExtendedMessageSignature}E";
|
||||||
|
/* NOKXCF */
|
||||||
|
private const string GetFileSignature = $"{CommonExtendedMessageSignature}F";
|
||||||
|
/* NOKXCM */
|
||||||
|
private const string DisplayCustomMessageSignature = $"{CommonExtendedMessageSignature}M";
|
||||||
|
/* NOKXCP */
|
||||||
|
private const string PutFileSignature = $"{CommonExtendedMessageSignature}P";
|
||||||
|
/* NOKXCT */
|
||||||
|
private const string BenchmarkTestsSignature = $"{CommonExtendedMessageSignature}T";
|
||||||
|
|
||||||
|
//
|
||||||
|
// UFP extended commands
|
||||||
|
//
|
||||||
|
/* NOKXFF */
|
||||||
|
private const string AsyncFlashModeSignature = $"{UFPExtendedMessageSignature}F";
|
||||||
|
/* NOKXFI */
|
||||||
|
private const string UnlockSignature = $"{UFPExtendedMessageSignature}I";
|
||||||
|
/* NOKXFO */
|
||||||
|
private const string RelockSignature = $"{UFPExtendedMessageSignature}O";
|
||||||
|
/* NOKXFR */
|
||||||
|
private const string ReadParamSignature = $"{UFPExtendedMessageSignature}R";
|
||||||
|
/* NOKXFS */
|
||||||
|
private const string SecureFlashSignature = $"{UFPExtendedMessageSignature}S";
|
||||||
|
/* NOKXFT */
|
||||||
|
private const string TelemetryReadSignature = $"{UFPExtendedMessageSignature}T";
|
||||||
|
/* NOKXFW */
|
||||||
|
private const string WriteParamSignature = $"{UFPExtendedMessageSignature}W";
|
||||||
|
/* NOKXFX */
|
||||||
|
private const string GetLogsSignature = $"{UFPExtendedMessageSignature}X";
|
||||||
|
|
||||||
|
//
|
||||||
|
// UFP Read Params
|
||||||
|
//
|
||||||
|
private const string AppTypeReadParamSignature = "APPT";
|
||||||
|
private const string ResetProtectionReadParamSignature = "ATRP";
|
||||||
|
private const string BitlockerStateReadParamSignature = "BITL";
|
||||||
|
private const string BuildInfoReadParamSignature = "BNFO";
|
||||||
|
private const string CurrentBootOptionReadParamSignature = "CUFO";
|
||||||
|
private const string AsyncProtocolSupportReadParamSignature = "DAS\0";
|
||||||
|
private const string DirectoryEntriesSizeReadParamSignature = "DES\0";
|
||||||
|
private const string DevicePlatformIDReadParamSignature = "DPI\0";
|
||||||
|
private const string DevicePropertiesReadParamSignature = "DPR\0";
|
||||||
|
private const string DeviceTargetInfoReadParamSignature = "DTI\0";
|
||||||
|
private const string DataVerifySpeedReadParamSignature = "DTSP";
|
||||||
|
private const string DeviceIDReadParamSignature = "DUI\0";
|
||||||
|
private const string EMMCTestResultReadParamSignature = "EMMT";
|
||||||
|
private const string EMMCSizeReadParamSignature = "EMS\0";
|
||||||
|
private const string EMMCWriteSpeedReadParamSignature = "EMWS";
|
||||||
|
private const string FlashAppInfoReadParamSignature = "FAI\0";
|
||||||
|
private const string FlashAppOptionsReadParamSignature = "FO\0\0";
|
||||||
|
private const string FlashingStatusReadParamSignature = "FS\0\0";
|
||||||
|
private const string FileSizeReadParamSignature = "FZ\0\0";
|
||||||
|
private const string SecureBootStatusReadParamSignature = "GSBS";
|
||||||
|
private const string GetUEFIVariableReadParamSignature = "GUFV";
|
||||||
|
private const string GetUEFIVariableSizeReadParamSignature = "GUVS";
|
||||||
|
private const string LargestMemoryRegionReadParamSignature = "LGMR";
|
||||||
|
private const string LogSizeReadParamSignature = "LZ\0\0";
|
||||||
|
private const string MACAddressReadParamSignature = "MAC\0";
|
||||||
|
private const string ModeDataReadParamSignature = "MODE";
|
||||||
|
private const string ProcessorManufacturerReadParamSignature = "pm\0\0";
|
||||||
|
private const string SDCardSizeReadParamSignature = "SDS\0";
|
||||||
|
private const string SupportedSecureFFUProtocolsReadParamSignature = "SFPI";
|
||||||
|
private const string SMBIOSDataReadParamSignature = "SMBD";
|
||||||
|
private const string SerialNumberReadParamSignature = "SN\0\0";
|
||||||
|
private const string SizeOfSystemMemoryReadParamSignature = "SOSM";
|
||||||
|
private const string SecurityStatusReadParamSignature = "SS\0\0";
|
||||||
|
private const string TelemetryLogSizeReadParamSignature = "TELS";
|
||||||
|
private const string TransferSizeReadParamSignature = "TS\0\0";
|
||||||
|
private const string UEFIBootFlagReadParamSignature = "UBF\0";
|
||||||
|
private const string UEFIBootOptionsReadParamSignature = "UEBO";
|
||||||
|
private const string UnlockIDReadParamSignature = "UKID";
|
||||||
|
private const string UnlockTokenFilesReadParamSignature = "UKTF";
|
||||||
|
private const string USBSpeedReadParamSignature = "USBS";
|
||||||
|
private const string WriteBufferSizeReadParamSignature = "WBS\0";
|
||||||
|
|
||||||
|
//
|
||||||
|
// UFP Write Params
|
||||||
|
//
|
||||||
|
private const string BootOptionOptionalDataWriteParamSignature = "BOCL";
|
||||||
|
private const string BootOptionAsFirstEntryWriteParamSignature = "BOF\0";
|
||||||
|
private const string BootOptionAsLastEntryWriteParamSignature = "BOL\0";
|
||||||
|
private const string FlashOptionsWriteParamSignature = "FO\0\0";
|
||||||
|
private const string LogInsertWriteParamSignature = "LI\0\0";
|
||||||
|
private const string ModeWriteParamSignature = "MODE";
|
||||||
|
private const string OneTimeBootSequenceWriteParamSignature = "OBU\0";
|
||||||
|
private const string SettingUEFIVariableWriteParamSignature = "SUFV";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,534 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnifiedFlashingPlatform.UEFI;
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public partial class UnifiedFlashingPlatformModel
|
||||||
|
{
|
||||||
|
public byte[]? ReadParam(string Param)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x0B];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
|
||||||
|
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);
|
||||||
|
if ((Response == null) || (Response.Length < 0x10))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Result = new byte[Response[0x10]];
|
||||||
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadStringParam(string Param)
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(Param);
|
||||||
|
return Bytes == null ? null : Encoding.ASCII.GetString(Bytes).Trim('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppType ReadAppType()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(AppTypeReadParamSignature);
|
||||||
|
return Bytes == null ? AppType.Min : Bytes[0] == 1 ? AppType.UEFI : AppType.Min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResetProtectionInfo? ReadResetProtection()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(ResetProtectionReadParamSignature);
|
||||||
|
return Bytes == null
|
||||||
|
? null
|
||||||
|
: 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(BitlockerStateReadParamSignature);
|
||||||
|
return Bytes == null ? null : Bytes[0] == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadBuildInfo()
|
||||||
|
{
|
||||||
|
return ReadStringParam(BuildInfoReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort? ReadCurrentBootOption()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(CurrentBootOptionReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 2 ? null : BitConverter.ToUInt16(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool? ReadDeviceAsyncSupport()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(AsyncProtocolSupportReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 2 ? null : BitConverter.ToUInt16(Bytes.Reverse().ToArray()) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong? ReadDirectoryEntriesSize(string PartitionName, string DirectoryName)
|
||||||
|
{
|
||||||
|
if (PartitionName.Length > 35)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] PartitionNameBuffer = Encoding.Unicode.GetBytes(PartitionName);
|
||||||
|
byte[] DirectoryNameBuffer = Encoding.Unicode.GetBytes(DirectoryName);
|
||||||
|
|
||||||
|
byte[] Request = new byte[87 + DirectoryNameBuffer.Length + 2];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
const string Param = DirectoryEntriesSizeReadParamSignature;
|
||||||
|
|
||||||
|
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(DirectoryNameBuffer, 0, Request, 87, DirectoryNameBuffer.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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadDevicePlatformID()
|
||||||
|
{
|
||||||
|
return ReadStringParam(DevicePlatformIDReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reads the device properties from the UEFI Variable "MSRuntimeDeviceProperties"
|
||||||
|
// in the g_guidMSRuntimeDeviceProperties namespace and returns it as a string.
|
||||||
|
//
|
||||||
|
public string? ReadDeviceProperties()
|
||||||
|
{
|
||||||
|
return ReadStringParam(DevicePropertiesReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceTargetingInfo? ReadDeviceTargetInfo()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(DeviceTargetInfoReadParamSignature);
|
||||||
|
if (Bytes == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort ManufacturerLength = BitConverter.ToUInt16(Bytes[0..2].Reverse().ToArray());
|
||||||
|
ushort FamilyLength = BitConverter.ToUInt16(Bytes[2..4].Reverse().ToArray());
|
||||||
|
ushort ProductNameLength = BitConverter.ToUInt16(Bytes[4..6].Reverse().ToArray());
|
||||||
|
ushort ProductVersionLength = BitConverter.ToUInt16(Bytes[6..8].Reverse().ToArray());
|
||||||
|
ushort SKUNumberLength = BitConverter.ToUInt16(Bytes[8..10].Reverse().ToArray());
|
||||||
|
ushort BaseboardManufacturerLength = BitConverter.ToUInt16(Bytes[10..12].Reverse().ToArray());
|
||||||
|
ushort BaseboardProductLength = BitConverter.ToUInt16(Bytes[12..14].Reverse().ToArray());
|
||||||
|
|
||||||
|
int 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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Gets the last FFU Flash Operation Data verify speed in KB/s
|
||||||
|
//
|
||||||
|
public uint? ReadDataVerifySpeed()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(DataVerifySpeedReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid? ReadDeviceID()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(DeviceIDReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 16 ? null : new Guid(Bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadEmmcTestResult()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(EMMCTestResultReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Gets the eMMC Size in sectors, if present
|
||||||
|
//
|
||||||
|
public uint? ReadEmmcSize()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(EMMCSizeReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Gets the eMMC Write speed in KB/s
|
||||||
|
//
|
||||||
|
public uint? ReadEmmcWriteSpeed()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(EMMCWriteSpeedReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlashAppInfo? ReadFlashAppInfo()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(FlashAppInfoReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 6 || Bytes[0] != 2
|
||||||
|
? null
|
||||||
|
: new FlashAppInfo()
|
||||||
|
{
|
||||||
|
ProtocolMajorVersion = Bytes[1],
|
||||||
|
ProtocolMinorVersion = Bytes[2],
|
||||||
|
ImplementationMajorVersion = Bytes[3],
|
||||||
|
ImplementationMinorVersion = Bytes[4]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reads the device properties from the UEFI Variable "FfuConfigurationOptions"
|
||||||
|
// in the g_guidLumiaGuid namespace and returns it as a string.
|
||||||
|
//
|
||||||
|
public string? ReadFlashOptions()
|
||||||
|
{
|
||||||
|
return ReadStringParam(FlashAppOptionsReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadFlashingStatus()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(FlashingStatusReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong? ReadFileSize(string PartitionName, string FileName)
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
const string Param = FileSizeReadParamSignature;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool? ReadSecureBootStatus()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(SecureBootStatusReadParamSignature);
|
||||||
|
return Bytes == null ? null : Bytes[0] == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UefiVariable? ReadUEFIVariable(Guid Guid, string Name, uint Size)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[39 + ((Name.Length + 1) * 2)];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
string Param = GetUEFIVariableReadParamSignature;
|
||||||
|
|
||||||
|
byte[] VariableNameBuffer = Encoding.Unicode.GetBytes(Name);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Guid.ToByteArray(), 0, Request, 15, 16);
|
||||||
|
Buffer.BlockCopy(BitConverter.GetBytes(Size).Reverse().ToArray(), 0, Request, 31, 4);
|
||||||
|
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);
|
||||||
|
if ((Response == null) || (Response.Length < 0x10))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Result = new byte[Response[0x10]];
|
||||||
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
||||||
|
|
||||||
|
return new UefiVariable()
|
||||||
|
{
|
||||||
|
Attributes = (UefiVariableAttributes)BitConverter.ToUInt32(Result[0..4].Reverse().ToArray()),
|
||||||
|
DataSize = BitConverter.ToUInt32(Result[4..8].Reverse().ToArray()),
|
||||||
|
Data = Result[8..^0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadUEFIVariableSize(Guid Guid, string Name)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[39 + ((Name.Length + 1) * 2)];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
string Param = GetUEFIVariableSizeReadParamSignature;
|
||||||
|
|
||||||
|
byte[] VariableNameBuffer = Encoding.Unicode.GetBytes(Name);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Guid.ToByteArray(), 0, Request, 15, 16);
|
||||||
|
|
||||||
|
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);
|
||||||
|
if ((Response == null) || (Response.Length < 0x10))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Result = new byte[Response[0x10]];
|
||||||
|
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
|
||||||
|
return Result == null || Result.Length != 4 ? null : BitConverter.ToUInt32(Result.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Returns the largest memory region in bytes available for use by UFP
|
||||||
|
//
|
||||||
|
public ulong? ReadLargestMemoryRegion()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(LargestMemoryRegionReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 8 ? null : BitConverter.ToUInt64(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong? ReadLogSize(DeviceLogType LogType)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x10];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
const string Param = LogSizeReadParamSignature;
|
||||||
|
|
||||||
|
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()], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reads the MAC Address in the following format: "%02x-%02x-%02x-%02x-%02x-%02x"
|
||||||
|
//
|
||||||
|
public string? ReadMacAddress()
|
||||||
|
{
|
||||||
|
return ReadStringParam(MACAddressReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadModeData(Mode Mode)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x10];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
string Param = ModeDataReadParamSignature;
|
||||||
|
|
||||||
|
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)Mode;
|
||||||
|
|
||||||
|
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 Result == null || Result.Length != 4 ? null : BitConverter.ToUInt32(Result.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadProcessorManufacturer()
|
||||||
|
{
|
||||||
|
return ReadStringParam(ProcessorManufacturerReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Gets the SD Card Size in sectors, if present
|
||||||
|
//
|
||||||
|
public uint? ReadSDCardSize()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(SDCardSizeReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadSupportedFFUProtocolInfo()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ReadStringParam(SupportedSecureFFUProtocolsReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadSMBIOSData()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ReadStringParam(SMBIOSDataReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid? ReadSerialNumber()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(SerialNumberReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 16 ? null : new Guid(Bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Returns the size of system memory in kB
|
||||||
|
//
|
||||||
|
public ulong? ReadSizeOfSystemMemory()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(SizeOfSystemMemoryReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 8 ? null : BitConverter.ToUInt64(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadSecurityStatus()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ReadStringParam(SecurityStatusReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadTelemetryLogSize()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ReadStringParam(TelemetryLogSizeReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadTransferSize()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(TransferSizeReadParamSignature);
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
return ReadStringParam(UEFIBootFlagReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BOOT_OPTION[]? ReadUEFIBootOptions()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x0B];
|
||||||
|
const string Header = ReadParamSignature; // NOKXFR
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(UEFIBootOptionsReadParamSignature), 0, Request, 7, UEFIBootOptionsReadParamSignature.Length);
|
||||||
|
|
||||||
|
byte[]? Response = ExecuteRawMethod(Request);
|
||||||
|
if ((Response == null) || (Response.Length < 0x10))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ResponseBuffer = Response[0x19..];
|
||||||
|
|
||||||
|
List<BOOT_OPTION> bootOptions = [];
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
while (j != ResponseBuffer.Length)
|
||||||
|
{
|
||||||
|
BOOT_OPTION bootOption = BOOT_OPTION.ReadFromBuffer(ResponseBuffer, j);
|
||||||
|
j += bootOption.TotalSize;
|
||||||
|
|
||||||
|
bootOptions.Add(bootOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [.. bootOptions];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reads the device properties from the UEFI Variable "UnlockID"
|
||||||
|
// in the g_guidOfflineDUIdEfiNamespace namespace and returns it as a string.
|
||||||
|
//
|
||||||
|
public byte[] ReadUnlockID()
|
||||||
|
{
|
||||||
|
return ReadParam(UnlockIDReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ReadUnlockTokenFiles()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return ReadStringParam(UnlockTokenFilesReadParamSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public USBSpeed? ReadUSBSpeed()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(USBSpeedReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 2
|
||||||
|
? null
|
||||||
|
: new USBSpeed()
|
||||||
|
{
|
||||||
|
CurrentUSBSpeed = Bytes[0],
|
||||||
|
MaxUSBSpeed = Bytes[1]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint? ReadWriteBufferSize()
|
||||||
|
{
|
||||||
|
byte[]? Bytes = ReadParam(WriteBufferSizeReadParamSignature);
|
||||||
|
return Bytes == null || Bytes.Length != 4 ? null : BitConverter.ToUInt32(Bytes.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,543 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using WPinternals;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public partial class UnifiedFlashingPlatformModel
|
||||||
|
{
|
||||||
|
private readonly PhoneInfo Info = new();
|
||||||
|
|
||||||
|
public void FlashSectors(uint StartSector, byte[] Data, byte TargetDevice = 0, int Progress = 0)
|
||||||
|
{
|
||||||
|
// Start sector is in UInt32, so max size of eMMC is 2 TB.
|
||||||
|
|
||||||
|
byte[] Request = new byte[Data.Length + 0x40];
|
||||||
|
|
||||||
|
const string Header = FlashSignature; // NOKF
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Request[0x05] = TargetDevice; // Target device: 0: eMMC, 1: SDIO, 2: Other ???, 3: ???
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(StartSector, 4), 0, Request, 0x0B, 4); // Start sector
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(Data.Length / 0x200, 4), 0, Request, 0x0F, 4); // Sector count
|
||||||
|
Request[0x13] = (byte)Progress; // Progress (0 - 100)
|
||||||
|
Request[0x18] = 0; // Verify needed
|
||||||
|
Request[0x19] = 0; // Skip write
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Data, 0, Request, 0x40, Data.Length);
|
||||||
|
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Hello()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
ByteOperations.WriteAsciiString(Request, 0, HelloSignature);
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
if (ByteOperations.ReadAsciiString(Response, 0, 4) != HelloSignature)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Bad response from phone!", "The phone did not answer properly to the Hello message sent.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetPhone()
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Rebooting phone");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Sending reset-request failed");
|
||||||
|
Debug.WriteLine("Assuming automatic reset already in progress");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GPT ReadGPT()
|
||||||
|
{
|
||||||
|
// If this function is used with a locked BootMgr v1,
|
||||||
|
// then the mode-switching should be done outside this function,
|
||||||
|
// because the context-switches that are used here are not supported on BootMgr v1.
|
||||||
|
|
||||||
|
// Only works in BootLoader-mode or on unlocked bootloaders in Flash-mode!!
|
||||||
|
|
||||||
|
/*PhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
|
||||||
|
FlashAppType OriginalAppType = Info.App;
|
||||||
|
bool Switch = (Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure;
|
||||||
|
if (Switch)
|
||||||
|
{
|
||||||
|
SwitchToBootManagerContext();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
byte[] Request = new byte[0x04];
|
||||||
|
const string Header = GetGPTSignature;
|
||||||
|
|
||||||
|
System.Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
|
||||||
|
byte[]? Buffer = ExecuteRawMethod(Request);
|
||||||
|
if ((Buffer == null) || (Buffer.Length < 0x4408))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Unable to read GPT!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort Error = (ushort)((Buffer[6] << 8) + Buffer[7]);
|
||||||
|
if (Error > 0)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"ReadGPT: Error 0x{Error:X4}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length: 0x4400 for 512 (0x200) Sector Size (from sector 0 to sector 34)
|
||||||
|
// Length: 0x6000 for 4096 (0x1000) Sector Size (from sector 0 to sector 6)
|
||||||
|
|
||||||
|
uint ReturnedGPTBufferLength = (uint)Buffer.Length - 8;
|
||||||
|
uint SectorSize = Buffer.Length == 0x4408
|
||||||
|
? 512
|
||||||
|
: Buffer.Length == 0x6008
|
||||||
|
? (uint)4096
|
||||||
|
: 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);
|
||||||
|
|
||||||
|
/*if (Switch)
|
||||||
|
{
|
||||||
|
if (OriginalAppType == FlashAppType.FlashApp)
|
||||||
|
{
|
||||||
|
SwitchToFlashAppContext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SwitchToPhoneInfoAppContext();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return new GPT(GPTBuffer);//, SectorSize); // NOKT message header and MBR are ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ThrowFlashError(int ErrorCode)
|
||||||
|
{
|
||||||
|
string SubMessage = ErrorCode switch
|
||||||
|
{
|
||||||
|
0x0008 => "Unsupported protocol / Invalid options",
|
||||||
|
0x000F => "Invalid sub block count",
|
||||||
|
0x0010 => "Invalid sub block length",
|
||||||
|
0x0012 => "Authentication required",
|
||||||
|
0x000E => "Invalid sub block type",
|
||||||
|
0x0013 => "Failed async message",
|
||||||
|
0x1000 => "Invalid header type",
|
||||||
|
0x1001 => "FFU header contain unknown extra data",
|
||||||
|
0x0001 => "Couldn't allocate memory",
|
||||||
|
0x1106 => "Security header validation failed",
|
||||||
|
0x1105 => "Invalid hash table size",
|
||||||
|
0x1104 => "Invalid catalog size",
|
||||||
|
0x1103 => "Invalid chunk size",
|
||||||
|
0x1102 => "Unsupported algorithm",
|
||||||
|
0x1101 => "Invalid struct size",
|
||||||
|
0x1100 => "Invalid signature",
|
||||||
|
0x1202 => "Invalid struct size",
|
||||||
|
0x1203 => "Unsupported algorithm",
|
||||||
|
0x1204 => "Invalid chunk size",
|
||||||
|
0x1005 => "Data not aligned correctly",
|
||||||
|
0x0009 => "Locate protocol failed",
|
||||||
|
0x1003 => "Hash mismatch",
|
||||||
|
0x1006 => "Couldn't find hash from security header for index",
|
||||||
|
0x1004 => "Security header import missing / All FFU headers have not been imported",
|
||||||
|
0x1304 => "Invalid platform ID",
|
||||||
|
0x1307 => "Invalid write descriptor info",
|
||||||
|
0x1306 => "Invalid write descriptor info",
|
||||||
|
0x1305 => "Invalid block size",
|
||||||
|
0x1303 => "Unsupported FFU version",
|
||||||
|
0x1302 => "Unsupported struct version",
|
||||||
|
0x1301 => "Invalid update type",
|
||||||
|
0x100B => "Too much payload data, all data has already been written",
|
||||||
|
0x1008 => "Internal error",
|
||||||
|
0x1007 => "Payload data does not contain all data",
|
||||||
|
0x0004 => "Flash write failed",
|
||||||
|
0x000D => "Flash verify failed",
|
||||||
|
0x0002 => "Flash read failed",
|
||||||
|
_ => "Unknown error",
|
||||||
|
};
|
||||||
|
|
||||||
|
WPinternalsException Ex = new("Flash failed!")
|
||||||
|
{
|
||||||
|
SubMessage = $"Error 0x{ErrorCode:X4}: {SubMessage}"
|
||||||
|
};
|
||||||
|
|
||||||
|
throw Ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendFfuHeaderV1(byte[] FfuHeader, int Progress = 0, byte Options = 0)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[FfuHeader.Length + 0x20];
|
||||||
|
|
||||||
|
const 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] = (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
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x18, 4); // Payload length = length of header
|
||||||
|
Request[0x1C] = Options; // Header options = 0
|
||||||
|
|
||||||
|
Buffer.BlockCopy(FfuHeader, 0, Request, 0x20, FfuHeader.Length);
|
||||||
|
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendFfuHeaderV2(uint TotalHeaderLength, uint OffsetForThisPart, byte[] FfuHeader, int Progress = 0, byte Options = 0)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[FfuHeader.Length + 0x3C];
|
||||||
|
|
||||||
|
const 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] = (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
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x28, 4), 0, Request, 0x10, 4); // Subblock starts at 0x14, payload starts at 0x3C.
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(TotalHeaderLength, 4), 0, Request, 0x18, 4); // Payload length = length of header
|
||||||
|
Request[0x1C] = Options; // Header options = 0
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(OffsetForThisPart, 4), 0, Request, 0x1D, 4);
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x21, 4);
|
||||||
|
Request[0x25] = 0; // No Erase
|
||||||
|
|
||||||
|
Buffer.BlockCopy(FfuHeader, 0, Request, 0x3C, FfuHeader.Length);
|
||||||
|
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
if (Response.Length == 4)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Flash protocol v2 not supported", "The device reported that the Flash protocol v2 was not supported while sending the FFU header.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendFfuPayloadV1(byte[] FfuChunk, int Progress = 0, byte Options = 0)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[FfuChunk.Length + 0x1C];
|
||||||
|
|
||||||
|
const 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
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(0x0000000C, 4), 0, Request, 0x0C, 4); // Subblock type for ChunkData = 0x0C
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x08, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
|
||||||
|
Request[0x18] = Options; // Data options = 0 (1 = verify)
|
||||||
|
|
||||||
|
Buffer.BlockCopy(FfuChunk, 0, Request, 0x1C, FfuChunk.Length);
|
||||||
|
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendFfuPayloadV2(byte[] FfuChunk, int Progress = 0, byte Options = 0)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[FfuChunk.Length + 0x20];
|
||||||
|
|
||||||
|
const 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
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(0x0000001B, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
|
||||||
|
Request[0x18] = Options; // Data options = 0 (1 = verify)
|
||||||
|
|
||||||
|
Buffer.BlockCopy(FfuChunk, 0, Request, 0x20, FfuChunk.Length);
|
||||||
|
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendFfuPayloadV3(byte[] FfuChunk, uint WriteDescriptorIndex, uint CRC, int Progress = 0, byte Options = 0)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[FfuChunk.Length + 0x20];
|
||||||
|
|
||||||
|
const 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
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(0x0000001D, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x2C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
|
||||||
|
Request[0x18] = Options; // Data options = 0 (1 = verify)
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(WriteDescriptorIndex, 4), 0, Request, 0x19, 4); // Payload length = length of chunk
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes(CRC, 4), 0, Request, 0x1D, 4); // Payload length = length of chunk
|
||||||
|
|
||||||
|
Buffer.BlockCopy(FfuChunk, 0, Request, 0x40, FfuChunk.Length);
|
||||||
|
|
||||||
|
byte[] Response = ExecuteRawMethod(Request) ?? throw new BadConnectionException();
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhoneInfo ReadPhoneInfo()
|
||||||
|
{
|
||||||
|
// NOKV = Info Query
|
||||||
|
|
||||||
|
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
||||||
|
PhoneInfo Result = Info;
|
||||||
|
|
||||||
|
if (Result.State == PhoneInfoState.Empty)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
|
||||||
|
byte[]? Response = ExecuteRawMethod(Request);
|
||||||
|
if ((Response != null) && (ByteOperations.ReadAsciiString(Response, 0, 4) != "NOKU"))
|
||||||
|
{
|
||||||
|
Result.App = (FlashAppType)Response[5];
|
||||||
|
|
||||||
|
switch (Result.App)
|
||||||
|
{
|
||||||
|
case FlashAppType.FlashApp:
|
||||||
|
Result.FlashAppProtocolVersionMajor = Response[6];
|
||||||
|
Result.FlashAppProtocolVersionMinor = Response[7];
|
||||||
|
Result.FlashAppVersionMajor = Response[8];
|
||||||
|
Result.FlashAppVersionMinor = Response[9];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte SubblockCount = Response[10];
|
||||||
|
int SubblockOffset = 11;
|
||||||
|
|
||||||
|
for (int i = 0; i < SubblockCount; i++)
|
||||||
|
{
|
||||||
|
byte SubblockID = Response[SubblockOffset + 0x00];
|
||||||
|
ushort SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
|
||||||
|
int SubblockPayloadOffset = SubblockOffset + 3;
|
||||||
|
byte SubblockVersion;
|
||||||
|
switch (SubblockID)
|
||||||
|
{
|
||||||
|
case 0x01:
|
||||||
|
Result.TransferSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
Result.WriteBufferSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
Result.EmmcSizeInSectors = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
if (Result.App == FlashAppType.FlashApp)
|
||||||
|
{
|
||||||
|
Result.SdCardSizeInSectors = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim([' ', '\0']);
|
||||||
|
break;
|
||||||
|
case 0x0D:
|
||||||
|
Result.AsyncSupport = Response[SubblockPayloadOffset + 1] == 1;
|
||||||
|
break;
|
||||||
|
case 0x0F: // Supported but check parsing below pls
|
||||||
|
SubblockVersion = Response[SubblockPayloadOffset]; // 0x03
|
||||||
|
Result.PlatformSecureBootEnabled = Response[SubblockPayloadOffset + 0x01] == 0x01;
|
||||||
|
Result.SecureFfuEnabled = Response[SubblockPayloadOffset + 0x02] == 0x01;
|
||||||
|
Result.JtagDisabled = Response[SubblockPayloadOffset + 0x03] == 0x01;
|
||||||
|
Result.RdcPresent = Response[SubblockPayloadOffset + 0x04] == 0x01;
|
||||||
|
Result.Authenticated = (Response[SubblockPayloadOffset + 0x05] == 0x01) || (Response[SubblockPayloadOffset + 0x05] == 0x02);
|
||||||
|
Result.UefiSecureBootEnabled = Response[SubblockPayloadOffset + 0x06] == 0x01;
|
||||||
|
Result.SecondaryHardwareKeyPresent = Response[SubblockPayloadOffset + 0x07] == 0x01;
|
||||||
|
break;
|
||||||
|
case 0x10: // Also check to be sure
|
||||||
|
SubblockVersion = Response[SubblockPayloadOffset]; // 0x01
|
||||||
|
Result.SecureFfuSupportedProtocolMask = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 0x01);
|
||||||
|
break;
|
||||||
|
case 0x1F: // Recheck too
|
||||||
|
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
// CRC header info
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
uint SectorCount = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
uint SectorSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset + 4);
|
||||||
|
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([' ', '\0']);
|
||||||
|
Result.BootDevices.Add((SectorCount, SectorSize, FlashType, FlashTypeIndex, Unknown, DevicePath));
|
||||||
|
break;
|
||||||
|
case 0x23:
|
||||||
|
byte[] Bytes = Response[SubblockPayloadOffset..(SubblockPayloadOffset + SubblockLength)];
|
||||||
|
|
||||||
|
ushort ManufacturerLength = BitConverter.ToUInt16(Bytes[0..2].Reverse().ToArray());
|
||||||
|
ushort FamilyLength = BitConverter.ToUInt16(Bytes[2..4].Reverse().ToArray());
|
||||||
|
ushort ProductNameLength = BitConverter.ToUInt16(Bytes[4..6].Reverse().ToArray());
|
||||||
|
ushort ProductVersionLength = BitConverter.ToUInt16(Bytes[6..8].Reverse().ToArray());
|
||||||
|
ushort SKUNumberLength = BitConverter.ToUInt16(Bytes[8..10].Reverse().ToArray());
|
||||||
|
ushort BaseboardManufacturerLength = BitConverter.ToUInt16(Bytes[10..12].Reverse().ToArray());
|
||||||
|
ushort BaseboardProductLength = BitConverter.ToUInt16(Bytes[12..14].Reverse().ToArray());
|
||||||
|
|
||||||
|
int CurrentOffset = 14;
|
||||||
|
Result.Manufacturer = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ManufacturerLength)]);
|
||||||
|
CurrentOffset += ManufacturerLength;
|
||||||
|
Result.Family = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + FamilyLength)]);
|
||||||
|
CurrentOffset += FamilyLength;
|
||||||
|
Result.ProductName = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ProductNameLength)]);
|
||||||
|
CurrentOffset += ProductNameLength;
|
||||||
|
Result.ProductVersion = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + ProductVersionLength)]);
|
||||||
|
CurrentOffset += ProductVersionLength;
|
||||||
|
Result.SKUNumber = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + SKUNumberLength)]);
|
||||||
|
CurrentOffset += SKUNumberLength;
|
||||||
|
Result.BaseboardManufacturer = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + BaseboardManufacturerLength)]);
|
||||||
|
CurrentOffset += BaseboardManufacturerLength;
|
||||||
|
Result.BaseboardProduct = Encoding.ASCII.GetString(Bytes[CurrentOffset..(CurrentOffset + BaseboardProductLength)]);
|
||||||
|
break;
|
||||||
|
case 0x24:
|
||||||
|
Result.LargestMemoryRegion = BitConverter.ToUInt64(Response[SubblockPayloadOffset..(SubblockPayloadOffset + 8)].Reverse().ToArray());
|
||||||
|
break;
|
||||||
|
case 0x25:
|
||||||
|
Result.AppType = (AppType)Response[SubblockPayloadOffset];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.WriteLine($"Unknown Subblock: ID: 0x{SubblockID:X2} Length: 0x{SubblockLength:X4}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SubblockOffset += SubblockLength + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result.State = PhoneInfoState.Basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
||||||
|
|
||||||
|
if (!PhoneInfoLogged)
|
||||||
|
{
|
||||||
|
Result.Log();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FlashAppType
|
||||||
|
{
|
||||||
|
FlashApp = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum PhoneInfoState
|
||||||
|
{
|
||||||
|
Empty,
|
||||||
|
Basic
|
||||||
|
};
|
||||||
|
|
||||||
|
public class PhoneInfo
|
||||||
|
{
|
||||||
|
public PhoneInfoState State = PhoneInfoState.Empty;
|
||||||
|
|
||||||
|
public FlashAppType App;
|
||||||
|
|
||||||
|
public byte FlashAppVersionMajor;
|
||||||
|
public byte FlashAppVersionMinor;
|
||||||
|
public byte FlashAppProtocolVersionMajor;
|
||||||
|
public byte FlashAppProtocolVersionMinor;
|
||||||
|
|
||||||
|
public uint TransferSize;
|
||||||
|
public bool MmosOverUsbSupported;
|
||||||
|
public uint SdCardSizeInSectors;
|
||||||
|
public uint WriteBufferSize;
|
||||||
|
public uint EmmcSizeInSectors;
|
||||||
|
public string? PlatformID;
|
||||||
|
public ushort SecureFfuSupportedProtocolMask;
|
||||||
|
public bool AsyncSupport;
|
||||||
|
|
||||||
|
public bool PlatformSecureBootEnabled;
|
||||||
|
public bool SecureFfuEnabled;
|
||||||
|
public bool JtagDisabled;
|
||||||
|
public bool RdcPresent;
|
||||||
|
public bool Authenticated;
|
||||||
|
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 ulong LargestMemoryRegion;
|
||||||
|
public AppType AppType;
|
||||||
|
public List<(uint SectorCount, uint SectorSize, ushort FlashType, ushort FlashIndex, uint Unknown, string DevicePath)> BootDevices = [];
|
||||||
|
|
||||||
|
public bool IsBootloaderSecure;
|
||||||
|
|
||||||
|
public void Log()
|
||||||
|
{
|
||||||
|
switch (App)
|
||||||
|
{
|
||||||
|
case FlashAppType.FlashApp:
|
||||||
|
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($"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($"JTAG: {(JtagDisabled ? "Disabled" : "Enabled")}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
const string Header = ShutdownSignature;
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnifiedFlashingPlatform.UEFI;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public partial class UnifiedFlashingPlatformModel
|
||||||
|
{
|
||||||
|
public void WriteParam(string Param, byte[] Data)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x0F + Data.Length];
|
||||||
|
const string Header = WriteParamSignature; // NOKXFW
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
|
||||||
|
// 4 empty bytes here
|
||||||
|
Buffer.BlockCopy(Data, 0, Request, 15, Data.Length);
|
||||||
|
|
||||||
|
ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Verify proper functionality
|
||||||
|
public void SetUEFIVariable(Guid Guid, string Name, UefiVariableAttributes Attributes, byte[] Data)
|
||||||
|
{
|
||||||
|
byte[] ParamBuffer = new byte[540 + Data.Length];
|
||||||
|
|
||||||
|
/* 15..30 */ Buffer.BlockCopy(Guid.ToByteArray(), 0, ParamBuffer, 0, 16);
|
||||||
|
/* 31..34 */ Buffer.BlockCopy(BigEndian.GetBytes(Math.Min(512, Name.Length * 2), 4), 0, ParamBuffer, 16, 4);
|
||||||
|
/* 35.. */ Buffer.BlockCopy(Encoding.Unicode.GetBytes(Name), 0, ParamBuffer, 20, Math.Min(512, Name.Length * 2)); // 256 Max Size for name (unicode)
|
||||||
|
/* 547..550 */ Buffer.BlockCopy(BigEndian.GetBytes(Attributes, 4), 0, ParamBuffer, 532, 4);
|
||||||
|
/* 551..554 */ Buffer.BlockCopy(BigEndian.GetBytes(Data.Length, 4), 0, ParamBuffer, 536, 4);
|
||||||
|
/* 555.. */ Buffer.BlockCopy(Data, 0, ParamBuffer, 540, Data.Length);
|
||||||
|
|
||||||
|
WriteParam(SettingUEFIVariableWriteParamSignature, ParamBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetOneTimeBootSequence(ushort BootEntryID)
|
||||||
|
{
|
||||||
|
//WriteParam(OneTimeBootSequenceWriteParamSignature, BigEndian.GetBytes(BootEntryID, 2));
|
||||||
|
WriteParam("UOBU", [.. BigEndian.GetBytes(BootEntryID, 2).Reverse()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBootOptionAsFirstEntry(ushort BootEntryID)
|
||||||
|
{
|
||||||
|
//WriteParam(BootOptionAsFirstEntryWriteParamSignature, BigEndian.GetBytes(BootEntryID, 2));
|
||||||
|
WriteParam("UBOF", [.. BigEndian.GetBytes(BootEntryID, 2).Reverse()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBootOptionAsLastEntry(ushort BootEntryID)
|
||||||
|
{
|
||||||
|
WriteParam(BootOptionAsLastEntryWriteParamSignature, BigEndian.GetBytes(BootEntryID, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetProgressBar(uint Percentage)
|
||||||
|
{
|
||||||
|
WriteParam("PBI\0", BigEndian.GetBytes(Percentage, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnifiedFlashingPlatform.UEFI;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
|
namespace UnifiedFlashingPlatform
|
||||||
|
{
|
||||||
|
public partial class UnifiedFlashingPlatformModel : IDisposable
|
||||||
|
{
|
||||||
|
private bool Disposed = false;
|
||||||
|
private readonly USBDevice USBDevice;
|
||||||
|
private readonly USBPipe InputPipe;
|
||||||
|
private readonly USBPipe OutputPipe;
|
||||||
|
private readonly object UsbLock = new();
|
||||||
|
|
||||||
|
public UnifiedFlashingPlatformModel(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 void Relock()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = RelockSignature; // NOKXFO
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MassStorage()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = MassStorageSignature; // NOKM
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RebootPhone()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = $"{SwitchModeSignature}R"; // NOKXCBR
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwitchToUFP()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = $"{SwitchModeSignature}U"; // NOKXCBU
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ContinueBoot()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = $"{SwitchModeSignature}W"; // NOKXCBW
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PowerOff()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = $"{SwitchModeSignature}Z"; // NOKXCBZ
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TransitionToUFPBootApp()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[7];
|
||||||
|
const string Header = $"{SwitchModeSignature}T"; // NOKXCBT
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayCustomMessage(string Message, ushort Row)
|
||||||
|
{
|
||||||
|
byte[] MessageBuffer = Encoding.Unicode.GetBytes(Message);
|
||||||
|
byte[] Request = new byte[8 + MessageBuffer.Length];
|
||||||
|
const string Header = DisplayCustomMessageSignature; // NOKXCM
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
Buffer.BlockCopy(BitConverter.GetBytes(Row).Reverse().ToArray(), 0, Request, 6, 2);
|
||||||
|
Buffer.BlockCopy(MessageBuffer, 0, Request, 8, MessageBuffer.Length);
|
||||||
|
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearScreen()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[6];
|
||||||
|
const string Header = ClearScreenSignature; // NOKXCC
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
_ = ExecuteRawMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[]? Echo(byte[] DataPayload)
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[10 + DataPayload.Length];
|
||||||
|
const string Header = EchoSignature; // NOKXCE
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
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 FILE_INFO[]? GetDirectoryEntries(string PartitionName, string DirectoryName)
|
||||||
|
{
|
||||||
|
ulong? size = ReadDirectoryEntriesSize(PartitionName, DirectoryName);
|
||||||
|
if (size == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetDirectoryEntries(PartitionName, DirectoryName, size.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FILE_INFO[]? GetDirectoryEntries(string PartitionName, string DirectoryName, ulong DataStructSize)
|
||||||
|
{
|
||||||
|
if (PartitionName.Length > 35)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] PartitionNameBuffer = Encoding.Unicode.GetBytes(PartitionName);
|
||||||
|
byte[] DirectoryNameBuffer = Encoding.Unicode.GetBytes(DirectoryName);
|
||||||
|
|
||||||
|
byte[] Request = new byte[1114];
|
||||||
|
const string Header = GetDirectoryEntriesSignature; // NOKXCD
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(PartitionNameBuffer, 0, Request, 6, PartitionNameBuffer.Length);
|
||||||
|
Buffer.BlockCopy(DirectoryNameBuffer, 0, Request, 78, DirectoryNameBuffer.Length); // 512 max size (1024 for unicode)
|
||||||
|
|
||||||
|
Buffer.BlockCopy(BigEndian.GetBytes((int)DataStructSize, 4), 0, Request, 1102, 4);
|
||||||
|
|
||||||
|
// TODO: Investigate data size
|
||||||
|
//Buffer.BlockCopy(BigEndian.GetBytes(360, 8), 0, Request, 1106, 8);
|
||||||
|
|
||||||
|
byte[]? Response = ExecuteRawMethod(Request);
|
||||||
|
if ((Response == null) || (Response.Length < 0x10))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResultCode = (Response[6] << 8) + Response[7];
|
||||||
|
if (ResultCode != 0)
|
||||||
|
{
|
||||||
|
ThrowFlashError(ResultCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResponseLength = BigEndian.ToInt32(Response, 8);
|
||||||
|
|
||||||
|
byte[] Result = new byte[ResponseLength];
|
||||||
|
Buffer.BlockCopy(Response, 12, Result, 0, ResponseLength);
|
||||||
|
|
||||||
|
List<FILE_INFO> directoryEntries = [];
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
while (j != Result.Length)
|
||||||
|
{
|
||||||
|
FILE_INFO directoryEntry = FILE_INFO.ReadFromBuffer(Result, j);
|
||||||
|
j += (int)directoryEntry.Size;
|
||||||
|
|
||||||
|
directoryEntries.Add(directoryEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [.. directoryEntries];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TelemetryStart()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
const string Header = TelemetryStartSignature; // NOKS
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TelemetryEnd()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[4];
|
||||||
|
const string Header = TelemetryEndSignature; // NOKN
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
ExecuteRawVoidMethod(Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WIP!
|
||||||
|
public string? ReadLog()
|
||||||
|
{
|
||||||
|
byte[] Request = new byte[0x13];
|
||||||
|
const string Header = GetLogsSignature;
|
||||||
|
ulong BufferSize = 0xE000 - 0xC;
|
||||||
|
|
||||||
|
ulong Length = ReadLogSize(DeviceLogType.Flashing)!.Value;
|
||||||
|
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;
|
||||||
|
|
||||||
|
Buffer.BlockCopy(Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||||
|
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);
|
||||||
|
|
||||||
|
string PartialLogContent = Encoding.ASCII.GetString(Result);
|
||||||
|
|
||||||
|
LogContent += PartialLogContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LogContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~UnifiedFlashingPlatformModel()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
using WPinternals.HelperClasses;
|
using WPinternals.HelperClasses;
|
||||||
using WPinternals.Models.Lumia.NCSd;
|
using WPinternals.Models.Lumia.NCSd;
|
||||||
using WPinternals.Models.SimpleIO;
|
using WPinternals.Models.SimpleIO;
|
||||||
@@ -95,6 +96,9 @@ namespace WPinternals
|
|||||||
case PhoneInterfaces.SimpleIO:
|
case PhoneInterfaces.SimpleIO:
|
||||||
ActivateSubContext(new SimpleIOViewModel((SimpleIOModel)CurrentModel, ModeSwitchRequestCallback));
|
ActivateSubContext(new SimpleIOViewModel((SimpleIOModel)CurrentModel, ModeSwitchRequestCallback));
|
||||||
break;
|
break;
|
||||||
|
case PhoneInterfaces.UFP:
|
||||||
|
ActivateSubContext(new UFPViewModel((UnifiedFlashingPlatformModel)CurrentModel, ModeSwitchRequestCallback));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
using WPinternals.HelperClasses;
|
using WPinternals.HelperClasses;
|
||||||
using WPinternals.Models.Lumia.NCSd;
|
using WPinternals.Models.Lumia.NCSd;
|
||||||
using WPinternals.Models.SimpleIO;
|
using WPinternals.Models.SimpleIO;
|
||||||
@@ -113,6 +114,9 @@ namespace WPinternals
|
|||||||
case PhoneInterfaces.SimpleIO:
|
case PhoneInterfaces.SimpleIO:
|
||||||
ActivateSubContext(new SimpleIOModeViewModel((SimpleIOModel)CurrentModel, OnModeSwitchRequested));
|
ActivateSubContext(new SimpleIOModeViewModel((SimpleIOModel)CurrentModel, OnModeSwitchRequested));
|
||||||
break;
|
break;
|
||||||
|
case PhoneInterfaces.UFP:
|
||||||
|
ActivateSubContext(new UFPModeViewModel((UnifiedFlashingPlatformModel)CurrentModel, OnModeSwitchRequested));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ namespace WPinternals
|
|||||||
Qualcomm_Flash,
|
Qualcomm_Flash,
|
||||||
Lumia_BadMassStorage,
|
Lumia_BadMassStorage,
|
||||||
Lumia_PhoneInfo,
|
Lumia_PhoneInfo,
|
||||||
SimpleIO
|
SimpleIO,
|
||||||
|
UFP
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create this class on the UI thread, after the main-window of the application is initialized.
|
// Create this class on the UI thread, after the main-window of the application is initialized.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ using System.Diagnostics.Eventing.Reader;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
using WPinternals.HelperClasses;
|
using WPinternals.HelperClasses;
|
||||||
using WPinternals.Models.Lumia.NCSd;
|
using WPinternals.Models.Lumia.NCSd;
|
||||||
using WPinternals.Models.Lumia.UEFI;
|
using WPinternals.Models.Lumia.UEFI;
|
||||||
@@ -49,6 +50,7 @@ namespace WPinternals
|
|||||||
private USBNotifier LumiaLabelNotifier;
|
private USBNotifier LumiaLabelNotifier;
|
||||||
private USBNotifier HidInterfaceNotifier;
|
private USBNotifier HidInterfaceNotifier;
|
||||||
private USBNotifier SimpleIONotifier;
|
private USBNotifier SimpleIONotifier;
|
||||||
|
private USBNotifier UFPNotifier;
|
||||||
|
|
||||||
public PhoneInterfaces? CurrentInterface = null;
|
public PhoneInterfaces? CurrentInterface = null;
|
||||||
private PhoneInterfaces? LastInterface = null;
|
private PhoneInterfaces? LastInterface = null;
|
||||||
@@ -71,6 +73,8 @@ namespace WPinternals
|
|||||||
|
|
||||||
private Guid SimpleIOInterfaceGuid = new("{82809dd0-51f5-11e1-b86c-0800200c9a66}");
|
private Guid SimpleIOInterfaceGuid = new("{82809dd0-51f5-11e1-b86c-0800200c9a66}");
|
||||||
|
|
||||||
|
private Guid UFPInterfaceGuid = new("{9E3BD5F7-9690-4FCC-8810-3E2650CD6ECC}");
|
||||||
|
|
||||||
private readonly object ModelLock = new();
|
private readonly object ModelLock = new();
|
||||||
|
|
||||||
private readonly EventWaitHandle NewInterfaceWaitHandle = new(false, EventResetMode.AutoReset);
|
private readonly EventWaitHandle NewInterfaceWaitHandle = new(false, EventResetMode.AutoReset);
|
||||||
@@ -121,6 +125,10 @@ namespace WPinternals
|
|||||||
SimpleIONotifier.Arrival += LumiaNotifier_Arrival;
|
SimpleIONotifier.Arrival += LumiaNotifier_Arrival;
|
||||||
SimpleIONotifier.Removal += LumiaNotifier_Removal;
|
SimpleIONotifier.Removal += LumiaNotifier_Removal;
|
||||||
|
|
||||||
|
UFPNotifier = new USBNotifier(UFPInterfaceGuid);
|
||||||
|
UFPNotifier.Arrival += LumiaNotifier_Arrival;
|
||||||
|
UFPNotifier.Removal += LumiaNotifier_Removal;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EventLogQuery LogQuery = new("Microsoft-Windows-Kernel-PnP/Configuration", PathType.LogName, "*[System[(EventID = 411)]]");
|
EventLogQuery LogQuery = new("Microsoft-Windows-Kernel-PnP/Configuration", PathType.LogName, "*[System[(EventID = 411)]]");
|
||||||
@@ -159,6 +167,7 @@ namespace WPinternals
|
|||||||
LumiaEmergencyNotifier.Dispose();
|
LumiaEmergencyNotifier.Dispose();
|
||||||
HidInterfaceNotifier.Dispose();
|
HidInterfaceNotifier.Dispose();
|
||||||
SimpleIONotifier.Dispose();
|
SimpleIONotifier.Dispose();
|
||||||
|
UFPNotifier.Dispose();
|
||||||
LogWatcher.Dispose();
|
LogWatcher.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +194,18 @@ namespace WPinternals
|
|||||||
if (e.DevicePath.Contains("VID_0421&", StringComparison.OrdinalIgnoreCase) ||
|
if (e.DevicePath.Contains("VID_0421&", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("VID_045E&", StringComparison.OrdinalIgnoreCase))
|
e.DevicePath.Contains("VID_045E&", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (e.DevicePath.Contains("&PID_062A", StringComparison.OrdinalIgnoreCase))
|
if (e.DevicePath.Contains("&PID_0658", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
CurrentModel = new UnifiedFlashingPlatformModel(e.DevicePath);
|
||||||
|
|
||||||
|
CurrentInterface = PhoneInterfaces.UFP;
|
||||||
|
LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly);
|
||||||
|
LogFile.Log("Device path: " + e.DevicePath, LogType.FileOnly);
|
||||||
|
LogFile.Log("Connected device: Lumia", LogType.FileAndConsole);
|
||||||
|
LogFile.Log("Mode: UFP", LogType.FileAndConsole);
|
||||||
|
NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel));
|
||||||
|
}
|
||||||
|
else if (e.DevicePath.Contains("&PID_062A", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
CurrentModel = new SimpleIOModel(e.DevicePath);
|
CurrentModel = new SimpleIOModel(e.DevicePath);
|
||||||
|
|
||||||
@@ -551,6 +571,7 @@ namespace WPinternals
|
|||||||
e.DevicePath.Contains("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) ||
|
e.DevicePath.Contains("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) ||
|
e.DevicePath.Contains("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("VID_045E&PID_062A", StringComparison.OrdinalIgnoreCase) ||
|
e.DevicePath.Contains("VID_045E&PID_062A", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
e.DevicePath.Contains("VID_045E&PID_0658", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("VID_05C6&PID_9008", StringComparison.OrdinalIgnoreCase) ||
|
e.DevicePath.Contains("VID_05C6&PID_9008", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("DISK&VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.OrdinalIgnoreCase) ||
|
e.DevicePath.Contains("DISK&VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.OrdinalIgnoreCase) ||
|
||||||
e.DevicePath.Contains("DISK&VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.OrdinalIgnoreCase)
|
e.DevicePath.Contains("DISK&VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
using WPinternals.HelperClasses;
|
using WPinternals.HelperClasses;
|
||||||
using WPinternals.Models.Lumia;
|
using WPinternals.Models.Lumia;
|
||||||
using WPinternals.Models.Lumia.NCSd;
|
using WPinternals.Models.Lumia.NCSd;
|
||||||
@@ -218,6 +219,36 @@ namespace WPinternals
|
|||||||
// Make switch and set message or navigate to error
|
// Make switch and set message or navigate to error
|
||||||
switch (CurrentMode)
|
switch (CurrentMode)
|
||||||
{
|
{
|
||||||
|
case PhoneInterfaces.UFP:
|
||||||
|
IsSwitchingInterface = true;
|
||||||
|
switch (TargetMode)
|
||||||
|
{
|
||||||
|
case null:
|
||||||
|
((UnifiedFlashingPlatformModel)PhoneNotifier.CurrentModel).Shutdown();
|
||||||
|
ModeSwitchProgressWrapper("Please disconnect your device. Waiting...", null);
|
||||||
|
LogFile.Log("Please disconnect your device. Waiting...", LogType.FileAndConsole);
|
||||||
|
new Thread(() =>
|
||||||
|
{
|
||||||
|
PhoneNotifier.WaitForRemoval().Wait();
|
||||||
|
ModeSwitchSuccessWrapper();
|
||||||
|
}).Start();
|
||||||
|
break;
|
||||||
|
case PhoneInterfaces.Lumia_Normal:
|
||||||
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
((UnifiedFlashingPlatformModel)PhoneNotifier.CurrentModel).ResetPhone();
|
||||||
|
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
||||||
|
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
||||||
|
break;
|
||||||
|
case PhoneInterfaces.Lumia_Bootloader:
|
||||||
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
((UnifiedFlashingPlatformModel)PhoneNotifier.CurrentModel).ResetPhone();
|
||||||
|
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
||||||
|
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PhoneInterfaces.SimpleIO:
|
case PhoneInterfaces.SimpleIO:
|
||||||
IsSwitchingInterface = true;
|
IsSwitchingInterface = true;
|
||||||
switch (TargetMode)
|
switch (TargetMode)
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
|
|
||||||
|
namespace WPinternals
|
||||||
|
{
|
||||||
|
internal class UFPModeViewModel : ContextViewModel
|
||||||
|
{
|
||||||
|
private readonly UnifiedFlashingPlatformModel CurrentModel;
|
||||||
|
private readonly Action<PhoneInterfaces?> RequestModeSwitch;
|
||||||
|
|
||||||
|
internal UFPModeViewModel(UnifiedFlashingPlatformModel CurrentModel, Action<PhoneInterfaces?> RequestModeSwitch)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
this.CurrentModel = CurrentModel;
|
||||||
|
this.RequestModeSwitch = RequestModeSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RebootTo(string Mode)
|
||||||
|
{
|
||||||
|
switch (Mode)
|
||||||
|
{
|
||||||
|
case "Normal":
|
||||||
|
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||||
|
break;
|
||||||
|
case "MassStorage":
|
||||||
|
RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage);
|
||||||
|
break;
|
||||||
|
case "Shutdown":
|
||||||
|
RequestModeSwitch(null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using UnifiedFlashingPlatform;
|
||||||
|
using WPinternals.HelperClasses;
|
||||||
|
|
||||||
|
namespace WPinternals
|
||||||
|
{
|
||||||
|
// Create this class on the UI thread, after the main-window of the application is initialized.
|
||||||
|
// It is necessary to create the object on the UI thread, because notification events to the View need to be fired on that thread.
|
||||||
|
// The Model for this ViewModel communicates over USB and for that it uses the hWnd of the main window.
|
||||||
|
// Therefore the main window must be created before the ViewModel is created.
|
||||||
|
|
||||||
|
internal class UFPViewModel : ContextViewModel
|
||||||
|
{
|
||||||
|
private readonly UnifiedFlashingPlatformModel CurrentModel;
|
||||||
|
private readonly Action<PhoneInterfaces> RequestModeSwitch;
|
||||||
|
private readonly object LockDeviceInfo = new();
|
||||||
|
private bool DeviceInfoLoaded = false;
|
||||||
|
|
||||||
|
internal UFPViewModel(UnifiedFlashingPlatformModel CurrentModel, Action<PhoneInterfaces> RequestModeSwitch)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
this.RequestModeSwitch = RequestModeSwitch;
|
||||||
|
|
||||||
|
this.CurrentModel = CurrentModel;
|
||||||
|
|
||||||
|
new Thread(() => StartLoadDeviceInfo()).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartLoadDeviceInfo()
|
||||||
|
{
|
||||||
|
lock (LockDeviceInfo)
|
||||||
|
{
|
||||||
|
if (!DeviceInfoLoaded)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PlatformName = CurrentModel.ReadStringParam("DPI");
|
||||||
|
LogFile.Log("Platform Name: " + PlatformName);
|
||||||
|
|
||||||
|
// Some phones do not support the Terminal interface! (928 verizon)
|
||||||
|
// Instead read param RRKH to get the RKH.
|
||||||
|
PublicID = null;
|
||||||
|
byte[] RawPublicID = CurrentModel.ReadParam("PID");
|
||||||
|
if (RawPublicID?.Length > 4)
|
||||||
|
{
|
||||||
|
PublicID = new byte[RawPublicID.Length - 4];
|
||||||
|
Array.Copy(RawPublicID, 4, PublicID, 0, RawPublicID.Length - 4);
|
||||||
|
LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " "));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PublicID = new byte[20];
|
||||||
|
LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " "));
|
||||||
|
}
|
||||||
|
RootKeyHash = CurrentModel.ReadParam("RRKH");
|
||||||
|
if (RootKeyHash != null)
|
||||||
|
{
|
||||||
|
LogFile.Log("Root Key Hash: " + Converter.ConvertHexToString(RootKeyHash, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] EMS = CurrentModel.ReadParam("EMS");
|
||||||
|
if (EMS != null)
|
||||||
|
{
|
||||||
|
UInt64 MemSize = (UInt64)(((UInt32)EMS[0] << 24) + ((UInt32)EMS[1] << 16) + ((UInt32)EMS[2] << 8) + EMS[3]) * 0x200;
|
||||||
|
double MemSizeDouble = (double)MemSize / 1024 / 1024 / 1024;
|
||||||
|
MemSizeDouble = (double)(int)(MemSizeDouble * 10) / 10;
|
||||||
|
string Manufacturer = null;
|
||||||
|
|
||||||
|
eMMC = Manufacturer == null ? MemSizeDouble.ToString() + " GB" : Manufacturer + " " + MemSizeDouble.ToString() + " GB";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eMMC = "Unknown";
|
||||||
|
SamsungWarningVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnifiedFlashingPlatformModel.PhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||||
|
BootloaderDescription = Info.FlashAppProtocolVersionMajor < 2 ? "Lumia Bootloader Spec A" : "Lumia Bootloader Spec B";
|
||||||
|
|
||||||
|
LogFile.Log("Bootloader: " + BootloaderDescription);
|
||||||
|
|
||||||
|
ProductCode = "";//TODO: FIXME: Info.ProductCode;
|
||||||
|
LogFile.Log("ProductCode: " + ProductCode);
|
||||||
|
|
||||||
|
ProductType = "";//TODO: FIXME: Info.Type;
|
||||||
|
LogFile.Log("ProductType: " + ProductType);
|
||||||
|
|
||||||
|
if (PlatformName == null)
|
||||||
|
{
|
||||||
|
LogFile.Log("Platform Name was null. Gathering information from an alternative source.");
|
||||||
|
|
||||||
|
PlatformName = Info.PlatformID;
|
||||||
|
LogFile.Log("Platform Name: " + PlatformName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogFile.Log("An unexpected error happened", LogType.FileAndConsole);
|
||||||
|
LogFile.Log(ex.GetType().ToString(), LogType.FileAndConsole);
|
||||||
|
LogFile.Log(ex.Message, LogType.FileAndConsole);
|
||||||
|
LogFile.Log(ex.StackTrace, LogType.FileAndConsole);
|
||||||
|
|
||||||
|
LogFile.Log("Reading status from Flash interface was aborted.");
|
||||||
|
}
|
||||||
|
DeviceInfoLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] _PublicID = null;
|
||||||
|
public byte[] PublicID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _PublicID;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_PublicID = value;
|
||||||
|
OnPropertyChanged(nameof(PublicID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] _RootKeyHash = null;
|
||||||
|
public byte[] RootKeyHash
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _RootKeyHash;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_RootKeyHash = value;
|
||||||
|
OnPropertyChanged(nameof(RootKeyHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _PlatformName = null;
|
||||||
|
public string PlatformName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _PlatformName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_PlatformName = value;
|
||||||
|
OnPropertyChanged(nameof(PlatformName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _ProductType = null;
|
||||||
|
public string ProductType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _ProductType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_ProductType = value;
|
||||||
|
OnPropertyChanged(nameof(ProductType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _ProductCode = null;
|
||||||
|
public string ProductCode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _ProductCode;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_ProductCode = value;
|
||||||
|
OnPropertyChanged(nameof(ProductCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _eMMC = null;
|
||||||
|
public string eMMC
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _eMMC;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_eMMC = value;
|
||||||
|
OnPropertyChanged(nameof(eMMC));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _BootloaderDescription = null;
|
||||||
|
public string BootloaderDescription
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _BootloaderDescription;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_BootloaderDescription = value;
|
||||||
|
OnPropertyChanged(nameof(BootloaderDescription));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _SamsungWarningVisible = false;
|
||||||
|
public bool SamsungWarningVisible
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _SamsungWarningVisible;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_SamsungWarningVisible = value;
|
||||||
|
OnPropertyChanged(nameof(SamsungWarningVisible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RebootTo(string Mode)
|
||||||
|
{
|
||||||
|
switch (Mode)
|
||||||
|
{
|
||||||
|
case "Normal":
|
||||||
|
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||||
|
break;
|
||||||
|
case "MassStorage":
|
||||||
|
RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -121,6 +121,12 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
<DataTemplate DataType="{x:Type local:SimpleIOModeViewModel}">
|
<DataTemplate DataType="{x:Type local:SimpleIOModeViewModel}">
|
||||||
<local:SimpleIOModeView />
|
<local:SimpleIOModeView />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type local:UFPViewModel}">
|
||||||
|
<local:UFPView />
|
||||||
|
</DataTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type local:UFPModeViewModel}">
|
||||||
|
<local:UFPModeView />
|
||||||
|
</DataTemplate>
|
||||||
<BitmapImage x:Key="LogoImageSource" UriSource="..\Assets\Logo.png" />
|
<BitmapImage x:Key="LogoImageSource" UriSource="..\Assets\Logo.png" />
|
||||||
<BitmapImage x:Key="LogoSmallImageSource" UriSource="..\Assets\Logo-Small.png" />
|
<BitmapImage x:Key="LogoSmallImageSource" UriSource="..\Assets\Logo-Small.png" />
|
||||||
<Style x:Key="MenuButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}">
|
<Style x:Key="MenuButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}">
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
<Run Text="This interface is meant for querying and provisioning the phone. This is normally used for configuring the phone during manufacturing." />
|
<Run Text="This interface is meant for querying and provisioning the phone. This is normally used for configuring the phone during manufacturing." />
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
|
<Hyperlink NavigateUri="Shutdown">Shutdown the phone</Hyperlink>
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="This will shutdown your phone. After selecting this option, you'll need to unplug your phone from your computer." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
<Hyperlink NavigateUri="MassStorage">Switch to Mass-Storage-mode</Hyperlink>
|
<Hyperlink NavigateUri="MassStorage">Switch to Mass-Storage-mode</Hyperlink>
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
<Run Text="This mode allows you to access the complete file-system of the phone. " />
|
<Run Text="This mode allows you to access the complete file-system of the phone. " />
|
||||||
@@ -81,11 +86,6 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
<helpers:CollapsibleRun IsVisible="{Binding EffectiveBootloaderSecurityStatus, Converter={StaticResource InverseConverter}, Mode=OneWay}" Text="Your security flags indicate the this mode can be accessed. But this switch will only succeed if you took all measures to unlock Mass Storage mode." />
|
<helpers:CollapsibleRun IsVisible="{Binding EffectiveBootloaderSecurityStatus, Converter={StaticResource InverseConverter}, Mode=OneWay}" Text="Your security flags indicate the this mode can be accessed. But this switch will only succeed if you took all measures to unlock Mass Storage mode." />
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
<Hyperlink NavigateUri="Shutdown">Shutdown the phone</Hyperlink>
|
|
||||||
<LineBreak />
|
|
||||||
<Run Text="This will shutdown your phone. After selecting this option, you'll need to unplug your phone from your computer." />
|
|
||||||
<LineBreak />
|
|
||||||
<LineBreak />
|
|
||||||
<Run Text="Warning 1: " Foreground="Red" FontWeight="Bold"/>
|
<Run Text="Warning 1: " Foreground="Red" FontWeight="Bold"/>
|
||||||
<Run Text="Once you've entered Mass Storage mode, be very careful with altering files. You can easily brick your phone, when you make invalid changes to the file-system of the phone." />
|
<Run Text="Once you've entered Mass Storage mode, be very careful with altering files. You can easily brick your phone, when you make invalid changes to the file-system of the phone." />
|
||||||
<LineBreak />
|
<LineBreak />
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<UserControl x:Class="WPinternals.UFPModeView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:WPinternals"
|
||||||
|
xmlns:helpers="clr-namespace:WPinternals.HelperClasses"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="700">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<helpers:BooleanConverter x:Key="VisibilityConverter" OnTrue="Visible" OnFalse="Collapsed" />
|
||||||
|
<helpers:BooleanConverter x:Key="InvisibilityConverter" OnTrue="Collapsed" OnFalse="Visible" />
|
||||||
|
<helpers:BooleanConverter x:Key="InverseConverter" OnTrue="False" OnFalse="True" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25">
|
||||||
|
<helpers:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0,0,0" VerticalScrollBarVisibility="Auto" >
|
||||||
|
<FlowDocument x:Name="Document" FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" TextAlignment="Left">
|
||||||
|
<FlowDocument.Resources>
|
||||||
|
<!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
|
||||||
|
<Style TargetType="{x:Type Paragraph}">
|
||||||
|
<Setter Property="Margin" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="{x:Type Section}">
|
||||||
|
<Setter Property="Margin" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
</FlowDocument.Resources>
|
||||||
|
<helpers:Paragraph>
|
||||||
|
<Run Text="Nokia Lumia - Switch mode" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="Current mode: " />
|
||||||
|
<Run Text="Unified Flashing Platform" Foreground="#FF3753A6" FontWeight="Bold" />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Hyperlink NavigateUri="Normal">Switch to Normal-mode</Hyperlink>
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="This will switch back to Windows Phone OS." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Hyperlink NavigateUri="Shutdown">Shutdown the phone</Hyperlink>
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="This will shutdown your phone. After selecting this option, you'll need to unplug your phone from your computer." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Hyperlink NavigateUri="MassStorage">Switch to Mass-Storage-mode</Hyperlink>
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="This mode allows you to access the complete file-system of the phone. " />
|
||||||
|
<Run Text="To enter this mode the phone will first be booted to Flash mode. After that this tool will immediately attempt to boot the phone to Mass Storage mode. So you may see your phone reboot multiple times." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="Warning 1: " Foreground="Red" FontWeight="Bold"/>
|
||||||
|
<Run Text="Once you've entered Mass Storage mode, be very careful with altering files. You can easily brick your phone, when you make invalid changes to the file-system of the phone." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="Warning 2: " Foreground="Red" FontWeight="Bold"/>
|
||||||
|
<Run Text="Before switching to Mass Storage Mode, verify that you do not have any other Windows Phone disks or partitions mounted. The partitions may have equal identifiers, which will result in a conflict. The phone partitions will be mounted "offline" and if you try to switch them "online" in the Disk Manager, it will corrupt the partitions on the phone. Unmount any Windows Phone partitions before you continue." />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="Warning 3: " Foreground="Red" FontWeight="Bold"/>
|
||||||
|
<Run Text="Switching to Mass Storage mode should take about 10 seconds. Phones with Bootloader Spec A should be unlocked using an Engineering SBL3 to enable Mass Storage mode. When you unlocked the bootloader, but you did not use an Engineering SBL3, an attempt to boot to Mass Storage mode may result in an unresponsive state. Installing drivers for this interface may also cause to hang the PC. So when this switch is taking too long, you should reboot both the PC and the phone." />
|
||||||
|
</helpers:Paragraph>
|
||||||
|
</FlowDocument>
|
||||||
|
</helpers:FlowDocumentScrollViewerNoMouseWheel>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
|
||||||
|
namespace WPinternals
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for UFPModeView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class UFPModeView : UserControl
|
||||||
|
{
|
||||||
|
public UFPModeView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Source is Hyperlink link)
|
||||||
|
{
|
||||||
|
(this.DataContext as UFPModeViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Document_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
(sender as FlowDocument)?.AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<UserControl x:Class="WPinternals.UFPView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:local="clr-namespace:WPinternals"
|
||||||
|
xmlns:helpers="clr-namespace:WPinternals.HelperClasses"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignWidth="700">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<helpers:HexConverter x:Key="HexConverter" />
|
||||||
|
<helpers:BooleanConverter x:Key="VisibilityConverter" OnTrue="Visible" OnFalse="Collapsed" OnNull="Collapsed"/>
|
||||||
|
<helpers:BooleanConverter x:Key="InverseVisibilityConverter" OnTrue="Collapsed" OnFalse="Visible" OnNull="Collapsed" />
|
||||||
|
<helpers:ObjectToVisibilityConverter x:Key="ObjectToVisibilityConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<StackPanel>
|
||||||
|
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25" Margin="0,0,0,20">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<helpers:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0" VerticalScrollBarVisibility="Auto">
|
||||||
|
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||||
|
<helpers:Paragraph>
|
||||||
|
<Run Text="General info" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
|
||||||
|
<LineBreak />
|
||||||
|
<LineBreak />
|
||||||
|
<Grid IsHitTestVisible="False">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Platform name" />
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding PlatformName, Mode=OneWay}" />
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Operating mode" />
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="1" Text="Unified Flashing Platform" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" />
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="0" Text="Product Type" Visibility="{Binding Path=ProductType, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding ProductType}" Visibility="{Binding Path=ProductType, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||||
|
<TextBlock Grid.Row="3" Grid.Column="0" Text="Product Code" Visibility="{Binding Path=ProductCode, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||||
|
<TextBlock Grid.Row="3" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding ProductCode}" Visibility="{Binding Path=ProductCode, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||||
|
<TextBlock Grid.Row="5" Grid.Column="0" Text="Storage" />
|
||||||
|
<TextBlock Grid.Row="5" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding eMMC}"/>
|
||||||
|
<TextBlock Grid.Row="6" Grid.Column="0" Text="Bootloader" />
|
||||||
|
<TextBlock Grid.Row="6" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding BootloaderDescription}"/>
|
||||||
|
</Grid>
|
||||||
|
</helpers:Paragraph>
|
||||||
|
</FlowDocument>
|
||||||
|
</helpers:FlowDocumentScrollViewerNoMouseWheel>
|
||||||
|
<helpers:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0" VerticalScrollBarVisibility="Auto" Visibility="{Binding Path=SamsungWarningVisible, Converter={StaticResource VisibilityConverter}}">
|
||||||
|
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||||
|
<helpers:Paragraph>
|
||||||
|
<LineBreak />
|
||||||
|
<helpers:CollapsibleRun Text="Read the " IsVisible="{Binding SamsungWarningVisible}" />
|
||||||
|
<Hyperlink NavigateUri="GettingStarted">Getting started</Hyperlink>
|
||||||
|
<Run Text=" section for important information about Samsung eMMC." />
|
||||||
|
</helpers:Paragraph>
|
||||||
|
</FlowDocument>
|
||||||
|
</helpers:FlowDocumentScrollViewerNoMouseWheel>
|
||||||
|
<helpers:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0" VerticalScrollBarVisibility="Auto">
|
||||||
|
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||||
|
<helpers:Paragraph>
|
||||||
|
<LineBreak />
|
||||||
|
<Run Text="To let the phone go back to Windows, boot to " />
|
||||||
|
<Hyperlink NavigateUri="Normal">Normal</Hyperlink>
|
||||||
|
<Run Text=" mode." />
|
||||||
|
</helpers:Paragraph>
|
||||||
|
</FlowDocument>
|
||||||
|
</helpers:FlowDocumentScrollViewerNoMouseWheel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25" Margin="0,0,0,20">
|
||||||
|
<Expander Header="Phone identity" HorizontalContentAlignment="Stretch" Template="{DynamicResource TopicExpanderTemplate}" Margin="20,0">
|
||||||
|
<helpers:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" VerticalScrollBarVisibility="Auto" >
|
||||||
|
<FlowDocument x:Name="Document" FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||||
|
<helpers:Paragraph>
|
||||||
|
<LineBreak />
|
||||||
|
<Grid IsHitTestVisible="False">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Root Key Hash" />
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=RootKeyHash, Converter={StaticResource HexConverter}, Mode=OneWay}" TextWrapping="Wrap" />
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Public Phone ID" />
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=PublicID, Converter={StaticResource HexConverter}, Mode=OneWay}" TextWrapping="Wrap" />
|
||||||
|
</Grid>
|
||||||
|
</helpers:Paragraph>
|
||||||
|
</FlowDocument>
|
||||||
|
</helpers:FlowDocumentScrollViewerNoMouseWheel>
|
||||||
|
</Expander>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (c) 2018, Rene Lergner - @Heathcliff74xda
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
|
||||||
|
namespace WPinternals
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for UFPView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class UFPView : UserControl
|
||||||
|
{
|
||||||
|
public UFPView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
Hyperlink link = args.Source as Hyperlink;
|
||||||
|
if (link?.NavigateUri != null)
|
||||||
|
{
|
||||||
|
(this.DataContext as UFPViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Document_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
(sender as FlowDocument)?.AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -344,6 +344,9 @@
|
|||||||
<ProjectReference Include="..\DiscUtils\DiscUtils.Fat\DiscUtils.Fat.WPI.csproj" />
|
<ProjectReference Include="..\DiscUtils\DiscUtils.Fat\DiscUtils.Fat.WPI.csproj" />
|
||||||
<ProjectReference Include="..\WinUSBNet\WinUSBNet.csproj" />
|
<ProjectReference Include="..\WinUSBNet\WinUSBNet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\UFP\" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PreBuildEvent>
|
<PreBuildEvent>
|
||||||
"C:\Program Files\PsTools\pskill.exe" XDesProc.exe 2>nul 1>nul
|
"C:\Program Files\PsTools\pskill.exe" XDesProc.exe 2>nul 1>nul
|
||||||
|
|||||||
Reference in New Issue
Block a user