mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16:40 +10:00
fix: Modern Flash App Label mode switching
This commit is contained in:
@@ -26,8 +26,6 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
internal class LumiaBootManagerAppModel : NokiaFlashModel
|
internal class LumiaBootManagerAppModel : NokiaFlashModel
|
||||||
{
|
{
|
||||||
private readonly PhoneInfo Info = new();
|
|
||||||
|
|
||||||
internal enum SecureBootKeyType : byte
|
internal enum SecureBootKeyType : byte
|
||||||
{
|
{
|
||||||
Retail = 0,
|
Retail = 0,
|
||||||
@@ -110,108 +108,10 @@ namespace WPinternals
|
|||||||
// NOKV = Info Query
|
// NOKV = Info Query
|
||||||
|
|
||||||
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
||||||
|
ReadPhoneInfoCommon();
|
||||||
|
|
||||||
PhoneInfo Result = Info;
|
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.BootManager:
|
|
||||||
Result.BootManagerProtocolVersionMajor = Response[6];
|
|
||||||
Result.BootManagerProtocolVersionMinor = Response[7];
|
|
||||||
Result.BootManagerVersionMajor = Response[8];
|
|
||||||
Result.BootManagerVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.FlashApp:
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.FlashAppVersionMajor = Response[8];
|
|
||||||
Result.FlashAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.PhoneInfoApp:
|
|
||||||
Result.PhoneInfoAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.PhoneInfoAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.PhoneInfoAppVersionMajor = Response[8];
|
|
||||||
Result.PhoneInfoAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte SubblockCount = Response[10];
|
|
||||||
int SubblockOffset = 11;
|
|
||||||
|
|
||||||
for (int i = 0; i < SubblockCount; i++)
|
|
||||||
{
|
|
||||||
byte SubblockID = Response[SubblockOffset + 0x00];
|
|
||||||
UInt16 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.BootManager)
|
|
||||||
{
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
|
|
||||||
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
|
|
||||||
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
|
|
||||||
}
|
|
||||||
else 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:
|
|
||||||
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:
|
|
||||||
SubblockVersion = Response[SubblockPayloadOffset]; // 0x01
|
|
||||||
Result.SecureFfuSupportedProtocolMask = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 0x01);
|
|
||||||
break;
|
|
||||||
case 0x1F:
|
|
||||||
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
// CRC header info
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SubblockOffset += SubblockLength + 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result.State = PhoneInfoState.Basic;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
|
||||||
|
|
||||||
if (!PhoneInfoLogged)
|
if (!PhoneInfoLogged)
|
||||||
{
|
{
|
||||||
Result.Log(LogType.FileOnly);
|
Result.Log(LogType.FileOnly);
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ namespace WPinternals
|
|||||||
ProductType = ProductType.ToUpper();
|
ProductType = ProductType.ToUpper();
|
||||||
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
||||||
{
|
{
|
||||||
ProductType = "RM-" + ProductType[2..];
|
ProductType = $"RM-{ProductType[2..]}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,10 +212,10 @@ namespace WPinternals
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoftwarePackage Package = null;
|
SoftwarePackage Package = null;
|
||||||
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
|
using (MemoryStream JsonResultStream = new(Encoding.UTF8.GetBytes(JsonResultString)))
|
||||||
{
|
{
|
||||||
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
|
DataContractJsonSerializer SoftwarePackagesJsonSerializer = new(typeof(SoftwarePackages));
|
||||||
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
|
SoftwarePackages SoftwarePackages = (SoftwarePackages)SoftwarePackagesJsonSerializer.ReadObject(JsonResultStream);
|
||||||
if (SoftwarePackages != null)
|
if (SoftwarePackages != null)
|
||||||
{
|
{
|
||||||
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
|
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ namespace WPinternals
|
|||||||
|
|
||||||
internal class LumiaFlashAppModel : NokiaFlashModel
|
internal class LumiaFlashAppModel : NokiaFlashModel
|
||||||
{
|
{
|
||||||
private readonly PhoneInfo Info = new();
|
|
||||||
private UefiSecurityStatusResponse _SecurityStatus = null;
|
private UefiSecurityStatusResponse _SecurityStatus = null;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -163,106 +162,10 @@ namespace WPinternals
|
|||||||
// NOKV = Info Query
|
// NOKV = Info Query
|
||||||
|
|
||||||
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
||||||
|
ReadPhoneInfoCommon();
|
||||||
|
|
||||||
PhoneInfo Result = Info;
|
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.BootManager:
|
|
||||||
Result.BootManagerProtocolVersionMajor = Response[6];
|
|
||||||
Result.BootManagerProtocolVersionMinor = Response[7];
|
|
||||||
Result.BootManagerVersionMajor = Response[8];
|
|
||||||
Result.BootManagerVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.FlashApp:
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.FlashAppVersionMajor = Response[8];
|
|
||||||
Result.FlashAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.PhoneInfoApp:
|
|
||||||
Result.PhoneInfoAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.PhoneInfoAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.PhoneInfoAppVersionMajor = Response[8];
|
|
||||||
Result.PhoneInfoAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte SubblockCount = Response[10];
|
|
||||||
int SubblockOffset = 11;
|
|
||||||
|
|
||||||
for (int i = 0; i < SubblockCount; i++)
|
|
||||||
{
|
|
||||||
byte SubblockID = Response[SubblockOffset + 0x00];
|
|
||||||
UInt16 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.BootManager)
|
|
||||||
{
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
|
|
||||||
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
|
|
||||||
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
|
|
||||||
}
|
|
||||||
else 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:
|
|
||||||
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:
|
|
||||||
SubblockVersion = Response[SubblockPayloadOffset]; // 0x01
|
|
||||||
Result.SecureFfuSupportedProtocolMask = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 0x01);
|
|
||||||
break;
|
|
||||||
case 0x1F:
|
|
||||||
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
// CRC header info
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SubblockOffset += SubblockLength + 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result.State = PhoneInfoState.Basic;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
|
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
|
||||||
{
|
{
|
||||||
if (Result.App == FlashAppType.FlashApp)
|
if (Result.App == FlashAppType.FlashApp)
|
||||||
@@ -274,8 +177,6 @@ namespace WPinternals
|
|||||||
Result.State = PhoneInfoState.Extended;
|
Result.State = PhoneInfoState.Extended;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
|
||||||
|
|
||||||
if (!PhoneInfoLogged)
|
if (!PhoneInfoLogged)
|
||||||
{
|
{
|
||||||
Result.Log(LogType.FileOnly);
|
Result.Log(LogType.FileOnly);
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
internal class LumiaPhoneInfoAppModel : NokiaFlashModel
|
internal class LumiaPhoneInfoAppModel : NokiaFlashModel
|
||||||
{
|
{
|
||||||
private readonly PhoneInfo Info = new();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Not valid commands
|
// Not valid commands
|
||||||
//
|
//
|
||||||
@@ -101,106 +99,10 @@ namespace WPinternals
|
|||||||
// NOKV = Info Query
|
// NOKV = Info Query
|
||||||
|
|
||||||
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
||||||
|
ReadPhoneInfoCommon();
|
||||||
|
|
||||||
PhoneInfo Result = Info;
|
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.BootManager:
|
|
||||||
Result.BootManagerProtocolVersionMajor = Response[6];
|
|
||||||
Result.BootManagerProtocolVersionMinor = Response[7];
|
|
||||||
Result.BootManagerVersionMajor = Response[8];
|
|
||||||
Result.BootManagerVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.FlashApp:
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.FlashAppVersionMajor = Response[8];
|
|
||||||
Result.FlashAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
case FlashAppType.PhoneInfoApp:
|
|
||||||
Result.PhoneInfoAppProtocolVersionMajor = Response[6];
|
|
||||||
Result.PhoneInfoAppProtocolVersionMinor = Response[7];
|
|
||||||
Result.PhoneInfoAppVersionMajor = Response[8];
|
|
||||||
Result.PhoneInfoAppVersionMinor = Response[9];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte SubblockCount = Response[10];
|
|
||||||
int SubblockOffset = 11;
|
|
||||||
|
|
||||||
for (int i = 0; i < SubblockCount; i++)
|
|
||||||
{
|
|
||||||
byte SubblockID = Response[SubblockOffset + 0x00];
|
|
||||||
UInt16 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.BootManager)
|
|
||||||
{
|
|
||||||
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
|
|
||||||
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
|
|
||||||
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
|
|
||||||
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
|
|
||||||
}
|
|
||||||
else 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:
|
|
||||||
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:
|
|
||||||
SubblockVersion = Response[SubblockPayloadOffset]; // 0x01
|
|
||||||
Result.SecureFfuSupportedProtocolMask = BigEndian.ToUInt16(Response, SubblockPayloadOffset + 0x01);
|
|
||||||
break;
|
|
||||||
case 0x1F:
|
|
||||||
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
// CRC header info
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SubblockOffset += SubblockLength + 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result.State = PhoneInfoState.Basic;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
|
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -217,8 +119,6 @@ namespace WPinternals
|
|||||||
Result.State = PhoneInfoState.Extended;
|
Result.State = PhoneInfoState.Extended;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
|
||||||
|
|
||||||
if (!PhoneInfoLogged)
|
if (!PhoneInfoLogged)
|
||||||
{
|
{
|
||||||
Result.Log(LogType.FileOnly);
|
Result.Log(LogType.FileOnly);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace WPinternals
|
namespace WPinternals
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
private string _devicePath;
|
private string _devicePath;
|
||||||
|
|
||||||
private readonly PhoneInfo Info = new();
|
internal readonly PhoneInfo Info = new();
|
||||||
|
|
||||||
internal event InterfaceChangedHandler InterfaceChanged = delegate { };
|
internal event InterfaceChangedHandler InterfaceChanged = delegate { };
|
||||||
|
|
||||||
@@ -60,7 +61,20 @@ namespace WPinternals
|
|||||||
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
|
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
|
||||||
{
|
{
|
||||||
PhoneInfo info = ReadPhoneInfoCommon();
|
PhoneInfo info = ReadPhoneInfoCommon();
|
||||||
bool ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
|
||||||
|
bool ModernFlashApp = false;
|
||||||
|
switch (info.App)
|
||||||
|
{
|
||||||
|
case FlashAppType.FlashApp:
|
||||||
|
ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.PhoneInfoApp:
|
||||||
|
ModernFlashApp = info.PhoneInfoAppVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.BootManager:
|
||||||
|
ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Request = new byte[7];
|
byte[] Request = new byte[7];
|
||||||
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "B");
|
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "B");
|
||||||
@@ -95,7 +109,20 @@ namespace WPinternals
|
|||||||
internal void SwitchToPhoneInfoAppContext()
|
internal void SwitchToPhoneInfoAppContext()
|
||||||
{
|
{
|
||||||
PhoneInfo info = ReadPhoneInfoCommon();
|
PhoneInfo info = ReadPhoneInfoCommon();
|
||||||
bool ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
|
||||||
|
bool ModernFlashApp = false;
|
||||||
|
switch (info.App)
|
||||||
|
{
|
||||||
|
case FlashAppType.FlashApp:
|
||||||
|
ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.PhoneInfoApp:
|
||||||
|
ModernFlashApp = info.PhoneInfoAppVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.BootManager:
|
||||||
|
ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Request = new byte[7];
|
byte[] Request = new byte[7];
|
||||||
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
|
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
|
||||||
@@ -141,7 +168,20 @@ namespace WPinternals
|
|||||||
internal void SwitchToFlashAppContext()
|
internal void SwitchToFlashAppContext()
|
||||||
{
|
{
|
||||||
PhoneInfo info = ReadPhoneInfoCommon();
|
PhoneInfo info = ReadPhoneInfoCommon();
|
||||||
bool ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
|
||||||
|
bool ModernFlashApp = false;
|
||||||
|
switch (info.App)
|
||||||
|
{
|
||||||
|
case FlashAppType.FlashApp:
|
||||||
|
ModernFlashApp = info.FlashAppProtocolVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.PhoneInfoApp:
|
||||||
|
ModernFlashApp = info.PhoneInfoAppVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
case FlashAppType.BootManager:
|
||||||
|
ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Request = new byte[7];
|
byte[] Request = new byte[7];
|
||||||
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "F"); // This will stop charging the phone
|
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "F"); // This will stop charging the phone
|
||||||
@@ -203,7 +243,6 @@ namespace WPinternals
|
|||||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||||
// NOKV = Info Query
|
// NOKV = Info Query
|
||||||
|
|
||||||
bool PhoneInfoLogged = Info.State != PhoneInfoState.Empty;
|
|
||||||
PhoneInfo Result = Info;
|
PhoneInfo Result = Info;
|
||||||
|
|
||||||
if (Result.State == PhoneInfoState.Empty)
|
if (Result.State == PhoneInfoState.Empty)
|
||||||
@@ -257,6 +296,19 @@ namespace WPinternals
|
|||||||
case 0x03:
|
case 0x03:
|
||||||
Result.EmmcSizeInSectors = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
Result.EmmcSizeInSectors = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
break;
|
break;
|
||||||
|
case 0x04:
|
||||||
|
if (Result.App == FlashAppType.BootManager)
|
||||||
|
{
|
||||||
|
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
|
||||||
|
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
|
||||||
|
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
|
||||||
|
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
|
||||||
|
}
|
||||||
|
else if (Result.App == FlashAppType.FlashApp)
|
||||||
|
{
|
||||||
|
Result.SdCardSizeInSectors = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim([' ', '\0']);
|
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim([' ', '\0']);
|
||||||
break;
|
break;
|
||||||
@@ -293,11 +345,6 @@ namespace WPinternals
|
|||||||
|
|
||||||
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
||||||
|
|
||||||
if (!PhoneInfoLogged)
|
|
||||||
{
|
|
||||||
Result.Log(LogType.FileOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -426,8 +426,8 @@ namespace WPinternals
|
|||||||
private void InterfaceChanged(PhoneInterfaces NewInterface, string DevicePath)
|
private void InterfaceChanged(PhoneInterfaces NewInterface, string DevicePath)
|
||||||
{
|
{
|
||||||
LastInterface = CurrentInterface;
|
LastInterface = CurrentInterface;
|
||||||
CurrentInterface = null;
|
|
||||||
|
|
||||||
|
CurrentInterface = null;
|
||||||
if (CurrentModel != null)
|
if (CurrentModel != null)
|
||||||
{
|
{
|
||||||
CurrentModel.Dispose();
|
CurrentModel.Dispose();
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ namespace WPinternals
|
|||||||
break;
|
break;
|
||||||
case PhoneInterfaces.Lumia_Bootloader:
|
case PhoneInterfaces.Lumia_Bootloader:
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||||
if (ModernFlashApp)
|
if (ModernFlashApp)
|
||||||
{
|
{
|
||||||
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToBootManagerContext();
|
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToBootManagerContext();
|
||||||
@@ -397,7 +397,7 @@ namespace WPinternals
|
|||||||
break;
|
break;
|
||||||
case PhoneInterfaces.Lumia_PhoneInfo: // attempt to boot from limited phone info to full phone info
|
case PhoneInterfaces.Lumia_PhoneInfo: // attempt to boot from limited phone info to full phone info
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||||
if (ModernFlashApp)
|
if (ModernFlashApp)
|
||||||
{
|
{
|
||||||
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToPhoneInfoAppContext();
|
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToPhoneInfoAppContext();
|
||||||
@@ -410,7 +410,7 @@ namespace WPinternals
|
|||||||
break;
|
break;
|
||||||
case PhoneInterfaces.Lumia_Flash:
|
case PhoneInterfaces.Lumia_Flash:
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
ModernFlashApp = ((LumiaPhoneInfoAppModel)CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||||
if (ModernFlashApp)
|
if (ModernFlashApp)
|
||||||
{
|
{
|
||||||
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToFlashAppContext();
|
((LumiaPhoneInfoAppModel)CurrentModel).SwitchToFlashAppContext();
|
||||||
@@ -713,366 +713,433 @@ namespace WPinternals
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SwitchFromPhoneInfoToLabelMode(bool Continuation = false)
|
private void SwitchFromPhoneInfoToLabelMode(bool Continuation = false)
|
||||||
{
|
{
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Unexpected Mode");
|
||||||
|
}
|
||||||
|
|
||||||
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
||||||
|
|
||||||
((LumiaBootManagerAppModel)CurrentModel).SwitchToFlashAppContext();
|
PhoneInfo PhoneInfoAppInfo = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
|
|
||||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)CurrentModel;
|
new Thread(async () =>
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
|
||||||
|
|
||||||
if (Info.MmosOverUsbSupported)
|
|
||||||
{
|
{
|
||||||
new Thread(() =>
|
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||||
{
|
{
|
||||||
LogFile.BeginAction("SwitchToLabelMode");
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, null);
|
|
||||||
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
|
|
||||||
if (Info.Type == "RM-1152")
|
|
||||||
{
|
|
||||||
Info.Type = "RM-1151";
|
|
||||||
}
|
|
||||||
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(Info.Type, Info.Firmware);
|
|
||||||
SetWorkingStatus("Downloading " + Info.Type + " Test Mode package...", MaxProgressValue: 100);
|
|
||||||
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
|
|
||||||
|
|
||||||
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
|
|
||||||
{
|
|
||||||
if (e.PropertyName == "Progress")
|
|
||||||
{
|
|
||||||
int progress = (sender as DownloadEntry)?.Progress ?? 0;
|
|
||||||
ulong.TryParse(progress.ToString(), out ulong progressret);
|
|
||||||
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
|
|
||||||
|
|
||||||
if (progress == 100)
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
|
||||||
|
|
||||||
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
|
|
||||||
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
FileInfo info = new(MMOSPath);
|
|
||||||
uint length = uint.Parse(info.Length.ToString());
|
|
||||||
const int maximumbuffersize = 0x00240000;
|
|
||||||
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
|
|
||||||
|
|
||||||
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
|
|
||||||
|
|
||||||
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
|
||||||
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
|
||||||
|
|
||||||
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception Ex)
|
|
||||||
{
|
|
||||||
LogFile.LogException(Ex);
|
|
||||||
ModeSwitchErrorWrapper(Ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.EndAction("SwitchToLabelMode");
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
|
|
||||||
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52]; // NOKR
|
|
||||||
|
|
||||||
BootModeFlagCommand[0x0F] = 0x59;
|
|
||||||
((LumiaFlashAppModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
|
||||||
((LumiaFlashAppModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
|
||||||
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SwitchFromFlashToLabelMode(bool Continuation = false)
|
|
||||||
{
|
|
||||||
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
|
||||||
|
|
||||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)CurrentModel;
|
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
|
||||||
|
|
||||||
if (Info.MmosOverUsbSupported)
|
|
||||||
{
|
|
||||||
new Thread(() =>
|
|
||||||
{
|
|
||||||
LogFile.BeginAction("SwitchToLabelMode");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, null);
|
|
||||||
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
|
|
||||||
if (Info.Type == "RM-1152")
|
|
||||||
{
|
|
||||||
Info.Type = "RM-1151";
|
|
||||||
}
|
|
||||||
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(Info.Type, Info.Firmware);
|
|
||||||
SetWorkingStatus("Downloading " + Info.Type + " Test Mode package...", MaxProgressValue: 100);
|
|
||||||
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
|
|
||||||
|
|
||||||
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
|
|
||||||
{
|
|
||||||
if (e.PropertyName == "Progress")
|
|
||||||
{
|
|
||||||
int progress = (sender as DownloadEntry)?.Progress ?? 0;
|
|
||||||
ulong.TryParse(progress.ToString(), out ulong progressret);
|
|
||||||
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
|
|
||||||
|
|
||||||
if (progress == 100)
|
|
||||||
{
|
|
||||||
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
|
||||||
|
|
||||||
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
|
|
||||||
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
FileInfo info = new(MMOSPath);
|
|
||||||
uint length = uint.Parse(info.Length.ToString());
|
|
||||||
const int maximumbuffersize = 0x00240000;
|
|
||||||
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
|
|
||||||
|
|
||||||
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
|
|
||||||
|
|
||||||
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
|
||||||
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
|
||||||
|
|
||||||
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception Ex)
|
|
||||||
{
|
|
||||||
LogFile.LogException(Ex);
|
|
||||||
ModeSwitchErrorWrapper(Ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.EndAction("SwitchToLabelMode");
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
|
|
||||||
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52]; // NOKR
|
|
||||||
|
|
||||||
BootModeFlagCommand[0x0F] = 0x59;
|
|
||||||
((LumiaFlashAppModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
|
||||||
((LumiaFlashAppModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
|
||||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
|
||||||
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void SwitchFromPhoneInfoToMassStorageMode(bool Continuation = false)
|
|
||||||
{
|
|
||||||
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
|
|
||||||
|
|
||||||
((LumiaBootManagerAppModel)CurrentModel).SwitchToFlashAppContext();
|
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
|
|
||||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)CurrentModel;
|
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
|
||||||
|
|
||||||
MassStorageWarning = null;
|
|
||||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
|
||||||
{
|
|
||||||
MassStorageWarning = "Switching to Mass Storage mode should take about 10 seconds. The phone 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. To reboot the phone, you have to perform a soft-reset. Press and hold the volume-down-button and the power-button at the same time for at least 10 seconds. This will trigger a power-cycle and the phone will reboot. Once fully booted, the phone may show strange behavior, like complaining about mail-accounts, showing old text-messages, inability to load https-websites, etc. This is expected behavior, because the time-settings of the phone are incorrect. Just wait a few seconds for the phone to get a data-connection and have the date/time synced. After that the strange behavior will stop automatically and normal operation is resumed.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MassStorageWarning = "When the screen of the phone is black for a while, it could be that the phone is already in Mass Storage Mode, but there is no drive-letter assigned. To resolve this issue, open Device Manager and manually assign a drive-letter to the MainOS partition of your phone, or open a command-prompt and type: diskpart automount enable.";
|
|
||||||
if (App.IsPnPEventLogMissing)
|
|
||||||
{
|
|
||||||
MassStorageWarning += " It is also possible that the phone is in Mass Storage mode, but the Mass Storage driver on this PC failed. Your PC does not have an eventlog to detect this misbehaviour. But in this case you will see a device with an exclamation mark in Device Manager and then you need to manually reset the phone by pressing and holding the power-button for at least 10 seconds until it vibrates and reboots. After that Windows Phone Internals will revert the changes. After the phone has rebooted to the OS, you can retry to unlock the bootloader.";
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool IsOldLumia = Info.FlashAppProtocolVersionMajor < 2;
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||||
bool IsNewLumia = Info.FlashAppProtocolVersionMajor >= 2;
|
|
||||||
bool IsUnlockedNew = false;
|
|
||||||
if (IsNewLumia)
|
|
||||||
{
|
|
||||||
GPT GPT = FlashModel.ReadGPT();
|
|
||||||
IsUnlockedNew = (GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null);
|
|
||||||
}
|
|
||||||
bool IsOriginalEngineeringLumia = !Info.IsBootloaderSecure && !IsUnlockedNew;
|
|
||||||
|
|
||||||
if (IsOldLumia || IsOriginalEngineeringLumia)
|
|
||||||
{
|
|
||||||
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
|
||||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
|
||||||
byte[] RebootToMassStorageCommand = [0x4E, 0x4F, 0x4B, 0x4D]; // NOKM
|
|
||||||
IsSwitchingInterface = true;
|
|
||||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
|
||||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
|
|
||||||
{
|
{
|
||||||
BootModeFlagCommand[0x0F] = 0x4D;
|
throw new WPinternalsException("Unexpected Mode");
|
||||||
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
}
|
||||||
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
|
||||||
if (ResultCode == 0)
|
|
||||||
{
|
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
|
||||||
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
||||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
|
||||||
}
|
if (Info.MmosOverUsbSupported)
|
||||||
else
|
{
|
||||||
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
|
LogFile.BeginAction("SwitchToLabelMode");
|
||||||
IsSwitchingInterface = false;
|
|
||||||
}
|
try
|
||||||
|
{
|
||||||
|
ModeSwitchProgressWrapper(ProgressText, null);
|
||||||
|
|
||||||
|
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
|
||||||
|
|
||||||
|
if (PhoneInfoAppInfo.Type == "RM-1152")
|
||||||
|
{
|
||||||
|
PhoneInfoAppInfo.Type = "RM-1151";
|
||||||
|
}
|
||||||
|
|
||||||
|
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(PhoneInfoAppInfo.Type, Info.Firmware);
|
||||||
|
|
||||||
|
SetWorkingStatus($"Downloading {Info.Type} Test Mode package...", MaxProgressValue: 100);
|
||||||
|
|
||||||
|
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
|
||||||
|
|
||||||
|
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
|
||||||
|
{
|
||||||
|
if (e.PropertyName == "Progress")
|
||||||
|
{
|
||||||
|
int progress = (sender as DownloadEntry)?.Progress ?? 0;
|
||||||
|
ulong.TryParse(progress.ToString(), out ulong progressret);
|
||||||
|
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
|
||||||
|
|
||||||
|
if (progress == 100)
|
||||||
|
{
|
||||||
|
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
||||||
|
|
||||||
|
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
|
||||||
|
|
||||||
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
FileInfo info = new(MMOSPath);
|
||||||
|
uint length = uint.Parse(info.Length.ToString());
|
||||||
|
const int maximumbuffersize = 0x00240000;
|
||||||
|
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
|
||||||
|
|
||||||
|
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
|
||||||
|
|
||||||
|
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
||||||
|
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
||||||
|
|
||||||
|
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception Ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(Ex);
|
||||||
|
ModeSwitchErrorWrapper(Ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogFile.EndAction("SwitchToLabelMode");
|
||||||
|
}).Start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
||||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52]; // NOKR
|
||||||
|
|
||||||
|
BootModeFlagCommand[0x0F] = 0x59;
|
||||||
|
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||||
|
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||||
|
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
||||||
|
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
||||||
}
|
}
|
||||||
}
|
}).Start();
|
||||||
else if (IsUnlockedNew)
|
}
|
||||||
|
|
||||||
|
private void SwitchFromFlashToLabelMode(bool Continuation = false)
|
||||||
|
{
|
||||||
|
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||||
{
|
{
|
||||||
new Thread(async () =>
|
throw new WPinternalsException("Unexpected Mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
PhoneInfo Info = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||||
|
|
||||||
|
new Thread(async () =>
|
||||||
|
{
|
||||||
|
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||||
{
|
{
|
||||||
LogFile.BeginAction("SwitchToMassStorageMode");
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
}
|
||||||
|
|
||||||
try
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Unexpected Mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
PhoneInfo PhoneInfoAppInfo = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||||
|
|
||||||
|
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||||
|
{
|
||||||
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Unexpected Mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||||
|
|
||||||
|
if (Info.MmosOverUsbSupported)
|
||||||
|
{
|
||||||
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
// Implementation of writing a partition with SecureBoot variable to the phone
|
LogFile.BeginAction("SwitchToLabelMode");
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
|
||||||
LogFile.Log("Preparing phone for Mass Storage Mode", LogType.FileAndConsole);
|
|
||||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
|
||||||
|
|
||||||
// Magic!
|
try
|
||||||
// The SBMSM resource is a compressed version of a raw NV-variable-partition.
|
|
||||||
// In this partition the SecureBoot variable is disabled and an extra variable is added which triggers Mass Storage Mode on next reboot.
|
|
||||||
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
|
|
||||||
// This normally leads to endless-loops when the NV-variables are enumerated.
|
|
||||||
// But the partition contains an extra hack to break out the endless loops.
|
|
||||||
using (var stream = assembly.GetManifestResourceStream("WPinternals.SBMSM"))
|
|
||||||
{
|
{
|
||||||
using DecompressedStream dec = new(stream);
|
ModeSwitchProgressWrapper(ProgressText, null);
|
||||||
using MemoryStream SB = new(); // Must be a seekable stream!
|
|
||||||
dec.CopyTo(SB);
|
|
||||||
|
|
||||||
// We don't need to check for the BACKUP_BS_NV partition here,
|
string TempFolder = Environment.GetEnvironmentVariable("TEMP") + @"\WPInternals";
|
||||||
// because the SecureBoot flag is disabled here.
|
|
||||||
// So either the NV was already backupped or already overwritten.
|
|
||||||
|
|
||||||
GPT GPT = FlashModel.ReadGPT();
|
if (PhoneInfoAppInfo.Type == "RM-1152")
|
||||||
Partition Target = GPT.GetPartition("UEFI_BS_NV");
|
{
|
||||||
|
PhoneInfoAppInfo.Type = "RM-1151";
|
||||||
|
}
|
||||||
|
|
||||||
// We've been reading the GPT, so we let the phone reset once more to be sure that memory maps are the same
|
string ENOSWPackage = LumiaDownloadModel.SearchENOSW(PhoneInfoAppInfo.Type, Info.Firmware);
|
||||||
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
|
|
||||||
List<FlashPart> Parts = new();
|
SetWorkingStatus($"Downloading {PhoneInfoAppInfo.Type} Test Mode package...", MaxProgressValue: 100);
|
||||||
FlashPart Part = new();
|
|
||||||
Part.StartSector = (uint)Target.FirstSector;
|
DownloadEntry downloadEntry = new(ENOSWPackage, TempFolder, null, null, null);
|
||||||
Part.Stream = SB;
|
|
||||||
Parts.Add(Part);
|
downloadEntry.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
|
||||||
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, null, false, false, Parts, DoResetFirst: true, ClearFlashingStatusAtEnd: false, ShowProgress: false,
|
{
|
||||||
SetWorkingStatus: (m, s, v, a, st) =>
|
if (e.PropertyName == "Progress")
|
||||||
{
|
{
|
||||||
if (SetWorkingStatus != null)
|
int progress = (sender as DownloadEntry)?.Progress ?? 0;
|
||||||
|
ulong.TryParse(progress.ToString(), out ulong progressret);
|
||||||
|
UpdateWorkingStatus(null, CurrentProgressValue: progressret);
|
||||||
|
|
||||||
|
if (progress == 100)
|
||||||
{
|
{
|
||||||
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
||||||
{
|
|
||||||
SetWorkingStatus(m, s, v, a, st);
|
|
||||||
}
|
|
||||||
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
SetWorkingStatus(ProgressText, MassStorageWarning);
|
|
||||||
}
|
|
||||||
|
|
||||||
LastStatus = st;
|
string MMOSPath = TempFolder + "\\" + (sender as DownloadEntry)?.Name;
|
||||||
|
|
||||||
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
FileInfo info = new(MMOSPath);
|
||||||
|
uint length = uint.Parse(info.Length.ToString());
|
||||||
|
const int maximumbuffersize = 0x00240000;
|
||||||
|
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
|
||||||
|
|
||||||
|
SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100);
|
||||||
|
|
||||||
|
ProgressUpdater progressUpdater = new(totalcounts + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
||||||
|
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
||||||
|
|
||||||
|
SetWorkingStatus("And now booting phone to MMOS...", "If the phone stays on the lightning cog screen for a while, you may need to unplug and replug the phone to continue the boot process.");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
UpdateWorkingStatus: (m, s, v, st) =>
|
};
|
||||||
{
|
}
|
||||||
if (UpdateWorkingStatus != null)
|
catch (Exception Ex)
|
||||||
{
|
{
|
||||||
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
LogFile.LogException(Ex);
|
||||||
{
|
ModeSwitchErrorWrapper(Ex.Message);
|
||||||
UpdateWorkingStatus(m, s, v, st);
|
|
||||||
}
|
|
||||||
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
|
||||||
{
|
|
||||||
SetWorkingStatus(ProgressText, MassStorageWarning);
|
|
||||||
}
|
|
||||||
|
|
||||||
LastStatus = st;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
LogFile.EndAction("SwitchToLabelMode");
|
||||||
{
|
}).Start();
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
|
||||||
// Wait for bootloader
|
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
||||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52]; // NOKR
|
||||||
{
|
|
||||||
LogFile.Log("Waiting for Mass Storage Mode (1)...", LogType.FileOnly);
|
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
BootModeFlagCommand[0x0F] = 0x59;
|
||||||
{
|
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||||
}
|
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
||||||
|
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
||||||
|
}
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for mass storage mode
|
private void SwitchFromPhoneInfoToMassStorageMode(bool Continuation = false)
|
||||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
{
|
||||||
{
|
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
|
||||||
LogFile.Log("Waiting for Mass Storage Mode (2)...", LogType.FileOnly);
|
|
||||||
await PhoneNotifier.WaitForArrival();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
new Thread(async () =>
|
||||||
{
|
{
|
||||||
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||||
}
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
|
||||||
MassStorage Storage = null;
|
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||||
if (PhoneNotifier.CurrentModel is MassStorage)
|
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||||
{
|
|
||||||
Storage = (MassStorage)PhoneNotifier.CurrentModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Storage == null)
|
MassStorageWarning = null;
|
||||||
|
if (Info.FlashAppProtocolVersionMajor < 2)
|
||||||
|
{
|
||||||
|
MassStorageWarning = "Switching to Mass Storage mode should take about 10 seconds. The phone 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. To reboot the phone, you have to perform a soft-reset. Press and hold the volume-down-button and the power-button at the same time for at least 10 seconds. This will trigger a power-cycle and the phone will reboot. Once fully booted, the phone may show strange behavior, like complaining about mail-accounts, showing old text-messages, inability to load https-websites, etc. This is expected behavior, because the time-settings of the phone are incorrect. Just wait a few seconds for the phone to get a data-connection and have the date/time synced. After that the strange behavior will stop automatically and normal operation is resumed.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MassStorageWarning = "When the screen of the phone is black for a while, it could be that the phone is already in Mass Storage Mode, but there is no drive-letter assigned. To resolve this issue, open Device Manager and manually assign a drive-letter to the MainOS partition of your phone, or open a command-prompt and type: diskpart automount enable.";
|
||||||
|
if (App.IsPnPEventLogMissing)
|
||||||
|
{
|
||||||
|
MassStorageWarning += " It is also possible that the phone is in Mass Storage mode, but the Mass Storage driver on this PC failed. Your PC does not have an eventlog to detect this misbehaviour. But in this case you will see a device with an exclamation mark in Device Manager and then you need to manually reset the phone by pressing and holding the power-button for at least 10 seconds until it vibrates and reboots. After that Windows Phone Internals will revert the changes. After the phone has rebooted to the OS, you can retry to unlock the bootloader.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOldLumia = Info.FlashAppProtocolVersionMajor < 2;
|
||||||
|
bool IsNewLumia = Info.FlashAppProtocolVersionMajor >= 2;
|
||||||
|
bool IsUnlockedNew = false;
|
||||||
|
if (IsNewLumia)
|
||||||
|
{
|
||||||
|
GPT GPT = FlashModel.ReadGPT();
|
||||||
|
IsUnlockedNew = (GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null);
|
||||||
|
}
|
||||||
|
bool IsOriginalEngineeringLumia = !Info.IsBootloaderSecure && !IsUnlockedNew;
|
||||||
|
|
||||||
|
if (IsOldLumia || IsOriginalEngineeringLumia)
|
||||||
|
{
|
||||||
|
byte[] BootModeFlagCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x46, 0x57, 0x00, 0x55, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // NOKFW UBF
|
||||||
|
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
||||||
|
byte[] RebootToMassStorageCommand = [0x4E, 0x4F, 0x4B, 0x4D]; // NOKM
|
||||||
|
IsSwitchingInterface = true;
|
||||||
|
byte[] RebootCommandResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
||||||
|
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
|
||||||
|
{
|
||||||
|
BootModeFlagCommand[0x0F] = 0x4D;
|
||||||
|
byte[] BootFlagResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||||
|
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
||||||
|
if (ResultCode == 0)
|
||||||
{
|
{
|
||||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage Mode");
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
|
||||||
|
((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||||
|
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||||
|
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ModeSwitchSuccessWrapper();
|
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
|
||||||
|
IsSwitchingInterface = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception Ex)
|
else
|
||||||
{
|
{
|
||||||
LogFile.LogException(Ex);
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
ModeSwitchErrorWrapper(Ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogFile.EndAction("SwitchToMassStorageMode");
|
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||||
}).Start();
|
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else if (IsUnlockedNew)
|
||||||
ModeSwitchErrorWrapper("Bootloader was not unlocked. First unlock bootloader before you try to switch to Mass Storage Mode.");
|
{
|
||||||
}
|
new Thread(async () =>
|
||||||
|
{
|
||||||
|
LogFile.BeginAction("SwitchToMassStorageMode");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Implementation of writing a partition with SecureBoot variable to the phone
|
||||||
|
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||||
|
LogFile.Log("Preparing phone for Mass Storage Mode", LogType.FileAndConsole);
|
||||||
|
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
// Magic!
|
||||||
|
// The SBMSM resource is a compressed version of a raw NV-variable-partition.
|
||||||
|
// In this partition the SecureBoot variable is disabled and an extra variable is added which triggers Mass Storage Mode on next reboot.
|
||||||
|
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
|
||||||
|
// This normally leads to endless-loops when the NV-variables are enumerated.
|
||||||
|
// But the partition contains an extra hack to break out the endless loops.
|
||||||
|
using (var stream = assembly.GetManifestResourceStream("WPinternals.SBMSM"))
|
||||||
|
{
|
||||||
|
using DecompressedStream dec = new(stream);
|
||||||
|
using MemoryStream SB = new(); // Must be a seekable stream!
|
||||||
|
dec.CopyTo(SB);
|
||||||
|
|
||||||
|
// We don't need to check for the BACKUP_BS_NV partition here,
|
||||||
|
// because the SecureBoot flag is disabled here.
|
||||||
|
// So either the NV was already backupped or already overwritten.
|
||||||
|
|
||||||
|
GPT GPT = FlashModel.ReadGPT();
|
||||||
|
Partition Target = GPT.GetPartition("UEFI_BS_NV");
|
||||||
|
|
||||||
|
// We've been reading the GPT, so we let the phone reset once more to be sure that memory maps are the same
|
||||||
|
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
|
||||||
|
List<FlashPart> Parts = new();
|
||||||
|
FlashPart Part = new();
|
||||||
|
Part.StartSector = (uint)Target.FirstSector;
|
||||||
|
Part.Stream = SB;
|
||||||
|
Parts.Add(Part);
|
||||||
|
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, null, false, false, Parts, DoResetFirst: true, ClearFlashingStatusAtEnd: false, ShowProgress: false,
|
||||||
|
SetWorkingStatus: (m, s, v, a, st) =>
|
||||||
|
{
|
||||||
|
if (SetWorkingStatus != null)
|
||||||
|
{
|
||||||
|
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
||||||
|
{
|
||||||
|
SetWorkingStatus(m, s, v, a, st);
|
||||||
|
}
|
||||||
|
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
||||||
|
{
|
||||||
|
SetWorkingStatus(ProgressText, MassStorageWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
LastStatus = st;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpdateWorkingStatus: (m, s, v, st) =>
|
||||||
|
{
|
||||||
|
if (UpdateWorkingStatus != null)
|
||||||
|
{
|
||||||
|
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
||||||
|
{
|
||||||
|
UpdateWorkingStatus(m, s, v, st);
|
||||||
|
}
|
||||||
|
else if ((LastStatus == WPinternalsStatus.Scanning) || (LastStatus == WPinternalsStatus.WaitingForManualReset))
|
||||||
|
{
|
||||||
|
SetWorkingStatus(ProgressText, MassStorageWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
LastStatus = st;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for bootloader
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
||||||
|
{
|
||||||
|
LogFile.Log("Waiting for Mass Storage Mode (1)...", LogType.FileOnly);
|
||||||
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for mass storage mode
|
||||||
|
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_MassStorage)
|
||||||
|
{
|
||||||
|
LogFile.Log("Waiting for Mass Storage Mode (2)...", LogType.FileOnly);
|
||||||
|
await PhoneNotifier.WaitForArrival();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_BadMassStorage)
|
||||||
|
{
|
||||||
|
throw new WPinternalsException("Phone is in Mass Storage mode, but the driver on PC failed to start");
|
||||||
|
}
|
||||||
|
|
||||||
|
MassStorage Storage = null;
|
||||||
|
if (PhoneNotifier.CurrentModel is MassStorage)
|
||||||
|
{
|
||||||
|
Storage = (MassStorage)PhoneNotifier.CurrentModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Storage == null)
|
||||||
|
{
|
||||||
|
ModeSwitchErrorWrapper("Failed to switch to Mass Storage Mode");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModeSwitchSuccessWrapper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception Ex)
|
||||||
|
{
|
||||||
|
LogFile.LogException(Ex);
|
||||||
|
ModeSwitchErrorWrapper(Ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogFile.EndAction("SwitchToMassStorageMode");
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModeSwitchErrorWrapper("Bootloader was not unlocked. First unlock bootloader before you try to switch to Mass Storage Mode.");
|
||||||
|
}
|
||||||
|
}).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SwitchFromFlashToMassStorageMode(bool Continuation = false)
|
private void SwitchFromFlashToMassStorageMode(bool Continuation = false)
|
||||||
@@ -1082,14 +1149,14 @@ namespace WPinternals
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((LumiaBootManagerAppModel)CurrentModel).SwitchToFlashAppContext();
|
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogFile.LogException(ex, LogType.FileOnly);
|
LogFile.LogException(ex, LogType.FileOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)CurrentModel;
|
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||||
|
|
||||||
MassStorageWarning = null;
|
MassStorageWarning = null;
|
||||||
@@ -1122,17 +1189,17 @@ namespace WPinternals
|
|||||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
||||||
byte[] RebootToMassStorageCommand = [0x4E, 0x4F, 0x4B, 0x4D]; // NOKM
|
byte[] RebootToMassStorageCommand = [0x4E, 0x4F, 0x4B, 0x4D]; // NOKM
|
||||||
IsSwitchingInterface = true;
|
IsSwitchingInterface = true;
|
||||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
byte[] RebootCommandResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
||||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
|
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknown command)
|
||||||
{
|
{
|
||||||
BootModeFlagCommand[0x0F] = 0x4D;
|
BootModeFlagCommand[0x0F] = 0x4D;
|
||||||
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
byte[] BootFlagResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||||
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
||||||
if (ResultCode == 0)
|
if (ResultCode == 0)
|
||||||
{
|
{
|
||||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||||
|
|
||||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user