mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-08-10 01:51:15 +10:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a982c119fb | ||
|
|
c6dee3fe33 | ||
|
|
91961b0e7b | ||
|
|
29c6ab06d4 | ||
|
|
b03b561724 | ||
|
|
91f534a7c3 | ||
|
|
f0f3268924 | ||
|
|
c269cfe839 | ||
|
|
7d8aad0e88 | ||
|
|
310d0b97c5 | ||
|
|
8e50c46357 | ||
|
|
e6555741b0 | ||
|
|
c21692491d | ||
|
|
350b6e8f1e | ||
|
|
0101477830 | ||
|
|
a6c017986b | ||
|
|
0174fc8b30 | ||
|
|
c6f6ef4429 | ||
|
|
ab0c35e879 | ||
|
|
676a95dd97 |
+108
-52
@@ -83,9 +83,13 @@ namespace WPinternals
|
||||
{
|
||||
FFU FFU = null;
|
||||
PhoneNotifierViewModel Notifier;
|
||||
NokiaFlashModel FlashModel;
|
||||
LumiaFlashAppModel FlashModel;
|
||||
LumiaBootManagerAppModel BootMgrModel;
|
||||
LumiaPhoneInfoAppModel PhoneInfoModel;
|
||||
NokiaPhoneModel NormalModel;
|
||||
PhoneInfo Info;
|
||||
LumiaFlashAppPhoneInfo FlashInfo;
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfo;
|
||||
LumiaBootManagerPhoneInfo BootManagerInfo;
|
||||
string ProductType;
|
||||
string ProductCode;
|
||||
string OperatorCode;
|
||||
@@ -182,23 +186,14 @@ namespace WPinternals
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
|
||||
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader); // This also works for Bootloader Spec A
|
||||
|
||||
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
|
||||
GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
|
||||
foreach (Partition Partition in GPT.Partitions)
|
||||
{
|
||||
LogFile.Log(Partition.Name.PadRight(20) + "0x" + Partition.FirstSector.ToString("X8") + " - 0x" + Partition.LastSector.ToString("X8") + " " + Partition.Volume, LogType.ConsoleOnly);
|
||||
}
|
||||
|
||||
if (FlashModel.ReadPhoneInfo(false).FlashAppProtocolVersionMajor >= 2)
|
||||
{
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
}
|
||||
|
||||
Notifier.Stop();
|
||||
}
|
||||
catch (Exception Ex)
|
||||
@@ -221,15 +216,14 @@ namespace WPinternals
|
||||
{
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
GPT GPT = FlashModel.ReadGPT(); // May throw NotSupportedException
|
||||
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
|
||||
GPT GPT = BootMgrModel.ReadGPT(); // May throw NotSupportedException
|
||||
string DirPath = Path.GetDirectoryName(args[2]);
|
||||
if (!string.IsNullOrEmpty(DirPath) && !Directory.Exists(DirPath))
|
||||
{
|
||||
Directory.CreateDirectory(DirPath);
|
||||
}
|
||||
GPT.WritePartitions(args[2]);
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
Notifier.Stop();
|
||||
}
|
||||
catch (Exception Ex)
|
||||
@@ -281,14 +275,13 @@ namespace WPinternals
|
||||
{
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
byte[] GptChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
BootMgrModel = (LumiaBootManagerAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Bootloader);
|
||||
byte[] GptChunk = BootMgrModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GptChunk);
|
||||
string Xml = File.ReadAllText(args[2]);
|
||||
GPT.MergePartitions(Xml, false);
|
||||
GPT.Rebuild();
|
||||
await LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(Notifier, null, false, false, 0, GptChunk, true, true);
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
Notifier.Stop();
|
||||
}
|
||||
catch (Exception Ex)
|
||||
@@ -318,7 +311,10 @@ namespace WPinternals
|
||||
s = new FileStream(args[3], FileMode.Open, FileAccess.Read);
|
||||
Archive = new ZipArchive(s);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
if (Archive == null)
|
||||
{
|
||||
@@ -549,9 +545,9 @@ namespace WPinternals
|
||||
try
|
||||
{
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
FlashInfo.Log(LogType.ConsoleOnly);
|
||||
|
||||
FFU ProfileFFU = null;
|
||||
FFU CurrentFFU;
|
||||
@@ -564,7 +560,7 @@ namespace WPinternals
|
||||
string PlatformID = CurrentFFU.PlatformID;
|
||||
|
||||
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
||||
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ProfileFFU = CurrentFFU;
|
||||
}
|
||||
@@ -573,7 +569,7 @@ namespace WPinternals
|
||||
|
||||
if (ProfileFFU == null)
|
||||
{
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
ProfileFFU = FFUs.Count > 0
|
||||
? new FFU(FFUs[0].Path)
|
||||
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
||||
@@ -698,9 +694,9 @@ namespace WPinternals
|
||||
LogFile.Log("Command: Show phone info", LogType.FileAndConsole);
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
FlashInfo.Log(LogType.ConsoleOnly);
|
||||
Notifier.Stop();
|
||||
break;
|
||||
case "unlockbootloader":
|
||||
@@ -710,9 +706,9 @@ namespace WPinternals
|
||||
LogFile.Log("Command: Unlock Bootloader", LogType.FileAndConsole);
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
FlashInfo.Log(LogType.ConsoleOnly);
|
||||
|
||||
FFU ProfileFFU = null;
|
||||
FFU SupportedFFU = null;
|
||||
@@ -726,7 +722,7 @@ namespace WPinternals
|
||||
string PlatformID = CurrentFFU.PlatformID;
|
||||
|
||||
// Check if the current FFU matches the connected phone, so that the FFU can be used for profiling.
|
||||
if (Info.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||
if (FlashInfo.PlatformID.StartsWith(PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ProfileFFU = CurrentFFU;
|
||||
}
|
||||
@@ -741,7 +737,7 @@ namespace WPinternals
|
||||
|
||||
if (ProfileFFU == null)
|
||||
{
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
ProfileFFU = FFUs.Count > 0
|
||||
? new FFU(FFUs[0].Path)
|
||||
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
||||
@@ -783,9 +779,9 @@ namespace WPinternals
|
||||
LogFile.Log("Custom ROM: " + CustomRomPath, LogType.FileAndConsole);
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
FlashInfo.Log(LogType.ConsoleOnly);
|
||||
LogFile.Log("Preparing to flash Custom ROM", LogType.FileAndConsole);
|
||||
await LumiaV2UnlockBootViewModel.LumiaV2FlashArchive(Notifier, CustomRomPath);
|
||||
LogFile.Log("Custom ROM flashed successfully", LogType.FileAndConsole);
|
||||
@@ -814,11 +810,11 @@ namespace WPinternals
|
||||
LogFile.Log("FFU file: " + FFUPath, LogType.FileAndConsole);
|
||||
Notifier = new PhoneNotifierViewModel();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
FlashInfo.Log(LogType.ConsoleOnly);
|
||||
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
|
||||
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
|
||||
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!FlashInfo.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
|
||||
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
|
||||
Notifier.Stop();
|
||||
}
|
||||
@@ -1280,11 +1276,55 @@ namespace WPinternals
|
||||
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
|
||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
||||
}
|
||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
ProductCode = Info.ProductCode;
|
||||
(Notifier.CurrentModel as LumiaBootManagerAppModel).SwitchToPhoneInfoAppContext();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
|
||||
ProductCode = PhoneInfo.ProductCode;
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
|
||||
ProductCode = PhoneInfo.ProductCode;
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
PhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
PhoneInfo = PhoneInfoModel.ReadPhoneInfo();
|
||||
ProductCode = PhoneInfo.ProductCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1445,11 +1485,19 @@ namespace WPinternals
|
||||
ProductType = ProductType.Substring(0, ProductType.IndexOf('_'));
|
||||
}
|
||||
}
|
||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
ProductType = Info.Type;
|
||||
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
|
||||
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
|
||||
//ProductType = BootManagerInfo.Type; // TODO: FIXME
|
||||
ProductType = "";
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
//ProductType = FlashInfo.Type; // TODO: FIXME
|
||||
ProductType = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1556,11 +1604,19 @@ namespace WPinternals
|
||||
NormalModel = (NokiaPhoneModel)Notifier.CurrentModel;
|
||||
ProductCode = NormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode");
|
||||
}
|
||||
else if ((Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) || (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash))
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
ProductCode = Info.ProductCode;
|
||||
BootMgrModel = (LumiaBootManagerAppModel)Notifier.CurrentModel;
|
||||
BootManagerInfo = BootMgrModel.ReadPhoneInfo();
|
||||
//ProductCode = BootManagerInfo.ProductCode; // TODO: FIXME
|
||||
ProductCode = "";
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
FlashInfo = FlashModel.ReadPhoneInfo();
|
||||
//ProductCode = FlashInfo.ProductCode; // TODO: FIXME
|
||||
ProductCode = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -316,13 +316,19 @@ namespace WPinternals
|
||||
{
|
||||
filename = System.IO.Path.GetFileName(Text);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
string directory = "";
|
||||
try
|
||||
{
|
||||
directory = System.IO.Path.GetDirectoryName(Text);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
FormattedText formatted;
|
||||
bool widthOK = false;
|
||||
bool changedWidth = false;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal enum FlashAppType
|
||||
{
|
||||
BootManager = 1,
|
||||
FlashApp = 2,
|
||||
PhoneInfoApp = 3
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class FlashVersion
|
||||
{
|
||||
public int ApplicationMajor;
|
||||
public int ApplicationMinor;
|
||||
public int ProtocolMajor;
|
||||
public int ProtocolMinor;
|
||||
}
|
||||
}
|
||||
@@ -275,7 +275,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
if (NewPartition.LastSector == 0)
|
||||
@@ -471,7 +474,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
DecompressedStream.Close();
|
||||
|
||||
UInt64 MaxPartitionSizeInSectors = OldPartition.SizeInSectors;
|
||||
@@ -521,7 +527,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
DecompressedStream.Close();
|
||||
if (NewPartition.SizeInSectors != StreamLengthInSectors)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace WPinternals
|
||||
return FfuUrl;
|
||||
}
|
||||
|
||||
internal static string SearchENOSW(string ProductType, string PhoneFirmwareRevision)
|
||||
internal static (string SecureWIMUrl, string DPLUrl) SearchENOSW(string ProductType, string PhoneFirmwareRevision)
|
||||
{
|
||||
if (ProductType?.Length == 0)
|
||||
{
|
||||
@@ -170,7 +170,7 @@ namespace WPinternals
|
||||
ProductType = ProductType.ToUpper();
|
||||
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
|
||||
{
|
||||
ProductType = "RM-" + ProductType[2..];
|
||||
ProductType = $"RM-{ProductType[2..]}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ namespace WPinternals
|
||||
packageClass = "Public",
|
||||
manufacturerHardwareModel = ProductType
|
||||
};
|
||||
|
||||
DiscoveryParameters DiscoveryParams = new()
|
||||
{
|
||||
query = DiscoveryQueryParams
|
||||
@@ -212,16 +213,15 @@ namespace WPinternals
|
||||
}
|
||||
|
||||
SoftwarePackage Package = null;
|
||||
using (MemoryStream JsonStream2 = new(Encoding.UTF8.GetBytes(JsonResultString)))
|
||||
using MemoryStream JsonResultStream = new(Encoding.UTF8.GetBytes(JsonResultString));
|
||||
DataContractJsonSerializer SoftwarePackagesJsonSerializer = new(typeof(SoftwarePackages));
|
||||
SoftwarePackages SoftwarePackages = (SoftwarePackages)SoftwarePackagesJsonSerializer.ReadObject(JsonResultStream);
|
||||
|
||||
if (SoftwarePackages != null)
|
||||
{
|
||||
DataContractJsonSerializer Serializer2 = new(typeof(SoftwarePackages));
|
||||
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
|
||||
if (SoftwarePackages != null)
|
||||
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
|
||||
{
|
||||
foreach (SoftwarePackage pkg in SoftwarePackages.softwarePackages)
|
||||
{
|
||||
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
|
||||
}
|
||||
Package = SoftwarePackages.softwarePackages.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,41 +230,40 @@ namespace WPinternals
|
||||
throw new WPinternalsException("ENOSW package not found", "No ENOSW package has been found in the remote software repository for the requested model.");
|
||||
}
|
||||
|
||||
SoftwareFile FileInfo = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
|
||||
SoftwareFile SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".secwim", StringComparison.OrdinalIgnoreCase));
|
||||
SoftwareFile DPLSoftwareFile = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
SoftwareFile DPLF = Package.files.First(f => f.fileName.EndsWith(".dpl", StringComparison.OrdinalIgnoreCase));
|
||||
Uri DPLUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + DPLF.fileName);
|
||||
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLUri);
|
||||
Uri DPLFileUrlUri = new($"https://api.swrepository.com/rest-api/discovery/fileurl/1/{Package.id}/{DPLSoftwareFile.fileName}");
|
||||
|
||||
Task<string> GetDPLTask = HttpClient.GetStringAsync(DPLFileUrlUri);
|
||||
GetDPLTask.Wait();
|
||||
string DPLString = GetDPLTask.Result;
|
||||
|
||||
string DPLUrl = "";
|
||||
FileUrlResult FileUrlDPL = null;
|
||||
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(DPLString)))
|
||||
string DPLFileUrlResultContent = GetDPLTask.Result;
|
||||
FileUrlResult DPLFileUrlResult = null;
|
||||
using MemoryStream DPLFileUrlResultStream = new(Encoding.UTF8.GetBytes(DPLFileUrlResultContent));
|
||||
DataContractJsonSerializer DPLFileUrlResultSerializer = new(typeof(FileUrlResult));
|
||||
DPLFileUrlResult = (FileUrlResult)DPLFileUrlResultSerializer.ReadObject(DPLFileUrlResultStream);
|
||||
|
||||
string DPLFileUrl = "";
|
||||
|
||||
if (DPLFileUrlResult != null)
|
||||
{
|
||||
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
|
||||
FileUrlDPL = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
|
||||
if (FileUrlDPL != null)
|
||||
{
|
||||
DPLUrl = FileUrlDPL.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
||||
}
|
||||
DPLFileUrl = DPLFileUrlResult.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
||||
}
|
||||
|
||||
if (DPLUrl?.Length == 0)
|
||||
if (DPLFileUrl?.Length == 0)
|
||||
{
|
||||
throw new WPinternalsException("DPL not found", "No DPL has been found in the remote software repository for the requested model.");
|
||||
}
|
||||
|
||||
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLUrl);
|
||||
Task<string> GetDPLStrTask = HttpClient.GetStringAsync(DPLFileUrl);
|
||||
GetDPLStrTask.Wait();
|
||||
string DPLStrString = GetDPLStrTask.Result;
|
||||
|
||||
DPL.Package dpl;
|
||||
XmlSerializer serializer = new(typeof(DPL.Package));
|
||||
using (StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", "")))
|
||||
{
|
||||
dpl = (DPL.Package)serializer.Deserialize(reader);
|
||||
}
|
||||
using StringReader reader = new(DPLStrString.Replace("ft:", "").Replace("dpl:", "").Replace("typedes:", ""));
|
||||
dpl = (DPL.Package)serializer.Deserialize(reader);
|
||||
|
||||
foreach (DPL.File file in dpl.Content.Files.File)
|
||||
{
|
||||
@@ -274,30 +273,30 @@ namespace WPinternals
|
||||
|
||||
if (IsFirmwareBetween(PhoneFirmwareRevision, range.From, range.To))
|
||||
{
|
||||
FileInfo = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
|
||||
SecureWimSoftwareFile = Package.files.First(f => f.fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
|
||||
Uri FileInfoUri = new("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + SecureWimSoftwareFile.fileName);
|
||||
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
|
||||
GetFileInfoTask.Wait();
|
||||
string FileInfoString = GetFileInfoTask.Result;
|
||||
|
||||
string ENOSWUrl = "";
|
||||
string ENOSWFileUrl = "";
|
||||
|
||||
FileUrlResult FileUrl = null;
|
||||
using (MemoryStream JsonStream3 = new(Encoding.UTF8.GetBytes(FileInfoString)))
|
||||
|
||||
using MemoryStream JsonStream4 = new(Encoding.UTF8.GetBytes(FileInfoString));
|
||||
DataContractJsonSerializer Serializer4 = new(typeof(FileUrlResult));
|
||||
FileUrl = (FileUrlResult)Serializer4.ReadObject(JsonStream4);
|
||||
if (FileUrl != null)
|
||||
{
|
||||
DataContractJsonSerializer Serializer3 = new(typeof(FileUrlResult));
|
||||
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
|
||||
if (FileUrl != null)
|
||||
{
|
||||
ENOSWUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
||||
}
|
||||
ENOSWFileUrl = FileUrl.url.Replace("sr.azureedge.net", "softwarerepo.blob.core.windows.net");
|
||||
}
|
||||
|
||||
HttpClient.Dispose();
|
||||
|
||||
return ENOSWUrl;
|
||||
return (ENOSWFileUrl, DPLFileUrl);
|
||||
}
|
||||
|
||||
private static bool IsFirmwareBetween(string PhoneFirmwareRevision, string Limit1, string Limit2)
|
||||
|
||||
@@ -73,7 +73,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AttachQualcommSerial(string DevicePath)
|
||||
@@ -119,7 +122,10 @@ namespace WPinternals
|
||||
SerialDevice.Close();
|
||||
SerialDevice.Dispose();
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -40,7 +40,10 @@ namespace WPinternals
|
||||
{
|
||||
Device = new USBDevice(DevicePath);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonElement? ExecuteJsonMethodAsJsonToken(string JsonMethod, Dictionary<string, object> Params, string ResultElement)
|
||||
@@ -173,6 +176,11 @@ namespace WPinternals
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Token.Value.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
return Token.Value.GetString().Equals("true", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
return Token.Value.GetBoolean();
|
||||
}
|
||||
|
||||
@@ -335,7 +343,10 @@ namespace WPinternals
|
||||
Result = new byte[OutputLength];
|
||||
System.Buffer.BlockCopy(Buffer, 0, Result, 0, OutputLength);
|
||||
}
|
||||
catch { } // Reboot command looses connection
|
||||
catch (Exception ex) // Reboot command looses connection
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@@ -363,7 +374,10 @@ namespace WPinternals
|
||||
pipe.Reset();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class CommonPhoneInfo
|
||||
{
|
||||
public PhoneInfoState State = PhoneInfoState.Empty;
|
||||
|
||||
public FlashAppType App;
|
||||
|
||||
public byte VersionMajor;
|
||||
public byte VersionMinor;
|
||||
public byte ProtocolVersionMajor;
|
||||
public byte ProtocolVersionMinor;
|
||||
|
||||
internal void Log(LogType Type)
|
||||
{
|
||||
LogFile.Log($"App: {VersionMajor}.{VersionMinor}", Type);
|
||||
LogFile.Log($"Protocol: {ProtocolVersionMajor}.{ProtocolVersionMinor}", Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaBootManagerPhoneInfo
|
||||
{
|
||||
public PhoneInfoState State = PhoneInfoState.Empty;
|
||||
|
||||
public FlashAppType App;
|
||||
|
||||
public byte FlashAppVersionMajor;
|
||||
public byte FlashAppVersionMinor;
|
||||
public byte FlashAppProtocolVersionMajor;
|
||||
public byte FlashAppProtocolVersionMinor;
|
||||
|
||||
public byte BootManagerVersionMajor;
|
||||
public byte BootManagerVersionMinor;
|
||||
public byte BootManagerProtocolVersionMajor;
|
||||
public byte BootManagerProtocolVersionMinor;
|
||||
|
||||
public UInt32 TransferSize;
|
||||
public bool MmosOverUsbSupported;
|
||||
|
||||
internal void Log(LogType Type)
|
||||
{
|
||||
switch (App)
|
||||
{
|
||||
case FlashAppType.BootManager:
|
||||
LogFile.Log($"Bootmanager: {BootManagerVersionMajor}.{BootManagerVersionMinor}", Type);
|
||||
LogFile.Log($"Bootmanager protocol: {BootManagerProtocolVersionMajor}.{BootManagerProtocolVersionMinor}", Type);
|
||||
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
|
||||
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
|
||||
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
|
||||
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaFlashAppPhoneInfo
|
||||
{
|
||||
public PhoneInfoState State = PhoneInfoState.Empty;
|
||||
|
||||
public string Firmware; // Extended info
|
||||
public byte[] RKH; // Extended info
|
||||
|
||||
public FlashAppType App;
|
||||
|
||||
public byte FlashAppVersionMajor;
|
||||
public byte FlashAppVersionMinor;
|
||||
public byte FlashAppProtocolVersionMajor;
|
||||
public byte FlashAppProtocolVersionMinor;
|
||||
|
||||
public UInt32 TransferSize;
|
||||
public bool MmosOverUsbSupported;
|
||||
public UInt32 SdCardSizeInSectors;
|
||||
public UInt32 WriteBufferSize;
|
||||
public UInt32 EmmcSizeInSectors;
|
||||
public string PlatformID;
|
||||
public UInt16 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 bool IsBootloaderSecure;
|
||||
|
||||
internal void Log(LogType Type)
|
||||
{
|
||||
if (State == PhoneInfoState.Extended)
|
||||
{
|
||||
if (RKH != null)
|
||||
{
|
||||
LogFile.Log($"Root key hash: {Converter.ConvertHexToString(RKH, "")}", Type);
|
||||
}
|
||||
|
||||
if (Firmware?.Length > 0)
|
||||
{
|
||||
LogFile.Log($"Firmware version: {Firmware}", Type);
|
||||
}
|
||||
}
|
||||
|
||||
switch (App)
|
||||
{
|
||||
case FlashAppType.FlashApp:
|
||||
LogFile.Log($"Flash app: {FlashAppVersionMajor}.{FlashAppVersionMinor}", Type);
|
||||
LogFile.Log($"Flash protocol: {FlashAppProtocolVersionMajor}.{FlashAppProtocolVersionMinor}", Type);
|
||||
break;
|
||||
}
|
||||
|
||||
LogFile.Log($"SecureBoot: {((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled")} (Platform Secure Boot: {(PlatformSecureBootEnabled ? "Enabled" : "Disabled")}, UEFI Secure Boot: {(UefiSecureBootEnabled ? "Enabled" : "Disabled")})", Type);
|
||||
|
||||
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
|
||||
{
|
||||
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")}", LogType.ConsoleOnly);
|
||||
}
|
||||
|
||||
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
|
||||
{
|
||||
LogFile.Log($"Flash app security: {(!IsBootloaderSecure ? "Disabled" : "Enabled")} (FFU security: {(SecureFfuEnabled ? "Enabled" : "Disabled")}, RDC: {(RdcPresent ? "Present" : "Not found")}, Authenticated: {(Authenticated ? "True" : "False")})", LogType.FileOnly);
|
||||
}
|
||||
|
||||
LogFile.Log($"JTAG: {(JtagDisabled ? "Disabled" : "Enabled")}", Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaPhoneInfoAppPhoneInfo
|
||||
{
|
||||
public PhoneInfoState State = PhoneInfoState.Empty;
|
||||
|
||||
public string Type; // Extended info
|
||||
public string ProductCode; // Extended info
|
||||
public string Imei; // Extended info
|
||||
|
||||
public FlashAppType App;
|
||||
|
||||
public byte PhoneInfoAppVersionMajor;
|
||||
public byte PhoneInfoAppVersionMinor;
|
||||
public byte PhoneInfoAppProtocolVersionMajor;
|
||||
public byte PhoneInfoAppProtocolVersionMinor;
|
||||
|
||||
internal void Log(LogType Type)
|
||||
{
|
||||
if (State == PhoneInfoState.Extended)
|
||||
{
|
||||
if (this.Type != null)
|
||||
{
|
||||
LogFile.Log($"Phone type: {this.Type}", Type);
|
||||
}
|
||||
|
||||
if (ProductCode != null)
|
||||
{
|
||||
LogFile.Log($"Product code: {ProductCode}", Type);
|
||||
}
|
||||
|
||||
if (Type != LogType.ConsoleOnly && (Imei != null))
|
||||
{
|
||||
LogFile.Log($"IMEI: {Imei}", LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
switch (App)
|
||||
{
|
||||
case FlashAppType.PhoneInfoApp:
|
||||
LogFile.Log($"Phone info app: {PhoneInfoAppVersionMajor}.{PhoneInfoAppVersionMinor}", Type);
|
||||
LogFile.Log($"Phone info protocol: {PhoneInfoAppProtocolVersionMajor}.{PhoneInfoAppProtocolVersionMinor}", Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal enum PhoneInfoState
|
||||
{
|
||||
Empty,
|
||||
Basic,
|
||||
Extended
|
||||
};
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -100,7 +101,10 @@ namespace WPinternals
|
||||
LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
while (!HandshakeCompleted && (HelloSendCount < 6));
|
||||
|
||||
|
||||
@@ -69,10 +69,16 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
@@ -89,6 +95,11 @@ namespace WPinternals
|
||||
|
||||
foreach (string Line in Lines)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Line[0] != ':')
|
||||
{
|
||||
throw new BadImageFormatException();
|
||||
@@ -116,7 +127,10 @@ namespace WPinternals
|
||||
Result = new byte[BufferSize];
|
||||
System.Buffer.BlockCopy(Buffer, 0, Result, 0, BufferSize);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
@@ -105,8 +106,6 @@ namespace WPinternals
|
||||
HeaderOffset = ImageOffset + (uint)LongHeaderPattern.Length;
|
||||
}
|
||||
|
||||
uint Version = ByteOperations.ReadUInt32(Binary, ImageOffset + 0X04);
|
||||
|
||||
if (ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00) != 0)
|
||||
{
|
||||
ImageOffset = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00);
|
||||
@@ -125,71 +124,63 @@ namespace WPinternals
|
||||
CodeSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X0C);
|
||||
SignatureAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X10);
|
||||
SignatureSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X14);
|
||||
SignatureOffset = SignatureAddress - ImageAddress + ImageOffset;
|
||||
CertificatesAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X18);
|
||||
CertificatesSize = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C);
|
||||
CertificatesOffset = CertificatesAddress - ImageAddress + ImageOffset;
|
||||
|
||||
if (SignatureAddress == 0xFFFFFFFF)
|
||||
using MemoryStream fileStream = new(Binary);
|
||||
using BinaryReader reader = new(fileStream);
|
||||
|
||||
List<byte[]> Signatures = [];
|
||||
uint LastOffset = 0;
|
||||
|
||||
for (uint i = 0; i < fileStream.Length - 6; i++)
|
||||
{
|
||||
SignatureAddress = ImageAddress + CodeSize;
|
||||
}
|
||||
fileStream.Seek(i, SeekOrigin.Begin);
|
||||
|
||||
if (CertificatesAddress == 0xFFFFFFFF)
|
||||
{
|
||||
CertificatesAddress = SignatureAddress + SignatureSize;
|
||||
}
|
||||
ushort offset0 = reader.ReadUInt16();
|
||||
short offset1 = (short)((reader.ReadByte() << 8) | reader.ReadByte());
|
||||
ushort offset2 = reader.ReadUInt16();
|
||||
|
||||
// Headers newer than version 5 need more padding here
|
||||
if (Version > 5)
|
||||
{
|
||||
ImageOffset += 0x80;
|
||||
}
|
||||
|
||||
SignatureOffset = ImageOffset + CodeSize;
|
||||
CertificatesOffset = ImageOffset + CodeSize + SignatureSize;
|
||||
|
||||
// Keeping just in case
|
||||
// SignatureOffset = SignatureAddress - ImageAddress + ImageOffset;
|
||||
// CertificatesOffset = ImageSize - CertificatesSize + ImageOffset;
|
||||
|
||||
uint CurrentCertificateOffset = CertificatesOffset;
|
||||
uint CertificateSize = 0;
|
||||
while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize))
|
||||
{
|
||||
if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
|
||||
if (offset0 == 0x8230 && offset1 >= 0 && offset2 == 0x8230)
|
||||
{
|
||||
CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian!
|
||||
uint CertificateSize = (uint)offset1 + 4; // Header Size is 4
|
||||
|
||||
if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize))
|
||||
bool IsCertificatePartOfExistingChain = LastOffset == 0 || LastOffset == i;
|
||||
if (!IsCertificatePartOfExistingChain)
|
||||
{
|
||||
// This is the last certificate. So this is the root key.
|
||||
RootKeyHash = SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize));
|
||||
break;
|
||||
}
|
||||
|
||||
LastOffset = i + CertificateSize;
|
||||
|
||||
fileStream.Seek(i, SeekOrigin.Begin);
|
||||
Signatures.Add(reader.ReadBytes((int)CertificateSize));
|
||||
}
|
||||
}
|
||||
|
||||
if (Signatures.Count > 0)
|
||||
{
|
||||
byte[] RootCertificate = Signatures[^1];
|
||||
|
||||
for (int i = 0; i < Signatures.Count; i++)
|
||||
{
|
||||
if (i + 1 != Signatures.Count)
|
||||
{
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
|
||||
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(SHA256.HashData(Signatures[i]), ""));
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize)), ""));
|
||||
}
|
||||
#endif
|
||||
CurrentCertificateOffset += CertificateSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset))
|
||||
{
|
||||
CurrentCertificateOffset -= CertificateSize;
|
||||
|
||||
// This is the last certificate. So this is the root key.
|
||||
RootKeyHash = SHA256.HashData(Binary.AsSpan((int)CurrentCertificateOffset, (int)CertificateSize));
|
||||
RootKeyHash = SHA256.HashData(Signatures[i]);
|
||||
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ namespace WPinternals
|
||||
{
|
||||
this.USBDevice = new USBDevice(DevicePath);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +149,10 @@ namespace WPinternals
|
||||
{
|
||||
IsIncomplete = true;
|
||||
}
|
||||
catch { } // Will be rethrown as BadConnectionException
|
||||
catch (Exception ex) // Will be rethrown as BadConnectionException
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
while (IsIncomplete);
|
||||
|
||||
|
||||
@@ -45,7 +45,10 @@ namespace WPinternals
|
||||
Binary = FFUFile.GetPartition("SBL3");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
// If not succeeded, then try to parse it as raw image
|
||||
if (Binary == null)
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaBootManagerAppModel : NokiaFlashModel
|
||||
{
|
||||
internal readonly LumiaBootManagerPhoneInfo BootManagerInfo = new();
|
||||
|
||||
internal enum SecureBootKeyType : byte
|
||||
{
|
||||
Retail = 0,
|
||||
Engineering = 1
|
||||
}
|
||||
|
||||
//
|
||||
// Not valid commands
|
||||
//
|
||||
/* NOK */
|
||||
private const string Signature = "NOK";
|
||||
/* NOKX */
|
||||
private const string ExtendedMessageSignature = $"{Signature}X";
|
||||
/* NOKXB */
|
||||
private const string LumiaBootManagerExtendedMessageSignature = $"{ExtendedMessageSignature}B";
|
||||
|
||||
//
|
||||
// Normal commands
|
||||
//
|
||||
/* NOKA */
|
||||
private const string ContinueBootSignature = $"{Signature}A";
|
||||
/* NOKB */
|
||||
private const string RPMBSignature = $"{Signature}B";
|
||||
/* NOKC */
|
||||
private const string BatteryStatusSignature = $"{Signature}C";
|
||||
/* NOKD */
|
||||
private const string DisableTimeoutsSignature = $"{Signature}D";
|
||||
/* NOKI */
|
||||
private const string HelloSignature = $"{Signature}I";
|
||||
/* NOKM */
|
||||
private const string RebootToMassStorageSignature = $"{Signature}M";
|
||||
/* NOKP */
|
||||
private const string RebootToPhoneInfoAppSignature = $"{Signature}P";
|
||||
/* NOKR */
|
||||
private const string RebootSignature = $"{Signature}R";
|
||||
/* NOKS */
|
||||
private const string RebootToFlashAppSignature = $"{Signature}S";
|
||||
/* NOKT */
|
||||
private const string GetGPTSignature = $"{Signature}T";
|
||||
/* NOKV */
|
||||
private const string InfoQuerySignature = $"{Signature}V";
|
||||
/* NOKW */
|
||||
private const string WriteBootFlagFileSignature = $"{Signature}W";
|
||||
/* NOKY */
|
||||
private const string MMOSStartCommandSignature = $"{Signature}Y";
|
||||
/* NOKZ */
|
||||
private const string ShutdownSignature = $"{Signature}Z";
|
||||
|
||||
//
|
||||
// Lumia Boot Manager extended commands
|
||||
//
|
||||
/* NOKXBD */
|
||||
private const string PlatformSecureBootEnableSignature = $"{LumiaBootManagerExtendedMessageSignature}D";
|
||||
/* NOKXBH */
|
||||
private const string WriteRootCertificateHashSignature = $"{LumiaBootManagerExtendedMessageSignature}H";
|
||||
/* NOKXBK */
|
||||
private const string UEFIKeysProvisionSignature = $"{LumiaBootManagerExtendedMessageSignature}K";
|
||||
/* NOKXBR */
|
||||
private const string ReadManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}R";
|
||||
/* NOKXBU */
|
||||
private const string FlushVariablesSignature = $"{LumiaBootManagerExtendedMessageSignature}U";
|
||||
/* NOKXBW */
|
||||
private const string WriteManufacturingStateSignature = $"{LumiaBootManagerExtendedMessageSignature}W";
|
||||
|
||||
public LumiaBootManagerAppModel(string DevicePath) : base(DevicePath)
|
||||
{
|
||||
}
|
||||
|
||||
internal void ContinueBoot()
|
||||
{
|
||||
LogFile.Log("Continue boot...");
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, ContinueBootSignature);
|
||||
ExecuteRawVoidMethod(Request);
|
||||
}
|
||||
|
||||
internal LumiaBootManagerPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
bool PhoneInfoLogged = BootManagerInfo.State != PhoneInfoState.Empty;
|
||||
ReadPhoneInfoBootManager();
|
||||
|
||||
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
|
||||
|
||||
if (!PhoneInfoLogged)
|
||||
{
|
||||
Result.Log(LogType.FileOnly);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal LumiaBootManagerPhoneInfo ReadPhoneInfoBootManager()
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
LumiaBootManagerPhoneInfo Result = BootManagerInfo;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
byte SubblockCount = Response[10];
|
||||
int SubblockOffset = 11;
|
||||
|
||||
for (int i = 0; i < SubblockCount; i++)
|
||||
{
|
||||
byte SubblockID = Response[SubblockOffset + 0x00];
|
||||
|
||||
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
|
||||
|
||||
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 0x04:
|
||||
Result.FlashAppProtocolVersionMajor = Response[SubblockPayloadOffset + 0x00];
|
||||
Result.FlashAppProtocolVersionMinor = Response[SubblockPayloadOffset + 0x01];
|
||||
Result.FlashAppVersionMajor = Response[SubblockPayloadOffset + 0x02];
|
||||
Result.FlashAppVersionMinor = Response[SubblockPayloadOffset + 0x03];
|
||||
break;
|
||||
case 0x1F:
|
||||
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
|
||||
break;
|
||||
case 0x20:
|
||||
// CRC header info
|
||||
break;
|
||||
}
|
||||
SubblockOffset += SubblockLength + 3;
|
||||
}
|
||||
}
|
||||
|
||||
Result.State = PhoneInfoState.Basic;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal 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!!
|
||||
|
||||
byte[] Request = new byte[0x04];
|
||||
const string Header = GetGPTSignature;
|
||||
|
||||
System.Buffer.BlockCopy(System.Text.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!");
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
byte[] GPTBuffer = new byte[Buffer.Length - 0x208];
|
||||
System.Buffer.BlockCopy(Buffer, 0x208, GPTBuffer, 0, 0x4200);
|
||||
|
||||
return new GPT(GPTBuffer); // NOKT message header and MBR are ignored
|
||||
}
|
||||
|
||||
internal byte[] GetGptChunk(UInt32 Size) // TODO!
|
||||
{
|
||||
// This function is also used to generate a dummy chunk to flash for testing.
|
||||
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
|
||||
byte[] GPTChunk = new byte[Size];
|
||||
|
||||
byte[] Request = new byte[0x04];
|
||||
const string Header = "NOKT";
|
||||
|
||||
System.Buffer.BlockCopy(System.Text.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!");
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
System.Buffer.BlockCopy(Buffer, 8, GPTChunk, 0, 0x4400);
|
||||
|
||||
return GPTChunk;
|
||||
}
|
||||
|
||||
internal void ProvisionSecureBootKeys(SecureBootKeyType KeyType) // Only for Flashmode, not BootManager mode.
|
||||
{
|
||||
byte[] Request = new byte[8];
|
||||
ByteOperations.WriteAsciiString(Request, 0, UEFIKeysProvisionSignature);
|
||||
Request[6] = 0; // Options
|
||||
Request[7] = (byte)KeyType;
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
UInt32 Status = ByteOperations.ReadUInt32(Response, 6);
|
||||
if (Status != 0)
|
||||
{
|
||||
ThrowFlashError((int)Status);
|
||||
}
|
||||
}
|
||||
|
||||
private 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!");
|
||||
Ex.SubMessage = "Error 0x" + ErrorCode.ToString("X4") + ": " + SubMessage;
|
||||
|
||||
throw Ex;
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
byte[] Request = new byte[4];
|
||||
const string Header = ShutdownSignature;
|
||||
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||
ExecuteRawMethod(Request);
|
||||
}
|
||||
|
||||
internal void ResetPhone()
|
||||
{
|
||||
LogFile.Log("Rebooting phone", LogType.FileAndConsole);
|
||||
try
|
||||
{
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, RebootSignature);
|
||||
ExecuteRawVoidMethod(Request);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogFile.Log("Sending reset-request failed", LogType.FileOnly);
|
||||
LogFile.Log("Assuming automatic reset already in progress", LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ResetPhoneToFlashMode()
|
||||
{
|
||||
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
|
||||
|
||||
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||
|
||||
// This only works when the phone is in BootMgr mode. If it is already in FlashApp, it will not reboot. It only makes the phone unresponsive.
|
||||
LogFile.Log("Rebooting phone to Flash mode...");
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature);
|
||||
ExecuteRawVoidMethod(Request);
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
info.App = FlashAppType.FlashApp;
|
||||
|
||||
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SwitchToPhoneInfoAppContextLegacy()
|
||||
{
|
||||
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
|
||||
|
||||
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, RebootToPhoneInfoAppSignature);
|
||||
ExecuteRawVoidMethod(Request);
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
info.App = FlashAppType.PhoneInfoApp;
|
||||
|
||||
RaiseInterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RebootToFlashApp()
|
||||
{
|
||||
LumiaBootManagerPhoneInfo info = ReadPhoneInfoBootManager();
|
||||
|
||||
bool ModernFlashApp = info.BootManagerVersionMajor >= 2;
|
||||
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, RebootToFlashAppSignature); // This will let the phone charge
|
||||
ExecuteRawVoidMethod(Request); // On phone with bootloader Spec A this triggers a reboot, so DisableRebootTimeOut() cannot be called immediately.
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
info.App = FlashAppType.FlashApp;
|
||||
|
||||
RaiseInterfaceChanged(PhoneInterfaces.Lumia_Flash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+559
-781
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,239 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaPhoneInfoAppModel : NokiaFlashModel
|
||||
{
|
||||
internal readonly LumiaPhoneInfoAppPhoneInfo PhoneInfoAppInfo = new();
|
||||
|
||||
//
|
||||
// Not valid commands
|
||||
//
|
||||
/* NOK */
|
||||
private const string Signature = "NOK";
|
||||
/* NOKX */
|
||||
private const string ExtendedMessageSignature = $"{Signature}X";
|
||||
/* NOKXP */
|
||||
private const string PhoneInfoAppExtendedMessageSignature = $"{ExtendedMessageSignature}P";
|
||||
|
||||
//
|
||||
// Normal commands
|
||||
//
|
||||
/* NOKA */
|
||||
private const string ContinueBootSignature = $"{Signature}A";
|
||||
/* NOKD */
|
||||
private const string DisableTimeoutsSignature = $"{Signature}D";
|
||||
/* NOKH */
|
||||
private const string GetPhoneInfoSignature = $"{Signature}H";
|
||||
/* NOKI */
|
||||
private const string HelloSignature = $"{Signature}I";
|
||||
/* NOKV */
|
||||
private const string InfoQuerySignature = $"{Signature}V";
|
||||
|
||||
//
|
||||
// Phone Info App extended commands
|
||||
//
|
||||
/* NOKXPH */
|
||||
private const string GetVariableSignature = $"{PhoneInfoAppExtendedMessageSignature}H";
|
||||
|
||||
public LumiaPhoneInfoAppModel(string DevicePath) : base(DevicePath)
|
||||
{
|
||||
}
|
||||
|
||||
internal void ContinueBoot()
|
||||
{
|
||||
LogFile.Log("Continue boot...");
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, ContinueBootSignature);
|
||||
ExecuteRawVoidMethod(Request);
|
||||
}
|
||||
|
||||
internal string GetPhoneInfo()
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
if (PhoneInfoAppInfo.PhoneInfoAppVersionMajor >= 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, GetPhoneInfoSignature);
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
UInt16 Length = BigEndian.ToUInt16(Response, 0x04);
|
||||
|
||||
string PhoneInfoData = ByteOperations.ReadAsciiString(Response, 0x8, Length);
|
||||
|
||||
return PhoneInfoData;
|
||||
}
|
||||
|
||||
internal LumiaPhoneInfoAppPhoneInfo ReadPhoneInfo(bool ExtendedInfo = true)
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
bool PhoneInfoLogged = PhoneInfoAppInfo.State != PhoneInfoState.Empty;
|
||||
ReadPhoneInfoPhoneInfoApp();
|
||||
|
||||
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
|
||||
|
||||
if (ExtendedInfo && (Result.State == PhoneInfoState.Basic))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Result.PhoneInfoAppProtocolVersionMajor >= 2)
|
||||
{
|
||||
Result.Type = ReadPhoneInfoVariable("TYPE");
|
||||
Result.ProductCode = ReadPhoneInfoVariable("CTR");
|
||||
Result.Imei = ReadPhoneInfoVariable("IMEI");
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Version: 1.1.1.3
|
||||
* TYPE: RM-885
|
||||
* BTR: 059R0M0
|
||||
* LPSN: ...
|
||||
* HWID: 1000
|
||||
* CTR: 059S4B1
|
||||
* MC: 0205354
|
||||
* IMEI: ...
|
||||
*/
|
||||
string PhoneInfoData = GetPhoneInfo();
|
||||
if (!string.IsNullOrEmpty(PhoneInfoData))
|
||||
{
|
||||
string[] Variables = PhoneInfoData.Split("\n");
|
||||
Dictionary<string, string> FormattedVariables = [];
|
||||
foreach (string Variable in Variables)
|
||||
{
|
||||
if (!Variable.Contains(":"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FormattedVariables.Add(Variable.Split(":")[0].Trim(), Variable.Split(":")[1].Trim());
|
||||
}
|
||||
|
||||
Result.Type = FormattedVariables["TYPE"];
|
||||
Result.ProductCode = FormattedVariables["CTR"];
|
||||
Result.Imei = FormattedVariables["IMEI"];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
Result.State = PhoneInfoState.Extended;
|
||||
}
|
||||
|
||||
if (!PhoneInfoLogged)
|
||||
{
|
||||
Result.Log(LogType.FileOnly);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal LumiaPhoneInfoAppPhoneInfo ReadPhoneInfoPhoneInfoApp()
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
LumiaPhoneInfoAppPhoneInfo Result = PhoneInfoAppInfo;
|
||||
|
||||
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.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];
|
||||
|
||||
LogFile.Log($"{Result.App} SubblockID: 0x{SubblockID:X}");
|
||||
|
||||
UInt16 SubblockLength = BigEndian.ToUInt16(Response, SubblockOffset + 0x01);
|
||||
int SubblockPayloadOffset = SubblockOffset + 3;
|
||||
byte SubblockVersion;
|
||||
switch (SubblockID)
|
||||
{
|
||||
case 0x20:
|
||||
// CRC header info
|
||||
break;
|
||||
}
|
||||
SubblockOffset += SubblockLength + 3;
|
||||
}
|
||||
}
|
||||
|
||||
Result.State = PhoneInfoState.Basic;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal string ReadPhoneInfoVariable(string VariableName)
|
||||
{
|
||||
// This function assumes the phone is in Phone Info App context
|
||||
|
||||
byte[] Request = new byte[16];
|
||||
ByteOperations.WriteAsciiString(Request, 0, GetVariableSignature + VariableName + "\0"); // BTR or CTR, CTR is public ProductCode
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
UInt16 Length = BigEndian.ToUInt16(Response, 6);
|
||||
return ByteOperations.ReadAsciiString(Response, 8, Length).Trim([' ', '\0']);
|
||||
}
|
||||
|
||||
internal string ReadProductCode()
|
||||
{
|
||||
string Result = ReadPhoneInfoVariable("CTR");
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal delegate void InterfaceChangedHandler(PhoneInterfaces NewInterface, string DevicePath);
|
||||
|
||||
internal class NokiaFlashModel : NokiaPhoneModel
|
||||
{
|
||||
private string _devicePath;
|
||||
|
||||
private readonly CommonPhoneInfo CommonInfo = new();
|
||||
|
||||
internal event InterfaceChangedHandler InterfaceChanged = delegate { };
|
||||
|
||||
//
|
||||
// Not valid commands
|
||||
//
|
||||
/* NOK */
|
||||
private const string Signature = "NOK";
|
||||
/* NOKX */
|
||||
private const string ExtendedMessageSignature = $"{Signature}X";
|
||||
/* NOKXC */
|
||||
private const string CommonExtendedMessageSignature = $"{ExtendedMessageSignature}C";
|
||||
|
||||
//
|
||||
// Common extended commands
|
||||
//
|
||||
/* NOKXCB */
|
||||
private const string SwitchModeSignature = $"{CommonExtendedMessageSignature}B";
|
||||
/* NOKXCE */
|
||||
private const string EchoSignature = $"{CommonExtendedMessageSignature}E";
|
||||
|
||||
public NokiaFlashModel(string DevicePath) : base(DevicePath)
|
||||
{
|
||||
_devicePath = DevicePath;
|
||||
}
|
||||
|
||||
internal void SwitchToBootManagerContext(bool DisableTimeOut = true)
|
||||
{
|
||||
CommonPhoneInfo info = ReadPhoneInfoCommon();
|
||||
|
||||
bool ModernFlashApp = info.VersionMajor >= 2;
|
||||
|
||||
byte[] Request = new byte[7];
|
||||
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}B");
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("SwitchToBootManagerContext: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
InterfaceChanged(PhoneInterfaces.Lumia_Bootloader, _devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SwitchToPhoneInfoAppContext()
|
||||
{
|
||||
CommonPhoneInfo info = ReadPhoneInfoCommon();
|
||||
|
||||
bool ModernFlashApp = info.VersionMajor >= 2;
|
||||
|
||||
byte[] Request = new byte[7];
|
||||
ByteOperations.WriteAsciiString(Request, 0, SwitchModeSignature + "P");
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
CommonInfo.App = FlashAppType.PhoneInfoApp;
|
||||
|
||||
InterfaceChanged(PhoneInterfaces.Lumia_PhoneInfo, _devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SwitchToMmosContext()
|
||||
{
|
||||
byte[] Request = new byte[7];
|
||||
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}A");
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("SwitchToPhoneInfoAppContext: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
}
|
||||
|
||||
internal void SwitchToFlashAppContext()
|
||||
{
|
||||
CommonPhoneInfo info = ReadPhoneInfoCommon();
|
||||
|
||||
bool ModernFlashApp = info.VersionMajor >= 2;
|
||||
|
||||
byte[] Request = new byte[7];
|
||||
ByteOperations.WriteAsciiString(Request, 0, $"{SwitchModeSignature}F"); // This will stop charging the phone
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU")
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Response[6] << 8) + Response[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("SwitchToFlashAppContext: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
DisableRebootTimeOut();
|
||||
|
||||
InterfaceChanged(PhoneInterfaces.Lumia_Flash, _devicePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Normal commands
|
||||
//
|
||||
/* NOKD */
|
||||
private const string DisableTimeoutsSignature = $"{Signature}D";
|
||||
/* NOKI */
|
||||
private const string HelloSignature = $"{Signature}I";
|
||||
/* NOKV */
|
||||
private const string InfoQuerySignature = $"{Signature}V";
|
||||
|
||||
internal FlashAppType GetFlashAppType()
|
||||
{
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, InfoQuerySignature);
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if ((Response == null) || (ByteOperations.ReadAsciiString(Response, 0, 4) == "NOKU"))
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
return (FlashAppType)Response[5];
|
||||
}
|
||||
|
||||
internal CommonPhoneInfo ReadPhoneInfoCommon()
|
||||
{
|
||||
// NOKH = Get Phone Info (IMEI and info from Product.dat) - Not available on some phones, like Lumia 640.
|
||||
// NOKV = Info Query
|
||||
|
||||
CommonPhoneInfo Result = CommonInfo;
|
||||
|
||||
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];
|
||||
Result.ProtocolVersionMajor = Response[6];
|
||||
Result.ProtocolVersionMinor = Response[7];
|
||||
Result.VersionMajor = Response[8];
|
||||
Result.VersionMinor = Response[9];
|
||||
}
|
||||
|
||||
Result.State = PhoneInfoState.Basic;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
public void DisableRebootTimeOut()
|
||||
{
|
||||
byte[] Request = new byte[4];
|
||||
const string Header = DisableTimeoutsSignature;
|
||||
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||
ExecuteRawMethod(Request);
|
||||
}
|
||||
|
||||
internal void Hello()
|
||||
{
|
||||
byte[] Request = new byte[4];
|
||||
ByteOperations.WriteAsciiString(Request, 0, HelloSignature);
|
||||
byte[] Response = ExecuteRawMethod(Request);
|
||||
if (Response == null)
|
||||
{
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
internal void RaiseInterfaceChanged(PhoneInterfaces NewInterface)
|
||||
{
|
||||
InterfaceChanged(NewInterface, _devicePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class UefiSecurityStatusResponse
|
||||
{
|
||||
public byte IsTestDevice;
|
||||
public bool PlatformSecureBootStatus;
|
||||
public bool SecureFfuEfuseStatus;
|
||||
public bool DebugStatus;
|
||||
public bool RdcStatus;
|
||||
public bool AuthenticationStatus;
|
||||
public bool UefiSecureBootStatus;
|
||||
public bool CryptoHardwareKey;
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ namespace WPinternals
|
||||
{
|
||||
LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole);
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download);
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download)
|
||||
|
||||
@@ -360,7 +360,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Phone.CloseVolume();
|
||||
@@ -463,7 +466,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Phone.CloseVolume();
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
@@ -73,15 +72,15 @@ namespace WPinternals
|
||||
{
|
||||
App.Config.AddFfuToRepository(FFUPath);
|
||||
App.Config.WriteConfig();
|
||||
LastStatusText = "File \"" + FFUFile + "\" was added to the repository.";
|
||||
LastStatusText = $"File \"{FFUFile}\" was added to the repository.";
|
||||
}
|
||||
catch (WPinternalsException Ex)
|
||||
{
|
||||
LastStatusText = "Error: " + Ex.Message + ". File \"" + FFUFile + "\" was not added.";
|
||||
LastStatusText = $"Error: {Ex.Message}. File \"{FFUFile}\" was not added.";
|
||||
}
|
||||
catch
|
||||
{
|
||||
LastStatusText = "Error: File \"" + FFUFile + "\" was not added.";
|
||||
LastStatusText = $"Error: File \"{FFUFile}\" was not added.";
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -136,14 +135,30 @@ namespace WPinternals
|
||||
internal static long GetFileLengthFromURL(string URL)
|
||||
{
|
||||
long Length = 0;
|
||||
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
|
||||
req.Method = "HEAD";
|
||||
req.ServicePoint.ConnectionLimit = 10;
|
||||
using (WebResponse resp = req.GetResponse())
|
||||
|
||||
WebRequest webReq = WebRequest.Create(URL);
|
||||
|
||||
if (webReq is HttpWebRequest req)
|
||||
{
|
||||
long.TryParse(resp.Headers.Get("Content-Length"), out Length);
|
||||
req.Method = "HEAD";
|
||||
req.ServicePoint.ConnectionLimit = 10;
|
||||
using (WebResponse resp = req.GetResponse())
|
||||
{
|
||||
long.TryParse(resp.Headers.Get("Content-Length"), out Length);
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
return Length;
|
||||
else if (webReq is FileWebRequest filereq)
|
||||
{
|
||||
webReq.Method = "HEAD";
|
||||
using (WebResponse resp = webReq.GetResponse())
|
||||
{
|
||||
long.TryParse(resp.Headers.Get("Content-Length"), out Length);
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal static string GetFileNameFromURL(string URL)
|
||||
@@ -174,6 +189,8 @@ namespace WPinternals
|
||||
{
|
||||
string FFUURL = null;
|
||||
string[] EmergencyURLs = null;
|
||||
string SecureWIMURL = null;
|
||||
|
||||
try
|
||||
{
|
||||
string TempProductType = ProductType.ToUpper();
|
||||
@@ -183,7 +200,17 @@ namespace WPinternals
|
||||
}
|
||||
|
||||
ProductType = TempProductType;
|
||||
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
|
||||
|
||||
try
|
||||
{
|
||||
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, ProductCode, OperatorCode, out TempProductType);
|
||||
}
|
||||
catch (WPinternalsException ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
FFUURL = LumiaDownloadModel.SearchFFU(ProductType, null, OperatorCode, out TempProductType);
|
||||
}
|
||||
|
||||
if (TempProductType != null)
|
||||
{
|
||||
ProductType = TempProductType;
|
||||
@@ -193,8 +220,16 @@ namespace WPinternals
|
||||
{
|
||||
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||
}
|
||||
|
||||
if (ProductType != null && FirmwareVersion != null)
|
||||
{
|
||||
(SecureWIMURL, string _) = LumiaDownloadModel.SearchENOSW(ProductType, FirmwareVersion);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
catch { }
|
||||
|
||||
UIContext.Post(s =>
|
||||
{
|
||||
@@ -205,7 +240,12 @@ namespace WPinternals
|
||||
|
||||
if (EmergencyURLs != null)
|
||||
{
|
||||
SearchResultList.Add(new SearchResult(ProductType + " emergency-files", EmergencyURLs, ProductType, EmergencyDownloaded, ProductType));
|
||||
SearchResultList.Add(new SearchResult($"{ProductType} emergency-files", EmergencyURLs, ProductType, EmergencyDownloaded, ProductType));
|
||||
}
|
||||
|
||||
if (SecureWIMURL != null)
|
||||
{
|
||||
SearchResultList.Add(new SearchResult($"{ProductType} ENOSW-files", SecureWIMURL, ProductType, ENOSWDownloaded, FirmwareVersion));
|
||||
}
|
||||
}, null);
|
||||
|
||||
@@ -236,6 +276,7 @@ namespace WPinternals
|
||||
{
|
||||
string FFUURL = null;
|
||||
string[] EmergencyURLs = null;
|
||||
string SecureWIMURL = null;
|
||||
try
|
||||
{
|
||||
string TempProductType = ProductType.ToUpper();
|
||||
@@ -255,8 +296,16 @@ namespace WPinternals
|
||||
{
|
||||
EmergencyURLs = LumiaDownloadModel.SearchEmergencyFiles(ProductType);
|
||||
}
|
||||
|
||||
if (ProductType != null && FirmwareVersion != null)
|
||||
{
|
||||
(SecureWIMURL, string _) = LumiaDownloadModel.SearchENOSW(ProductType, FirmwareVersion);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
catch { }
|
||||
|
||||
UIContext.Post(s =>
|
||||
{
|
||||
@@ -269,6 +318,11 @@ namespace WPinternals
|
||||
{
|
||||
Download(EmergencyURLs, ProductType, EmergencyDownloaded, ProductType);
|
||||
}
|
||||
|
||||
if (SecureWIMURL != null)
|
||||
{
|
||||
Download(SecureWIMURL, ProductType, ENOSWDownloaded, FirmwareVersion);
|
||||
}
|
||||
}, null);
|
||||
}).Start();
|
||||
}
|
||||
@@ -322,6 +376,12 @@ namespace WPinternals
|
||||
App.Config.AddEmergencyToRepository(Type, ProgrammerPath, PayloadPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void ENOSWDownloaded(string[] Files, object State)
|
||||
{
|
||||
App.Config.AddSecWimToRepository(Files[0], (string)State);
|
||||
}
|
||||
|
||||
public ObservableCollection<DownloadEntry> DownloadList { get; } = new();
|
||||
public ObservableCollection<SearchResult> SearchResultList { get; } = new();
|
||||
|
||||
@@ -369,7 +429,10 @@ namespace WPinternals
|
||||
{
|
||||
Directory.CreateDirectory(_DownloadFolder);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
if (!Directory.Exists(_DownloadFolder))
|
||||
{
|
||||
_DownloadFolder = @"C:\ProgramData\WPinternals\Repository";
|
||||
@@ -433,6 +496,24 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
private string _FirmwareVersion = null;
|
||||
public string FirmwareVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return _FirmwareVersion;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_FirmwareVersion != value)
|
||||
{
|
||||
_FirmwareVersion = value;
|
||||
|
||||
OnPropertyChanged(nameof(FirmwareVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _OperatorCode = null;
|
||||
public string OperatorCode
|
||||
{
|
||||
@@ -451,8 +532,13 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
internal override void EvaluateViewState()
|
||||
internal override async void EvaluateViewState()
|
||||
{
|
||||
if (IsSwitchingInterface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsActive)
|
||||
{
|
||||
return;
|
||||
@@ -460,11 +546,120 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
NokiaFlashModel LumiaFlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
PhoneInfo Info = LumiaFlashModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo FlashAppInfo = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||
FirmwareVersion = FlashAppInfo.Firmware;
|
||||
|
||||
IsSwitchingInterface = true;
|
||||
|
||||
try
|
||||
{
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo Info = LumiaPhoneInfoModel.ReadPhoneInfo();
|
||||
ProductType = Info.Type;
|
||||
OperatorCode = "";
|
||||
ProductCode = Info.ProductCode;
|
||||
|
||||
ModernFlashApp = Info.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex);
|
||||
}
|
||||
|
||||
IsSwitchingInterface = false;
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo Info = LumiaPhoneInfoModel.ReadPhoneInfo();
|
||||
ProductType = Info.Type;
|
||||
OperatorCode = "";
|
||||
ProductCode = Info.ProductCode;
|
||||
|
||||
IsSwitchingInterface = true;
|
||||
|
||||
bool ModernFlashApp = Info.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaFlashAppPhoneInfo FlashAppInfo = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||
FirmwareVersion = FlashAppInfo.Firmware;
|
||||
|
||||
ModernFlashApp = FlashAppInfo.FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
IsSwitchingInterface = false;
|
||||
}
|
||||
else if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Normal)
|
||||
{
|
||||
@@ -478,6 +673,8 @@ namespace WPinternals
|
||||
|
||||
ProductType = TempProductType;
|
||||
ProductCode = LumiaNormalModel.ExecuteJsonMethodAsString("ReadProductCode", "ProductCode"); // 059Q9D7
|
||||
|
||||
FirmwareVersion = LumiaNormalModel.ExecuteJsonMethodAsString("ReadSwVersion", "SwVersion");
|
||||
}
|
||||
}
|
||||
public DelegateCommand AddFFUCommand { get; } = null;
|
||||
@@ -490,7 +687,7 @@ namespace WPinternals
|
||||
Failed
|
||||
};
|
||||
|
||||
internal class DownloadEntry : INotifyPropertyChanged
|
||||
internal class DownloadEntry : INotifyPropertyChanged, IProgress<GeneralDownloadProgress>
|
||||
{
|
||||
private readonly SynchronizationContext UIContext;
|
||||
public event PropertyChangedEventHandler PropertyChanged = delegate { };
|
||||
@@ -499,7 +696,8 @@ namespace WPinternals
|
||||
internal string URL;
|
||||
internal string[] URLCollection;
|
||||
internal string Folder;
|
||||
internal HttpClient Client;
|
||||
//internal HttpClient Client;
|
||||
internal HttpDownloader Client;
|
||||
internal long SpeedIndex = -1;
|
||||
internal long[] Speeds = new long[10];
|
||||
internal long LastBytesReceived;
|
||||
@@ -521,11 +719,42 @@ namespace WPinternals
|
||||
{
|
||||
Size = DownloadsViewModel.GetFileLengthFromURL(URL);
|
||||
|
||||
Client = new HttpClient();
|
||||
_ = Client.DownloadFileAsync(Uri, Path.Combine(Folder, DownloadsViewModel.GetFileNameFromURL(Uri.LocalPath)), Client_DownloadProgressChanged, Client_DownloadFileCompleted);
|
||||
//Client = new HttpClient();
|
||||
|
||||
//_ = Client.DownloadFileAsync(Uri, Path.Combine(Folder, DownloadsViewModel.GetFileNameFromURL(Uri.LocalPath)), Client_DownloadProgressChanged, Client_DownloadFileCompleted);
|
||||
|
||||
Client = new(Folder, 4, false);
|
||||
|
||||
_ = Client.DownloadAsync([new FileDownloadInformation(URL, DownloadsViewModel.GetFileNameFromURL(Uri.LocalPath), Size, null, null)], this);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void Report(GeneralDownloadProgress e)
|
||||
{
|
||||
foreach (FileDownloadStatus status in e.DownloadedStatus)
|
||||
{
|
||||
if (status == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status.FileStatus == FileStatus.Failed || status.FileStatus == FileStatus.Failed)
|
||||
{
|
||||
Client_DownloadFileCompleted(true);
|
||||
}
|
||||
|
||||
if (status.FileStatus == FileStatus.Completed)
|
||||
{
|
||||
Client_DownloadFileCompleted(false);
|
||||
}
|
||||
|
||||
if (status.FileStatus == FileStatus.Downloading)
|
||||
{
|
||||
Client_DownloadProgressChanged(new HttpClientDownloadProgress(status.DownloadedBytes, status.File.FileSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Client_DownloadFileCompleted(bool Error)
|
||||
{
|
||||
void Finish()
|
||||
@@ -536,6 +765,9 @@ namespace WPinternals
|
||||
{
|
||||
if (URLCollection?.Any(c => App.DownloadManager.DownloadList.Any(d => d.URL == c)) != true) // if there are no files left to download from this collection, then call the callback-function.
|
||||
{
|
||||
Client.Dispose();
|
||||
Client = null;
|
||||
|
||||
string[] Files;
|
||||
if (URLCollection == null)
|
||||
{
|
||||
@@ -556,7 +788,14 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
UIContext?.Post(d => Finish(), null);
|
||||
if (UIContext == null)
|
||||
{
|
||||
Finish();
|
||||
}
|
||||
else
|
||||
{
|
||||
UIContext?.Post(d => Finish(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Client_DownloadProgressChanged(HttpClientDownloadProgress e)
|
||||
@@ -715,6 +954,18 @@ namespace WPinternals
|
||||
GetSize();
|
||||
}
|
||||
|
||||
internal SearchResult(string Name, string URL, string Category, Action<string[], object> Callback, object State)
|
||||
{
|
||||
UIContext = SynchronizationContext.Current;
|
||||
URLs = new string[1];
|
||||
URLs[0] = URL;
|
||||
this.Name = Name;
|
||||
this.Callback = Callback;
|
||||
this.State = State;
|
||||
this.Category = Category;
|
||||
GetSize();
|
||||
}
|
||||
|
||||
private void GetSize()
|
||||
{
|
||||
new Thread(() =>
|
||||
|
||||
@@ -0,0 +1,642 @@
|
||||
/*
|
||||
* Copyright (c) Gustave Monce and Contributors
|
||||
* Copyright (c) ADeltaX and Contributors
|
||||
*
|
||||
* 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
public class GeneralDownloadProgress
|
||||
{
|
||||
public long EstimatedTotalBytes;
|
||||
public long DownloadedTotalBytes;
|
||||
public int NumFilesDownloadedSuccessfully;
|
||||
public int NumFilesDownloadedUnsuccessfully;
|
||||
public int NumFiles;
|
||||
|
||||
public FileDownloadStatus[] DownloadedStatus;
|
||||
}
|
||||
|
||||
public enum FileStatus
|
||||
{
|
||||
Downloading,
|
||||
Verifying,
|
||||
Completed,
|
||||
Expired,
|
||||
Failed
|
||||
}
|
||||
|
||||
public class FileDownloadStatus
|
||||
{
|
||||
public FileStatus FileStatus;
|
||||
public long DownloadedBytes;
|
||||
public long HashedBytes;
|
||||
public FileDownloadInformation File;
|
||||
public FileDownloadStatus(FileDownloadInformation file)
|
||||
{
|
||||
File = file;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileDownloadInformation
|
||||
{
|
||||
public string DownloadUrl
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string FileName
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public long FileSize
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string Hash
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string HashAlgorithm
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public FileDownloadInformation(string DownloadUrl, string FileName, long FileSize, string Hash, string HashAlgorithm)
|
||||
{
|
||||
this.DownloadUrl = DownloadUrl;
|
||||
this.FileName = FileName;
|
||||
this.FileSize = FileSize;
|
||||
this.Hash = Hash;
|
||||
this.HashAlgorithm = HashAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
public class HttpDownloader : IDisposable
|
||||
{
|
||||
private const long CHUNK_SIZE = 8_388_608 + 65_536; //Slice 8MB+64KB
|
||||
private const string TEMP_DOWNLOAD_EXTENSION = ".dlTmp";
|
||||
|
||||
private readonly HttpClient _hc;
|
||||
public string DownloadFolderPath
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int DownloadThreads
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int DownloadRetries
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public bool VerifyFiles
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public HttpDownloader(string downloadFolderPath, int downloadThreads = 4, bool verifyFiles = true, IWebProxy proxy = null, bool useSystemProxy = true)
|
||||
{
|
||||
HttpClientHandler filter = new()
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.All,
|
||||
MaxConnectionsPerServer = 512,
|
||||
};
|
||||
|
||||
if (proxy != null || !useSystemProxy)
|
||||
{
|
||||
filter.Proxy = proxy;
|
||||
}
|
||||
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
filter.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; //For Linux, MS cert isn't trusted lol ¯\_(ツ)_/¯
|
||||
}
|
||||
|
||||
_hc = new HttpClient(filter)
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10)
|
||||
};
|
||||
_hc.DefaultRequestHeaders.Connection.Add("keep-alive");
|
||||
|
||||
DownloadThreads = downloadThreads;
|
||||
DownloadFolderPath = downloadFolderPath;
|
||||
VerifyFiles = verifyFiles;
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadAsync(List<FileDownloadInformation> Files, IProgress<GeneralDownloadProgress> generalDownloadProgress, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await ParallelQueue(Files, DownloadFile, generalDownloadProgress, DownloadThreads, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadAsync(FileDownloadInformation File, IProgress<FileDownloadStatus> downloadProgress = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await DownloadFile(File, downloadProgress, cancellationToken);
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> ParallelQueue(List<FileDownloadInformation> items, Func<FileDownloadInformation, IProgress<FileDownloadStatus>, CancellationToken, ValueTask<bool>> func,
|
||||
IProgress<GeneralDownloadProgress> generalProgress, int threads, CancellationToken cancellationToken)
|
||||
{
|
||||
Queue<FileDownloadInformation> pending = new(items);
|
||||
Task<bool>[] workingSlots = new Task<bool>[threads];
|
||||
int workingThreadsCount = 0;
|
||||
|
||||
GeneralDownloadProgress generalDownloadProgress = new()
|
||||
{
|
||||
DownloadedStatus = new FileDownloadStatus[threads],
|
||||
NumFiles = items.Count
|
||||
};
|
||||
|
||||
bool result = true;
|
||||
while (pending.Count + workingThreadsCount != 0)
|
||||
{
|
||||
if (workingThreadsCount < threads && pending.Count != 0)
|
||||
{
|
||||
FileDownloadInformation item = pending.Dequeue();
|
||||
FileDownloadStatus fileStatus = new(item);
|
||||
Progress<FileDownloadStatus> progress = new();
|
||||
|
||||
workingThreadsCount++;
|
||||
GetFreeSlotIndex(workingSlots, out int freeSlotIndex);
|
||||
generalDownloadProgress.DownloadedStatus[freeSlotIndex] = fileStatus;
|
||||
|
||||
progress.ProgressChanged += (s, e) =>
|
||||
{
|
||||
generalDownloadProgress.DownloadedTotalBytes += e.DownloadedBytes - generalDownloadProgress.DownloadedStatus[freeSlotIndex].DownloadedBytes;
|
||||
generalDownloadProgress.DownloadedStatus[freeSlotIndex].DownloadedBytes = e.DownloadedBytes;
|
||||
generalDownloadProgress.DownloadedStatus[freeSlotIndex].HashedBytes = e.HashedBytes;
|
||||
generalDownloadProgress.DownloadedStatus[freeSlotIndex].FileStatus = e.FileStatus;
|
||||
generalProgress?.Report(generalDownloadProgress);
|
||||
};
|
||||
|
||||
workingSlots[freeSlotIndex] = Task.Run(async () => await func(item, progress, cancellationToken));
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = await Task.WhenAny(workingSlots.Where(t => t != null));
|
||||
|
||||
for (int i = 0; i < workingSlots.Length; i++)
|
||||
{
|
||||
if (workingSlots[i]?.IsCompleted == true)
|
||||
{
|
||||
if (workingSlots[i].Result)
|
||||
{
|
||||
generalDownloadProgress.NumFilesDownloadedSuccessfully++;
|
||||
}
|
||||
else
|
||||
{
|
||||
generalDownloadProgress.NumFilesDownloadedUnsuccessfully++;
|
||||
result = false;
|
||||
}
|
||||
|
||||
workingThreadsCount--;
|
||||
workingSlots[i].Dispose();
|
||||
workingSlots[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async ValueTask<bool> DownloadFile(FileDownloadInformation downloadFile, IProgress<FileDownloadStatus> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return await HttpDownload(DownloadFolderPath, downloadFile, _hc, VerifyFiles, progress, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> HttpDownload(string basePath, FileDownloadInformation downloadFile, HttpClient httpClient, bool verifyFiles,
|
||||
IProgress<FileDownloadStatus> downloadProgress = null, int bufferSize = 65_536, CancellationToken cancellationToken = default)
|
||||
{
|
||||
long currRange = 0;
|
||||
long chunk = CHUNK_SIZE;
|
||||
long totalBytesRead = 0;
|
||||
long hashedBytes = 0;
|
||||
int blockBufferSize = bufferSize;
|
||||
|
||||
try
|
||||
{
|
||||
//This path will be used for downloaded and validated files, moved/renamed
|
||||
string filePath = Path.Combine(basePath, downloadFile.FileName);
|
||||
|
||||
//This path will be used for downloading files
|
||||
string tempFilePath = filePath + TEMP_DOWNLOAD_EXTENSION;
|
||||
|
||||
//If we have an already completed file, prefer this under certain conditions.
|
||||
if (File.Exists(tempFilePath) && File.Exists(filePath))
|
||||
{
|
||||
FileInfo tmpFileInfo = new(tempFilePath);
|
||||
FileInfo fileInfo = new(filePath);
|
||||
if (tmpFileInfo.Length == downloadFile.FileSize)
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
else if (fileInfo.Length == downloadFile.FileSize)
|
||||
{
|
||||
File.Delete(tempFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(tempFilePath))
|
||||
{
|
||||
FileInfo tmpFileInfo = new(tempFilePath);
|
||||
|
||||
if (tmpFileInfo.Length == downloadFile.FileSize)
|
||||
{
|
||||
//Decrypted file should match estimated bytes.
|
||||
//Imagine if it crashed during hashing, the file may be valid.
|
||||
//So... lets rename this file so it can be verified.
|
||||
File.Move(tempFilePath, filePath);
|
||||
totalBytesRead = tmpFileInfo.Length;
|
||||
}
|
||||
else if (tmpFileInfo.Length < downloadFile.FileSize)
|
||||
{
|
||||
//Download the remaining part
|
||||
currRange = tmpFileInfo.Length;
|
||||
totalBytesRead = tmpFileInfo.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If it's bigger then we have a problem.
|
||||
//Just... delete the file.
|
||||
File.Delete(tempFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
//If the filename was renamed then the download must have been completed successfully,
|
||||
//we just hash to be sure that the file hasn't been tampered
|
||||
if (verifyFiles)
|
||||
{
|
||||
FileStream fileStreamToHash = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
totalBytesRead = fileStreamToHash.Length;
|
||||
bool hashResult = await HashWithProgress(fileStreamToHash);
|
||||
fileStreamToHash.Dispose();
|
||||
|
||||
if (hashResult)
|
||||
{
|
||||
//Nice, the file is ok, return success.
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//The file is not ok.
|
||||
//It's better to delete this file and redownload from scratch
|
||||
//instead of partially downloading the missing parts and found later that the entire file was corrupted.
|
||||
File.Delete(filePath);
|
||||
|
||||
//This range may have been changed before (e.g. when assuming for temp. file), so let's set it to 0
|
||||
currRange = 0;
|
||||
totalBytesRead = 0;
|
||||
hashedBytes = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//At your own risk lol
|
||||
FileInfo fileInfo = new(filePath);
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = fileInfo.Length,
|
||||
FileStatus = FileStatus.Completed
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Before we need to create a directory.
|
||||
_ = Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
|
||||
//Open the file as stream.
|
||||
using FileStream streamToWriteTo = File.Open(tempFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
|
||||
|
||||
//Set the seek position to current range position (via totalBytesRead or currRange). This is needed.
|
||||
_ = streamToWriteTo.Seek(totalBytesRead, SeekOrigin.Begin);
|
||||
|
||||
using HttpRequestMessage httpRequestMessageHead = new(HttpMethod.Head, new Uri(downloadFile.DownloadUrl));
|
||||
using HttpResponseMessage response = await httpClient.SendAsync(httpRequestMessageHead, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||
|
||||
//Technically the server reports both content-length and Accept-Ranges.
|
||||
long? contentLength = response.Content.Headers.ContentLength;
|
||||
bool hasAcceptRanges = response.Headers.AcceptRanges.Contains("bytes");
|
||||
|
||||
//This is just a fallback in case the file delivery server goes nuts.
|
||||
if (!hasAcceptRanges)
|
||||
{
|
||||
//We don't have a way to download from a specific range, hence we set the position to 0
|
||||
//and download everything from scratch... Sadly.
|
||||
//TODO
|
||||
_ = streamToWriteTo.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = 0,
|
||||
FileStatus = FileStatus.Downloading
|
||||
});
|
||||
|
||||
//TODO: add download reporting for this
|
||||
//TODO: may throw an exception if the server suddently closes the connection (e.g. file expired.)
|
||||
|
||||
using HttpResponseMessage fullFileResp = await httpClient.GetAsync(downloadFile.DownloadUrl, cancellationToken);
|
||||
using Stream streamToReadFrom = await fullFileResp.Content.ReadAsStreamAsync();
|
||||
|
||||
await streamToReadFrom.CopyToAsync(streamToWriteTo);
|
||||
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = contentLength.Value,
|
||||
FileStatus = FileStatus.Downloading
|
||||
});
|
||||
|
||||
//just an assumption
|
||||
|
||||
if (verifyFiles)
|
||||
{
|
||||
_ = streamToWriteTo.Seek(0, SeekOrigin.Begin);
|
||||
bool hashResult = await HashWithProgress(streamToWriteTo);
|
||||
|
||||
if (hashResult)
|
||||
{
|
||||
streamToWriteTo.Close();
|
||||
File.Move(tempFilePath, filePath);
|
||||
}
|
||||
|
||||
return hashResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
streamToWriteTo.Close();
|
||||
File.Move(tempFilePath, filePath);
|
||||
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
FileStatus = FileStatus.Completed
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
while (currRange < contentLength.Value)
|
||||
{
|
||||
//Calculate range values
|
||||
if (currRange + chunk >= contentLength.Value)
|
||||
{
|
||||
chunk = contentLength.Value - currRange - 1;
|
||||
}
|
||||
|
||||
//Create request for range and send it, return asap (we just need the header to see if the status code is ok)
|
||||
using HttpRequestMessage requestMessageRange = CreateRequestHeaderForRange(HttpMethod.Get, downloadFile.DownloadUrl, currRange, currRange + chunk);
|
||||
using HttpResponseMessage filePartResp = await httpClient.SendAsync(requestMessageRange, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||
|
||||
//increment to the next range
|
||||
currRange += chunk + 1;
|
||||
|
||||
//If the server has replied with 200 ok/206 partial content
|
||||
if (filePartResp.IsSuccessStatusCode)
|
||||
{
|
||||
//get the underlying stream
|
||||
using Stream streamToReadFrom = await filePartResp.Content.ReadAsStreamAsync();
|
||||
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[blockBufferSize];
|
||||
|
||||
//read the content
|
||||
//TODO: it may throw an exception (stream closed because file expired?)
|
||||
//In that case we would wrap into another try catch and try to read the reason behind this
|
||||
while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
|
||||
{
|
||||
totalBytesRead += bytesRead;
|
||||
|
||||
//simply write to the file
|
||||
await streamToWriteTo.WriteAsync(buffer, 0, bytesRead, cancellationToken);
|
||||
|
||||
//report progress
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
FileStatus = FileStatus.Downloading
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filePartResp.StatusCode is HttpStatusCode.Forbidden or
|
||||
HttpStatusCode.NotFound or
|
||||
HttpStatusCode.Unauthorized)
|
||||
{
|
||||
//The url is expired.
|
||||
//Report that is expired and return false
|
||||
//We need to keep the file, because it's just incomplete, not corrupted.
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
FileStatus = FileStatus.Expired
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(filePartResp.ReasonPhrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//last left block if any
|
||||
|
||||
if (verifyFiles)
|
||||
{
|
||||
_ = streamToWriteTo.Seek(0, SeekOrigin.Begin);
|
||||
bool hashResult = await HashWithProgress(streamToWriteTo);
|
||||
|
||||
if (hashResult)
|
||||
{
|
||||
streamToWriteTo.Close();
|
||||
File.Move(tempFilePath, filePath);
|
||||
}
|
||||
|
||||
return hashResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
streamToWriteTo.Close();
|
||||
File.Move(tempFilePath, filePath);
|
||||
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
FileStatus = FileStatus.Completed
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch //(Exception ex)
|
||||
{
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
FileStatus = FileStatus.Failed
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//C# 7 - Local Functions
|
||||
async ValueTask<bool> HashWithProgress(Stream strm)
|
||||
{
|
||||
Progress<long> progressHashedBytes = new();
|
||||
progressHashedBytes.ProgressChanged += (s, e) =>
|
||||
{
|
||||
hashedBytes = e;
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
HashedBytes = hashedBytes,
|
||||
FileStatus = FileStatus.Verifying
|
||||
});
|
||||
};
|
||||
|
||||
bool hashMatches = true;
|
||||
switch (downloadFile.HashAlgorithm?.ToLower())
|
||||
{
|
||||
case "sha1":
|
||||
hashMatches = await IsDownloadedFileValidSHA1(strm, downloadFile.Hash,
|
||||
progressHashedBytes, cancellationToken);
|
||||
break;
|
||||
case "sha256":
|
||||
hashMatches = await IsDownloadedFileValidSHA256(strm, downloadFile.Hash,
|
||||
progressHashedBytes, cancellationToken);
|
||||
break;
|
||||
}
|
||||
|
||||
if (hashMatches)
|
||||
{
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
HashedBytes = hashedBytes,
|
||||
FileStatus = FileStatus.Completed
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
downloadProgress?.Report(new FileDownloadStatus(downloadFile)
|
||||
{
|
||||
DownloadedBytes = totalBytesRead,
|
||||
HashedBytes = hashedBytes,
|
||||
FileStatus = FileStatus.Failed
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private static async ValueTask<bool> IsDownloadedFileValidSHA256(Stream fileStream, string base64Hash, IProgress<long> progress = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using SHA256 hashAlgo = SHA256.Create();
|
||||
byte[] hashByte = await ComputeHashAsyncT(hashAlgo, fileStream, progress, cancellationToken: cancellationToken);
|
||||
return ByteArraySpanCompare(Convert.FromBase64String(base64Hash), hashByte);
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> IsDownloadedFileValidSHA1(Stream fileStream, string base64Hash, IProgress<long> progress = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using SHA1 hashAlgo = SHA1.Create();
|
||||
byte[] hashByte = await ComputeHashAsyncT(hashAlgo, fileStream, progress, cancellationToken: cancellationToken);
|
||||
return ByteArraySpanCompare(Convert.FromBase64String(base64Hash), hashByte);
|
||||
}
|
||||
|
||||
public static async ValueTask<byte[]> ComputeHashAsyncT(HashAlgorithm hashAlgorithm, Stream fileStream, IProgress<long> progress = null,
|
||||
int bufferSize = 1_048_576, CancellationToken cancellationToken = default)
|
||||
{
|
||||
int readBytes;
|
||||
long totalBytesRead = 0;
|
||||
long bufSizeEffective = Math.Min(bufferSize, fileStream.Length);
|
||||
byte[] buffer = new byte[bufSizeEffective];
|
||||
using MemoryStream ms = new(buffer);
|
||||
using CryptoStream cs = new(ms, hashAlgorithm, CryptoStreamMode.Write);
|
||||
while ((readBytes = await fileStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
|
||||
{
|
||||
await cs.WriteAsync(buffer, 0, readBytes, cancellationToken);
|
||||
ms.Position = 0;
|
||||
totalBytesRead += readBytes;
|
||||
progress?.Report(totalBytesRead);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
cs.FlushFinalBlock();
|
||||
return hashAlgorithm.Hash;
|
||||
}
|
||||
|
||||
private static bool ByteArraySpanCompare(ReadOnlySpan<byte> a1, ReadOnlySpan<byte> a2)
|
||||
{
|
||||
return a1.SequenceEqual(a2);
|
||||
}
|
||||
|
||||
private static void GetFreeSlotIndex<T>(T[] array, out int firstFreeTaskIndex)
|
||||
{
|
||||
firstFreeTaskIndex = -1;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i] == null)
|
||||
{
|
||||
firstFreeTaskIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpRequestMessage CreateRequestHeaderForRange(HttpMethod method, string url, long from, long to)
|
||||
{
|
||||
HttpRequestMessage request = new(method, new Uri(url));
|
||||
request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(from, to);
|
||||
return request;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//Release all resources that have been instanced and used
|
||||
_hc.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,10 @@ namespace WPinternals
|
||||
{
|
||||
EvaluateViewState();
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace WPinternals
|
||||
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash,
|
||||
(msg, sub) =>
|
||||
ActivateSubContext(new BusyViewModel(msg, sub)));
|
||||
if (((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: false).FlashAppProtocolVersionMajor < 2)
|
||||
if (((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: false).FlashAppProtocolVersionMajor < 2)
|
||||
{
|
||||
FlashPartitionsTask(EFIESPPath, MainOSPath, DataPath);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace WPinternals
|
||||
|
||||
ActivateSubContext(new BusyViewModel("Initializing flash..."));
|
||||
|
||||
NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppModel Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
GPT GPT = Phone.ReadGPT();
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace WPinternals
|
||||
await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash,
|
||||
(msg, sub) =>
|
||||
ActivateSubContext(new BusyViewModel(msg, sub)));
|
||||
if (((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: false).FlashAppProtocolVersionMajor < 2)
|
||||
if (((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: false).FlashAppProtocolVersionMajor < 2)
|
||||
{
|
||||
FlashArchiveTask(ArchivePath);
|
||||
}
|
||||
@@ -289,7 +289,7 @@ namespace WPinternals
|
||||
{
|
||||
ActivateSubContext(new BusyViewModel("Initializing flash..."));
|
||||
|
||||
NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppModel Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
ulong TotalSizeSectors = 0;
|
||||
int PartitionCount = 0;
|
||||
@@ -343,7 +343,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
TotalSizeSectors += StreamLengthInSectors;
|
||||
PartitionCount++;
|
||||
@@ -438,7 +441,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
if (StreamLengthInSectors <= Partition.SizeInSectors)
|
||||
{
|
||||
@@ -495,12 +501,12 @@ namespace WPinternals
|
||||
|
||||
internal void FlashFFUTask(string FFUPath)
|
||||
{
|
||||
new Thread(() =>
|
||||
new Thread(async () =>
|
||||
{
|
||||
bool Result = true;
|
||||
|
||||
NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
PhoneInfo Info = Phone.ReadPhoneInfo(false);
|
||||
LumiaFlashAppModel Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo Info = Phone.ReadPhoneInfo(false);
|
||||
|
||||
#region Remove bootloader changes
|
||||
|
||||
@@ -513,8 +519,35 @@ namespace WPinternals
|
||||
|
||||
if (Info.FlashAppProtocolVersionMajor >= 2)
|
||||
{
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Phone, 0x20000); // TODO: Get proper profile FFU and get ChunkSizeInBytes
|
||||
Phone.SwitchToBootManagerContext();
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
byte[] GPTChunk = ((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).GetGptChunk(0x20000); // TODO: Get proper profile FFU and get ChunkSizeInBytes
|
||||
GPT GPT = new(GPTChunk);
|
||||
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
FlashPart Part;
|
||||
List<FlashPart> FlashParts = new();
|
||||
|
||||
@@ -592,14 +625,14 @@ namespace WPinternals
|
||||
|
||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
ActivateSubContext(new BusyViewModel("Initializing flash..."));
|
||||
|
||||
@@ -658,12 +691,13 @@ namespace WPinternals
|
||||
|
||||
internal void FlashMMOSTask(string MMOSPath)
|
||||
{
|
||||
NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
Phone.SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
|
||||
LumiaFlashAppModel Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
bool Result = true;
|
||||
|
||||
@@ -66,15 +66,19 @@ namespace WPinternals
|
||||
switch (CurrentInterface)
|
||||
{
|
||||
case null:
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ActivateSubContext(null);
|
||||
//ActivateSubContext(new NokiaBootloaderViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ActivateSubContext(new NokiaBootloaderViewModel((LumiaBootManagerAppModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
ActivateSubContext(new NokiaPhoneInfoViewModel((LumiaPhoneInfoAppModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Normal:
|
||||
ActivateSubContext(new NokiaNormalViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
ActivateSubContext(new NokiaFlashViewModel((NokiaFlashModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
|
||||
ActivateSubContext(new NokiaFlashViewModel((LumiaFlashAppModel)CurrentModel, ModeSwitchRequestCallback, SwitchToGettingStarted));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
ActivateSubContext(new NokiaLabelViewModel((NokiaPhoneModel)CurrentModel, ModeSwitchRequestCallback));
|
||||
|
||||
@@ -87,14 +87,16 @@ namespace WPinternals
|
||||
ActivateSubContext(null);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ActivateSubContext(null);
|
||||
//ActivateSubContext(new NokiaModeBootloaderViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested));
|
||||
ActivateSubContext(new NokiaModeBootloaderViewModel((LumiaBootManagerAppModel)CurrentModel, OnModeSwitchRequested));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
ActivateSubContext(new NokiaModePhoneInfoViewModel((LumiaPhoneInfoAppModel)CurrentModel, OnModeSwitchRequested));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Normal:
|
||||
ActivateSubContext(new NokiaModeNormalViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
ActivateSubContext(new NokiaModeFlashViewModel((NokiaFlashModel)CurrentModel, OnModeSwitchRequested));
|
||||
ActivateSubContext(new NokiaModeFlashViewModel((LumiaFlashAppModel)CurrentModel, OnModeSwitchRequested));
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
ActivateSubContext(new NokiaModeLabelViewModel((NokiaPhoneModel)CurrentModel, OnModeSwitchRequested));
|
||||
|
||||
@@ -95,6 +95,11 @@ namespace WPinternals
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSwitchingInterface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (EvaluateViewStateLockObject)
|
||||
{
|
||||
switch (PhoneNotifier.CurrentInterface)
|
||||
@@ -133,11 +138,11 @@ namespace WPinternals
|
||||
{
|
||||
// Some phones, like Lumia 928 verizon, do not support the Terminal interface!
|
||||
// To read the RootKeyHash we use ReadParam("RRKH"), instead of GetTerminalResponse().RootKeyHash.
|
||||
RootKeyHash = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadParam("RRKH");
|
||||
RootKeyHash = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadParam("RRKH");
|
||||
|
||||
TestPos = 1;
|
||||
|
||||
UefiSecurityStatusResponse SecurityStatus = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadSecurityStatus();
|
||||
UefiSecurityStatusResponse SecurityStatus = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadSecurityStatus();
|
||||
if (SecurityStatus != null)
|
||||
{
|
||||
IsBootLoaderUnlocked = SecurityStatus.AuthenticationStatus || SecurityStatus.RdcStatus || !SecurityStatus.SecureFfuEfuseStatus;
|
||||
@@ -145,20 +150,21 @@ namespace WPinternals
|
||||
|
||||
TestPos = 2;
|
||||
|
||||
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo FlashInfo = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo();
|
||||
|
||||
if (SecurityStatus == null)
|
||||
{
|
||||
IsBootLoaderUnlocked = !Info.IsBootloaderSecure;
|
||||
IsBootLoaderUnlocked = !FlashInfo.IsBootloaderSecure;
|
||||
}
|
||||
|
||||
if (RootKeyHash == null)
|
||||
{
|
||||
RootKeyHash = Info.RKH ?? (new byte[32]);
|
||||
RootKeyHash = FlashInfo.RKH ?? (new byte[32]);
|
||||
}
|
||||
|
||||
TestPos = 3;
|
||||
|
||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
||||
if (FlashInfo.FlashAppProtocolVersionMajor < 2)
|
||||
{
|
||||
// This action is executed after the resources are selected by the user.
|
||||
void ReturnFunction(string FFUPath, string LoadersPath, string SBL3Path, string ProfileFFUPath, string EDEPath, string SupportedFFUPath, bool DoFixBoot)
|
||||
@@ -213,7 +219,7 @@ namespace WPinternals
|
||||
bool AlreadyUnlocked = false;
|
||||
if (DoUnlock)
|
||||
{
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
GPT GPT = FlashModel.ReadGPT();
|
||||
if ((GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null))
|
||||
{
|
||||
@@ -281,7 +287,7 @@ namespace WPinternals
|
||||
{
|
||||
FFU ProfileFFU = null;
|
||||
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
ProfileFFU = FFUs.Count > 0
|
||||
? new FFU(FFUs[0].Path)
|
||||
: throw new WPinternalsException("Profile FFU missing", "No profile FFU has been found in the repository for your device. You can add a profile FFU within the download section of the tool or by using the command line.");
|
||||
@@ -295,14 +301,64 @@ namespace WPinternals
|
||||
|
||||
TestPos = 5;
|
||||
|
||||
if (DoUnlock)
|
||||
IsSwitchingInterface = true;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
ActivateSubContext(new BootUnlockResourcesViewModel("Lumia Flash mode", RootKeyHash, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, ReturnFunction, Abort, IsBootLoaderUnlocked, true, Info.PlatformID, Info.Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateSubContext(new BootRestoreResourcesViewModel("Lumia Flash mode", RootKeyHash, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, ReturnFunction, Abort, IsBootLoaderUnlocked, true, Info.PlatformID, Info.Type));
|
||||
}
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoModel = (LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfo = LumiaPhoneInfoModel.ReadPhoneInfo();
|
||||
|
||||
IsSwitchingInterface = true;
|
||||
|
||||
ModernFlashApp = PhoneInfo.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
if (DoUnlock)
|
||||
{
|
||||
ActivateSubContext(new BootUnlockResourcesViewModel("Lumia Flash mode", RootKeyHash, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, ReturnFunction, Abort, IsBootLoaderUnlocked, true, FlashInfo.PlatformID, PhoneInfo.Type));
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateSubContext(new BootRestoreResourcesViewModel("Lumia Flash mode", RootKeyHash, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, ReturnFunction, Abort, IsBootLoaderUnlocked, true, FlashInfo.PlatformID, PhoneInfo.Type));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception Ex)
|
||||
@@ -451,7 +507,7 @@ namespace WPinternals
|
||||
}, null);
|
||||
}
|
||||
|
||||
private void StorePaths()
|
||||
private async void StorePaths()
|
||||
{
|
||||
RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\WPInternals", true) ?? Registry.CurrentUser.CreateSubKey(@"Software\WPInternals");
|
||||
|
||||
@@ -510,8 +566,56 @@ namespace WPinternals
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download && PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
{
|
||||
NokiaFlashModel Model = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
PhoneInfo Info = Model.ReadPhoneInfo();
|
||||
LumiaFlashAppModel Model = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo FlashInfo = Model.ReadPhoneInfo();
|
||||
|
||||
bool OriginalIsSwitchingInterface = IsSwitchingInterface;
|
||||
IsSwitchingInterface = true;
|
||||
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoModel = (LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfo = LumiaPhoneInfoModel.ReadPhoneInfo();
|
||||
|
||||
ModernFlashApp = PhoneInfo.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
IsSwitchingInterface = OriginalIsSwitchingInterface;
|
||||
|
||||
if (EDEPath == null)
|
||||
{
|
||||
@@ -524,7 +628,7 @@ namespace WPinternals
|
||||
{
|
||||
Key.SetValue("EDEPath", EDEPath);
|
||||
|
||||
App.Config.AddEmergencyToRepository(Info.Type, EDEPath, null);
|
||||
App.Config.AddEmergencyToRepository(PhoneInfo.Type, EDEPath, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,7 +746,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -658,7 +765,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
if (FFUs.Count > 0)
|
||||
@@ -688,7 +798,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -703,7 +816,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
TempEDEPath = LumiaV2UnlockBootViewModel.GetProgrammerPath(RootKeyHash, ProductType);
|
||||
if (TempEDEPath != null)
|
||||
@@ -753,7 +869,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -770,7 +889,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V1.1-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)).ToList();
|
||||
if (FFUs.Count > 0)
|
||||
@@ -815,7 +937,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -832,7 +957,10 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
List<FFUEntry> FFUs = App.Config.FFURepository.Where(e => App.PatchEngine.PatchDefinitions.First(p => p.Name == "SecureBootHack-V2-EFIESP").TargetVersions.Any(v => v.Description == e.OSVersion)).ToList();
|
||||
if (FFUs.Count > 0)
|
||||
@@ -1025,6 +1153,8 @@ namespace WPinternals
|
||||
{
|
||||
ValidateSupportedFfuPath();
|
||||
}
|
||||
|
||||
OkCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace WPinternals
|
||||
// TODO: Add logging
|
||||
private static void PerformSoftBrick(PhoneNotifierViewModel Notifier, FFU FFU)
|
||||
{
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
// Send FFU headers
|
||||
UInt64 CombinedFFUHeaderSize = FFU.HeaderSize;
|
||||
@@ -82,7 +82,10 @@ namespace WPinternals
|
||||
Result = true;
|
||||
LogFile.Log("Loader sent successfully");
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
if (Result)
|
||||
{
|
||||
@@ -136,7 +139,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -146,7 +149,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -156,7 +159,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -202,7 +205,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -212,7 +215,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -222,7 +225,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -270,7 +273,7 @@ namespace WPinternals
|
||||
|
||||
try
|
||||
{
|
||||
if (Notifier.CurrentModel is NokiaFlashModel)
|
||||
if (Notifier.CurrentModel is LumiaFlashAppModel)
|
||||
{
|
||||
await LumiaRelockUEFI(Notifier, FFUPath, true, SetWorkingStatus, UpdateWorkingStatus, null, (string Message, string SubMessage) =>
|
||||
{
|
||||
@@ -317,9 +320,9 @@ namespace WPinternals
|
||||
throw new Exception("Error: Parsing FFU-file failed.");
|
||||
}
|
||||
|
||||
if (Notifier.CurrentModel is NokiaFlashModel)
|
||||
if (Notifier.CurrentModel is LumiaFlashAppModel)
|
||||
{
|
||||
FlashVersion FlashVersion = ((NokiaFlashModel)Notifier.CurrentModel).GetFlashVersion();
|
||||
FlashVersion FlashVersion = ((LumiaFlashAppModel)Notifier.CurrentModel).GetFlashVersion();
|
||||
if (FlashVersion == null)
|
||||
{
|
||||
throw new Exception("Error: The version of the Flash Application on the phone could not be determined.");
|
||||
@@ -330,7 +333,7 @@ namespace WPinternals
|
||||
throw new Exception("Error: The version of the Flash Application on the phone is too old. Update your phone using Windows Updates or flash a newer ROM to your phone. Then try again.");
|
||||
}
|
||||
|
||||
UefiSecurityStatusResponse SecurityStatus = ((NokiaFlashModel)Notifier.CurrentModel).ReadSecurityStatus();
|
||||
UefiSecurityStatusResponse SecurityStatus = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadSecurityStatus();
|
||||
IsBootLoaderUnlocked = SecurityStatus.AuthenticationStatus || SecurityStatus.RdcStatus || !SecurityStatus.SecureFfuEfuseStatus;
|
||||
}
|
||||
|
||||
@@ -347,9 +350,9 @@ namespace WPinternals
|
||||
#endif
|
||||
|
||||
GPT NewGPT = null;
|
||||
if (Notifier.CurrentModel is NokiaFlashModel)
|
||||
if (Notifier.CurrentModel is LumiaFlashAppModel)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
@@ -361,7 +364,7 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
|
||||
NewGPT = ((NokiaFlashModel)Notifier.CurrentModel).ReadGPT();
|
||||
NewGPT = ((LumiaBootManagerAppModel)Notifier.CurrentModel).ReadGPT();
|
||||
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
@@ -445,7 +448,7 @@ namespace WPinternals
|
||||
}
|
||||
else if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
{
|
||||
RootKeyHash = ((NokiaFlashModel)Notifier.CurrentModel).ReadParam("RRKH");
|
||||
RootKeyHash = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadParam("RRKH");
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
@@ -570,7 +573,7 @@ namespace WPinternals
|
||||
if (IsBootLoaderUnlocked)
|
||||
// Flash phone in Flash app
|
||||
{
|
||||
NokiaFlashModel CurrentModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel CurrentModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
LogFile.Log("Start flashing in Custom Flash mode");
|
||||
|
||||
UInt64 TotalSectorCount = (UInt64)0x21 + 1 +
|
||||
@@ -729,7 +732,7 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash && FlashModel.ReadParam("FS")[3] > 0)
|
||||
{
|
||||
ExitSuccess("Bootloader is restored", "NOTE: You need to flash a stock ROM because you recovered a phone from a bootloader unlock failure.");
|
||||
@@ -740,7 +743,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -750,7 +753,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -760,7 +763,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -840,9 +843,9 @@ namespace WPinternals
|
||||
throw new Exception("Error: Parsing FFU-file failed.");
|
||||
}
|
||||
|
||||
if (Notifier.CurrentModel is NokiaFlashModel)
|
||||
if (Notifier.CurrentModel is LumiaFlashAppModel)
|
||||
{
|
||||
FlashVersion FlashVersion = ((NokiaFlashModel)Notifier.CurrentModel).GetFlashVersion();
|
||||
FlashVersion FlashVersion = ((LumiaFlashAppModel)Notifier.CurrentModel).GetFlashVersion();
|
||||
if (FlashVersion == null)
|
||||
{
|
||||
throw new Exception("Error: The version of the Flash Application on the phone could not be determined.");
|
||||
@@ -853,7 +856,7 @@ namespace WPinternals
|
||||
throw new Exception("Error: The version of the Flash Application on the phone is too old. Update your phone using Windows Updates or flash a newer ROM to your phone. Then try again.");
|
||||
}
|
||||
|
||||
UefiSecurityStatusResponse SecurityStatus = ((NokiaFlashModel)Notifier.CurrentModel).ReadSecurityStatus();
|
||||
UefiSecurityStatusResponse SecurityStatus = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadSecurityStatus();
|
||||
IsBootLoaderUnlocked = SecurityStatus.AuthenticationStatus || SecurityStatus.RdcStatus || !SecurityStatus.SecureFfuEfuseStatus;
|
||||
}
|
||||
|
||||
@@ -901,9 +904,9 @@ namespace WPinternals
|
||||
#endif
|
||||
|
||||
GPT NewGPT = null;
|
||||
if (Notifier.CurrentModel is NokiaFlashModel)
|
||||
if (Notifier.CurrentModel is LumiaFlashAppModel)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
@@ -915,7 +918,7 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
|
||||
NewGPT = ((NokiaFlashModel)Notifier.CurrentModel).ReadGPT();
|
||||
NewGPT = ((LumiaBootManagerAppModel)Notifier.CurrentModel).ReadGPT();
|
||||
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
@@ -1010,7 +1013,7 @@ namespace WPinternals
|
||||
}
|
||||
else if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
{
|
||||
RootKeyHash = ((NokiaFlashModel)Notifier.CurrentModel).ReadParam("RRKH");
|
||||
RootKeyHash = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadParam("RRKH");
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
@@ -1249,7 +1252,7 @@ namespace WPinternals
|
||||
if (IsBootLoaderUnlocked)
|
||||
// Flash phone in Flash app
|
||||
{
|
||||
NokiaFlashModel CurrentModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel CurrentModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
LogFile.Log("Start flashing in Custom Flash mode");
|
||||
|
||||
UInt64 TotalSectorCount = (UInt64)0x21 + 1 +
|
||||
@@ -1420,7 +1423,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -1430,7 +1433,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -1440,7 +1443,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
@@ -1464,54 +1467,6 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] GetGptChunk(NokiaFlashModel FlashModel, UInt32 Size)
|
||||
{
|
||||
// This function is also used to generate a dummy chunk to flash for testing.
|
||||
// The dummy chunk will contain the GPT, so it can be flashed to the first sectors for testing.
|
||||
byte[] GPTChunk = new byte[Size];
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||
FlashAppType OriginalAppType = Info.App;
|
||||
bool Switch = (Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure;
|
||||
if (Switch)
|
||||
{
|
||||
FlashModel.SwitchToBootManagerContext();
|
||||
}
|
||||
|
||||
byte[] Request = new byte[0x04];
|
||||
const string Header = "NOKT";
|
||||
|
||||
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
|
||||
|
||||
byte[] Buffer = FlashModel.ExecuteRawMethod(Request);
|
||||
if ((Buffer == null) || (Buffer.Length < 0x4408))
|
||||
{
|
||||
throw new InvalidOperationException("Unable to read GPT!");
|
||||
}
|
||||
|
||||
UInt16 Error = (UInt16)((Buffer[6] << 8) + Buffer[7]);
|
||||
if (Error > 0)
|
||||
{
|
||||
throw new NotSupportedException("ReadGPT: Error 0x" + Error.ToString("X4"));
|
||||
}
|
||||
|
||||
System.Buffer.BlockCopy(Buffer, 8, GPTChunk, 0, 0x4400);
|
||||
|
||||
if (Switch)
|
||||
{
|
||||
if (OriginalAppType == FlashAppType.FlashApp)
|
||||
{
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
FlashModel.SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
}
|
||||
|
||||
return GPTChunk;
|
||||
}
|
||||
|
||||
// Magic!
|
||||
// UEFI Secure Boot Hack for Spec A and Spec B devices
|
||||
//
|
||||
@@ -1544,7 +1499,7 @@ namespace WPinternals
|
||||
{
|
||||
GPT GPT = null;
|
||||
Partition Target = null;
|
||||
NokiaFlashModel FlashModel = null;
|
||||
LumiaFlashAppModel FlashModel = null;
|
||||
|
||||
LogFile.Log("Command: Relock phone", LogType.FileAndConsole);
|
||||
|
||||
@@ -1555,13 +1510,18 @@ namespace WPinternals
|
||||
|
||||
byte[] EFIESPBackup = null;
|
||||
|
||||
PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
bool IsSpecB = Info.FlashAppProtocolVersionMajor >= 2;
|
||||
bool UndoEFIESPPadding = false;
|
||||
|
||||
byte[] GPTChunk;
|
||||
|
||||
if (!IsSpecB)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
@@ -1572,9 +1532,14 @@ namespace WPinternals
|
||||
{
|
||||
throw new WPinternalsException("Phone is in an unexpected mode.", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
|
||||
GPTChunk = ((LumiaBootManagerAppModel)Notifier.CurrentModel).GetGptChunk(0x20000);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPTChunk = ((LumiaFlashAppModel)Notifier.CurrentModel).GetGptChunk(0x20000);
|
||||
}
|
||||
|
||||
byte[] GPTChunk = GetGptChunk((NokiaFlashModel)Notifier.CurrentModel, 0x20000);
|
||||
GPT = new GPT(GPTChunk);
|
||||
bool GPTChanged = false;
|
||||
Partition IsUnlockedPartitionSBL3 = GPT.GetPartition("IS_UNLOCKED_SBL3");
|
||||
@@ -1716,7 +1681,7 @@ namespace WPinternals
|
||||
|
||||
SetWorkingStatus("Flashing...", "The phone may reboot a couple of times. Just wait for it.", null, Status: WPinternalsStatus.Initializing);
|
||||
|
||||
((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
|
||||
List<FlashPart> FlashParts = new();
|
||||
|
||||
@@ -1727,7 +1692,7 @@ namespace WPinternals
|
||||
|
||||
FlashPart Part;
|
||||
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
// Remove IS_UNLOCKED flag in GPT
|
||||
Partition IsUnlockedPartition = GPT.GetPartition("IS_UNLOCKED");
|
||||
@@ -1785,7 +1750,7 @@ namespace WPinternals
|
||||
|
||||
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
|
||||
bool NvCleared = false;
|
||||
Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
Info = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
|
||||
{
|
||||
// ClearNV
|
||||
@@ -1854,7 +1819,7 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Flash)
|
||||
@@ -1883,7 +1848,7 @@ namespace WPinternals
|
||||
internal static async Task LumiaUnlockUEFI(PhoneNotifierViewModel Notifier, string ProfileFFUPath, string EDEPath, string SupportedFFUPath, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, bool ExperimentalSpecBEFIESPUnlock = false, bool ExperimentalSpecAEFIESPUnlock = true, bool ReUnlockDevice = false)
|
||||
{
|
||||
LogFile.BeginAction("UnlockBootloader");
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
if (SetWorkingStatus == null)
|
||||
{
|
||||
@@ -1907,7 +1872,7 @@ namespace WPinternals
|
||||
|
||||
try
|
||||
{
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
bool IsSpecB = Info.FlashAppProtocolVersionMajor >= 2;
|
||||
|
||||
if (ProfileFFUPath == null)
|
||||
@@ -1954,7 +1919,7 @@ namespace WPinternals
|
||||
|
||||
LumiaPatchEFIESP(SupportedFFU, UnlockedEFIESP, IsSpecB);
|
||||
|
||||
byte[] GPTChunk = GetGptChunk(FlashModel, (UInt32)ProfileFFU.ChunkSize);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk((UInt32)ProfileFFU.ChunkSize);
|
||||
byte[] GPTChunkBackup = new byte[GPTChunk.Length];
|
||||
Buffer.BlockCopy(GPTChunk, 0, GPTChunkBackup, 0, GPTChunk.Length);
|
||||
GPT GPT = new(GPTChunk);
|
||||
@@ -2039,8 +2004,8 @@ namespace WPinternals
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
FlashModel = ((LumiaFlashAppModel)Notifier.CurrentModel);
|
||||
}
|
||||
|
||||
GPTChanged = false;
|
||||
@@ -2205,7 +2170,7 @@ namespace WPinternals
|
||||
|
||||
if (!IsSpecB && !SBL3Eng)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
|
||||
LogFile.Log("Bootloader unlocked!", LogType.FileAndConsole);
|
||||
ExitSuccess("Bootloader unlocked successfully!", null);
|
||||
@@ -2341,7 +2306,7 @@ namespace WPinternals
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
} ((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
} ((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
|
||||
UInt32 OriginalEfiespFirstSector;
|
||||
if (!ReUnlockDevice)
|
||||
@@ -2501,7 +2466,7 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
}
|
||||
((NokiaFlashModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
|
||||
Parts = LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
|
||||
|
||||
@@ -2514,7 +2479,7 @@ namespace WPinternals
|
||||
|
||||
if (!IsSpecB)
|
||||
{
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2634,7 +2599,7 @@ namespace WPinternals
|
||||
|
||||
private static async Task LumiaFlashParts(PhoneNotifierViewModel Notifier, string FFUPath, bool PerformFullFlashFirst, bool SkipWrite, List<FlashPart> Parts, bool DoResetFirst = true, bool ClearFlashingStatusAtEnd = true, bool CheckSectorAlignment = true, bool ShowProgress = true, bool Experimental = false, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, string EDEPath = null)
|
||||
{
|
||||
PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
bool IsSpecA = Info.FlashAppProtocolVersionMajor < 2;
|
||||
|
||||
if (IsSpecA)
|
||||
@@ -2651,56 +2616,59 @@ namespace WPinternals
|
||||
{
|
||||
SetWorkingStatus("Initializing flash...", null, 100, Status: WPinternalsStatus.Initializing);
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
UInt64 InputStreamLength = 0;
|
||||
UInt64 totalwritten = 0;
|
||||
int ProgressPercentage = 0;
|
||||
|
||||
foreach (FlashPart Part in FlashParts)
|
||||
if (FlashParts != null)
|
||||
{
|
||||
InputStreamLength += (ulong)Part.Stream.Length;
|
||||
}
|
||||
|
||||
foreach (FlashPart Part in FlashParts)
|
||||
{
|
||||
Stream InputStream = new DecompressedStream(Part.Stream);
|
||||
|
||||
if (InputStream != null)
|
||||
foreach (FlashPart Part in FlashParts)
|
||||
{
|
||||
using (InputStream)
|
||||
InputStreamLength += (ulong)Part.Stream.Length;
|
||||
}
|
||||
|
||||
foreach (FlashPart Part in FlashParts)
|
||||
{
|
||||
Stream InputStream = new DecompressedStream(Part.Stream);
|
||||
|
||||
if (InputStream != null)
|
||||
{
|
||||
const int FlashBufferSize = 0x200000; // Flash 8 GB phone -> buffersize 0x200000 = 11:45 min, buffersize 0x20000 = 12:30 min
|
||||
byte[] FlashBuffer = new byte[FlashBufferSize];
|
||||
int BytesRead;
|
||||
UInt64 i = 0;
|
||||
do
|
||||
using (InputStream)
|
||||
{
|
||||
BytesRead = InputStream.Read(FlashBuffer, 0, FlashBufferSize);
|
||||
|
||||
byte[] FlashBufferFinalSize;
|
||||
if (BytesRead > 0)
|
||||
const int FlashBufferSize = 0x200000; // Flash 8 GB phone -> buffersize 0x200000 = 11:45 min, buffersize 0x20000 = 12:30 min
|
||||
byte[] FlashBuffer = new byte[FlashBufferSize];
|
||||
int BytesRead;
|
||||
UInt64 i = 0;
|
||||
do
|
||||
{
|
||||
if (BytesRead == FlashBufferSize)
|
||||
BytesRead = InputStream.Read(FlashBuffer, 0, FlashBufferSize);
|
||||
|
||||
byte[] FlashBufferFinalSize;
|
||||
if (BytesRead > 0)
|
||||
{
|
||||
FlashBufferFinalSize = FlashBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlashBufferFinalSize = new byte[BytesRead];
|
||||
Buffer.BlockCopy(FlashBuffer, 0, FlashBufferFinalSize, 0, BytesRead);
|
||||
if (BytesRead == FlashBufferSize)
|
||||
{
|
||||
FlashBufferFinalSize = FlashBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlashBufferFinalSize = new byte[BytesRead];
|
||||
Buffer.BlockCopy(FlashBuffer, 0, FlashBufferFinalSize, 0, BytesRead);
|
||||
}
|
||||
|
||||
FlashModel.FlashSectors((UInt32)(Part.StartSector + (i / 0x200)), FlashBufferFinalSize, ProgressPercentage);
|
||||
}
|
||||
|
||||
FlashModel.FlashSectors((UInt32)(Part.StartSector + (i / 0x200)), FlashBufferFinalSize, ProgressPercentage);
|
||||
UpdateWorkingStatus(Part.ProgressText, null, (uint)ProgressPercentage, WPinternalsStatus.Flashing);
|
||||
totalwritten += (UInt64)FlashBuffer.Length / 0x200;
|
||||
ProgressPercentage = (int)((double)totalwritten / (InputStreamLength / 0x200) * 100);
|
||||
|
||||
i += FlashBufferSize;
|
||||
}
|
||||
|
||||
UpdateWorkingStatus(Part.ProgressText, null, (uint)ProgressPercentage, WPinternalsStatus.Flashing);
|
||||
totalwritten += (UInt64)FlashBuffer.Length / 0x200;
|
||||
ProgressPercentage = (int)((double)totalwritten / (InputStreamLength / 0x200) * 100);
|
||||
|
||||
i += FlashBufferSize;
|
||||
while (BytesRead == FlashBufferSize);
|
||||
}
|
||||
while (BytesRead == FlashBufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ namespace WPinternals
|
||||
{
|
||||
LogFile.Log("Find Flashing Profile", LogType.FileAndConsole);
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
PhoneInfo Info;
|
||||
LumiaFlashAppPhoneInfo Info;
|
||||
if (DoResetFirst)
|
||||
{
|
||||
// The phone will be reset before flashing, so we have the opportunity to get some more info from the phone
|
||||
@@ -125,14 +125,14 @@ namespace WPinternals
|
||||
LogFile.Log("Command: Enable testsigning", LogType.FileAndConsole);
|
||||
PhoneNotifierViewModel Notifier = new();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
List<FlashPart> Parts = new();
|
||||
FlashPart Part;
|
||||
|
||||
// Use GetGptChunk() here instead of ReadGPT(), because ReadGPT() skips the first sector.
|
||||
// We need the fist sector if we want to write back the GPT.
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
bool GPTChanged = false;
|
||||
|
||||
@@ -228,11 +228,11 @@ namespace WPinternals
|
||||
return ((MassStorage)Notifier.CurrentModel).Drive;
|
||||
}
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
if (DoResetFirst)
|
||||
{
|
||||
// The phone will be reset before flashing, so we have the opportunity to get some more info from the phone
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
}
|
||||
|
||||
@@ -260,12 +260,12 @@ namespace WPinternals
|
||||
LogFile.Log("Command: Clear NV", LogType.FileAndConsole);
|
||||
PhoneNotifierViewModel Notifier = new();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
List<FlashPart> Parts = new();
|
||||
|
||||
// Use GetGptChunk() here instead of ReadGPT(), because ReadGPT() skips the first sector.
|
||||
// We need the fist sector if we want to write back the GPT.
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
bool GPTChanged = false;
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
@@ -336,13 +336,13 @@ namespace WPinternals
|
||||
PhoneNotifierViewModel Notifier = new();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
|
||||
// Use GetGptChunk() here instead of ReadGPT(), because ReadGPT() skips the first sector.
|
||||
// We need the fist sector if we want to write back the GPT.
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
|
||||
Partition TargetPartition = GPT.GetPartition(PartitionName);
|
||||
@@ -445,9 +445,9 @@ namespace WPinternals
|
||||
PhoneNotifierViewModel Notifier = new();
|
||||
UIContext.Send(s => Notifier.Start(), null);
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash);
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
|
||||
byte[] Data = File.ReadAllBytes(DataPath);
|
||||
|
||||
@@ -483,10 +483,10 @@ namespace WPinternals
|
||||
|
||||
internal async static Task LumiaV2CustomFlash(PhoneNotifierViewModel Notifier, string FFUPath, bool PerformFullFlashFirst, bool SkipWrite, List<FlashPart> FlashParts, bool DoResetFirst = true, bool ClearFlashingStatusAtEnd = true, bool CheckSectorAlignment = true, bool ShowProgress = true, bool Experimental = false, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, string ProgrammerPath = null)
|
||||
{
|
||||
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
PhoneInfo Info = Model.ReadPhoneInfo();
|
||||
LumiaFlashAppModel Model = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo Info = Model.ReadPhoneInfo();
|
||||
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Model, 131072u);
|
||||
byte[] GPTChunk = Model.GetGptChunk(131072u);
|
||||
|
||||
GPT GPT = new(GPTChunk);
|
||||
|
||||
@@ -554,13 +554,55 @@ namespace WPinternals
|
||||
ExitFailure = (m, s) => { };
|
||||
}
|
||||
|
||||
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
PhoneInfo Info = Model.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo FlashInfo = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo();
|
||||
|
||||
string Type = Info.Type;
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)Notifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoModel = (LumiaPhoneInfoAppModel)Notifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfo = LumiaPhoneInfoModel.ReadPhoneInfo();
|
||||
|
||||
ModernFlashApp = PhoneInfo.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await Notifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
string Type = PhoneInfo.Type;
|
||||
if (ProgrammerPath == null)
|
||||
{
|
||||
ProgrammerPath = GetProgrammerPath(Info.RKH, Type);
|
||||
ProgrammerPath = GetProgrammerPath(FlashInfo.RKH, Type);
|
||||
if (ProgrammerPath == null)
|
||||
{
|
||||
LogFile.Log("WARNING: No emergency programmer file found. Finding flash profile and rebooting phone may take a long time!", LogType.FileAndConsole);
|
||||
@@ -571,10 +613,10 @@ namespace WPinternals
|
||||
if (FFUPath == null)
|
||||
{
|
||||
// Try to find an FFU from the repository for which there is also a known flashing profile
|
||||
FFUs = App.Config.FFURepository.Where(e => Info.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
FFUs = App.Config.FFURepository.Where(e => FlashInfo.PlatformID.StartsWith(e.PlatformID, StringComparison.OrdinalIgnoreCase) && e.Exists()).ToList();
|
||||
foreach (FFUEntry CurrentEntry in FFUs)
|
||||
{
|
||||
Profile = App.Config.GetProfile(Info.PlatformID, Info.Firmware, CurrentEntry.FirmwareVersion);
|
||||
Profile = App.Config.GetProfile(FlashInfo.PlatformID, FlashInfo.Firmware, CurrentEntry.FirmwareVersion);
|
||||
if (Profile != null)
|
||||
{
|
||||
FFUPath = CurrentEntry.Path;
|
||||
@@ -630,14 +672,14 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV2)) == 0) // Exploit needs protocol v2 -> This check is not conclusive, because old phones also report support for this protocol, although it is really not supported.
|
||||
if ((FlashInfo.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV2)) == 0) // Exploit needs protocol v2 -> This check is not conclusive, because old phones also report support for this protocol, although it is really not supported.
|
||||
{
|
||||
throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that it does not support the Protocol Sync V2.");
|
||||
}
|
||||
|
||||
if (Info.FlashAppProtocolVersionMajor < 2) // Old phones do not support the hack. These phones have Flash protocol 1.x.
|
||||
if (FlashInfo.FlashAppProtocolVersionMajor < 2) // Old phones do not support the hack. These phones have Flash protocol 1.x.
|
||||
{
|
||||
throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that Flash App communication protocol is lower than 2. Reported version by the phone: " + Info.FlashAppProtocolVersionMajor + ".");
|
||||
throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that Flash App communication protocol is lower than 2. Reported version by the phone: " + FlashInfo.FlashAppProtocolVersionMajor + ".");
|
||||
}
|
||||
|
||||
UEFI UEFI = new(FFU.GetPartition("UEFI"));
|
||||
@@ -649,7 +691,7 @@ namespace WPinternals
|
||||
Options = (byte)FlashOptions.SkipWrite;
|
||||
}
|
||||
|
||||
if (!Info.IsBootloaderSecure)
|
||||
if (!FlashInfo.IsBootloaderSecure)
|
||||
{
|
||||
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
|
||||
}
|
||||
@@ -673,7 +715,7 @@ namespace WPinternals
|
||||
MaximumAttempts = (int)(((MaximumGapFill / FFU.ChunkSize) + 1) * 8);
|
||||
}
|
||||
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Model, (UInt32)FFU.ChunkSize);
|
||||
byte[] GPTChunk = ((LumiaFlashAppModel)Notifier.CurrentModel).GetGptChunk((UInt32)FFU.ChunkSize);
|
||||
|
||||
// Start with a reset
|
||||
if (DoResetFirst)
|
||||
@@ -682,7 +724,7 @@ namespace WPinternals
|
||||
|
||||
// When in flash mode, it is not possible to reboot straight to flash.
|
||||
// Reboot and catch the phone in bootloader mode and then switch to flash context
|
||||
Model.ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
|
||||
#region Properly recover from reset - many phones respond differently
|
||||
|
||||
@@ -818,22 +860,22 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Phone is in wrong mode", "The phone should have been detected in bootloader or flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
|
||||
}
|
||||
|
||||
Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
UpdateWorkingStatus("Initializing flash...", null, null);
|
||||
}
|
||||
|
||||
try
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
// This will succeed on new models
|
||||
Model.SwitchToFlashAppContext();
|
||||
Model.DisableRebootTimeOut();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).ResetPhoneToFlashMode();
|
||||
}
|
||||
catch
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
// This will succeed on old models
|
||||
Model.ResetPhoneToFlashMode();
|
||||
await Notifier.WaitForArrival();
|
||||
Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
}
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
// The payloads must be ordered by the number of locations
|
||||
@@ -849,7 +891,7 @@ namespace WPinternals
|
||||
{
|
||||
payloads =
|
||||
[
|
||||
.. GetNonOptimizedPayloads(FlashParts, FFU.ChunkSize, (uint)(Info.WriteBufferSize / FFU.ChunkSize), SetWorkingStatus, UpdateWorkingStatus).OrderBy(x => x.TargetLocations.Length),
|
||||
.. GetNonOptimizedPayloads(FlashParts, FFU.ChunkSize, (uint)(FlashInfo.WriteBufferSize / FFU.ChunkSize), SetWorkingStatus, UpdateWorkingStatus).OrderBy(x => x.TargetLocations.Length),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -876,7 +918,7 @@ namespace WPinternals
|
||||
bool Scanning = false;
|
||||
bool ResetScanning = false;
|
||||
|
||||
Profile = App.Config.GetProfile(Info.PlatformID, Info.Firmware, FFU.GetFirmwareVersion());
|
||||
Profile = App.Config.GetProfile(FlashInfo.PlatformID, FlashInfo.Firmware, FFU.GetFirmwareVersion());
|
||||
if (Profile == null)
|
||||
{
|
||||
LogFile.Log("No flashing profile found", LogType.FileAndConsole);
|
||||
@@ -926,17 +968,17 @@ namespace WPinternals
|
||||
//
|
||||
if (AllocateAsyncBuffersOnPhone)
|
||||
{
|
||||
Model.StartAsyncFlash();
|
||||
Model.EndAsyncFlash(); // Ending Async flashing is not necessary for Lumia 950, but it is necessary for Lumia 640!
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).StartAsyncFlash();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).EndAsyncFlash(); // Ending Async flashing is not necessary for Lumia 950, but it is necessary for Lumia 640!
|
||||
}
|
||||
|
||||
if (AllocateBackupBuffersOnPhone)
|
||||
{
|
||||
Model.BackupPartitionToRam("MODEM_FSG");
|
||||
Model.BackupPartitionToRam("MODEM_FS1");
|
||||
Model.BackupPartitionToRam("MODEM_FS2");
|
||||
Model.BackupPartitionToRam("SSD");
|
||||
Model.BackupPartitionToRam("DPP");
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).BackupPartitionToRam("MODEM_FSG");
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).BackupPartitionToRam("MODEM_FS1");
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).BackupPartitionToRam("MODEM_FS2");
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).BackupPartitionToRam("SSD");
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).BackupPartitionToRam("DPP");
|
||||
}
|
||||
|
||||
HeaderOffset = 0;
|
||||
@@ -986,20 +1028,20 @@ namespace WPinternals
|
||||
// Previous data + new data must fit in new headersize.
|
||||
// We can send an extra byte, because last memory buffer was sent including the tail.
|
||||
// And there is always extra space in the memoryspace after the tail.
|
||||
Model.SendFfuHeaderV2(LastHeaderV2Size + 1, 0, new byte[1], Options);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(LastHeaderV2Size + 1, 0, new byte[1], Options);
|
||||
}
|
||||
|
||||
// CurrentGapFill is the amount of data we want to be allocated on the phone
|
||||
// But we send less data, so the header won't be processed yet.
|
||||
PartialHeader = new byte[UefiMemorySim.PageSize];
|
||||
Model.SendFfuHeaderV2(CurrentGapFill, 0, PartialHeader, Options); // Fill memory gap -> This will fail on phones with Flash Protocol v1.x !! On Lumia 640 this will hang on receiving the response when EndAsyncFlash was not called.
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(CurrentGapFill, 0, PartialHeader, Options); // Fill memory gap -> This will fail on phones with Flash Protocol v1.x !! On Lumia 640 this will hang on receiving the response when EndAsyncFlash was not called.
|
||||
}
|
||||
|
||||
using (FileStream FfuFile = new(FFU.Path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
// On every flashing phase we need to send the full header again to reset all the counters.
|
||||
FfuFile.Read(FfuHeader, 0, (int)CombinedFFUHeaderSize);
|
||||
Model.SendFfuHeaderV1(FfuHeader, Options);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV1(FfuHeader, Options);
|
||||
|
||||
if (PerformFullFlashFirst && (FlashingPhase == 0))
|
||||
{
|
||||
@@ -1016,11 +1058,11 @@ namespace WPinternals
|
||||
UInt32 TotalChunkCount = (UInt32)FFU.TotalChunkCount;
|
||||
|
||||
// Protocol v2
|
||||
FlashPayload = new byte[Info.WriteBufferSize];
|
||||
FlashPayload = new byte[FlashInfo.WriteBufferSize];
|
||||
|
||||
while (Position < (UInt64)FfuFile.Length)
|
||||
{
|
||||
UInt32 CommonFlashPayloadSize = Info.WriteBufferSize;
|
||||
UInt32 CommonFlashPayloadSize = FlashInfo.WriteBufferSize;
|
||||
if (((UInt64)FfuFile.Length - Position) < CommonFlashPayloadSize)
|
||||
{
|
||||
CommonFlashPayloadSize = (UInt32)((UInt64)FfuFile.Length - Position);
|
||||
@@ -1029,7 +1071,7 @@ namespace WPinternals
|
||||
|
||||
FfuFile.Read(FlashPayload, 0, (int)CommonFlashPayloadSize);
|
||||
ChunkIndex += (int)(CommonFlashPayloadSize / FFU.ChunkSize);
|
||||
Model.SendFfuPayloadV2(FlashPayload, ShowProgress ? (int)((double)(ChunkIndex + 1) * 100 / TotalChunkCount) : 0, 0);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuPayloadV2(FlashPayload, ShowProgress ? (int)((double)(ChunkIndex + 1) * 100 / TotalChunkCount) : 0, 0);
|
||||
Position += CommonFlashPayloadSize;
|
||||
}
|
||||
}
|
||||
@@ -1151,7 +1193,7 @@ namespace WPinternals
|
||||
// This will allocate new memory at the bottom of the memory-pool, but it will not reset the previously imported ffu header.
|
||||
Step = 1;
|
||||
PartialHeader = new byte[UefiMemorySim.PageSize];
|
||||
Model.SendFfuHeaderV2(ExploitHeaderAllocationSize, 0, PartialHeader, Options); // SkipWrite = 1 (only works on engineering phones)
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(ExploitHeaderAllocationSize, 0, PartialHeader, Options); // SkipWrite = 1 (only works on engineering phones)
|
||||
|
||||
// Now we will send the rest of the exploit header, but we will increase the total size even higher, so that it still won't start processing the headers.
|
||||
// We've send only a small first part of the header. The allocated header was bigger: ExploitHeaderAllocationSize.
|
||||
@@ -1162,14 +1204,14 @@ namespace WPinternals
|
||||
while (ExploitHeaderRemaining > 0)
|
||||
{
|
||||
UInt32 CurrentFill = ExploitHeaderRemaining;
|
||||
if (CurrentFill > Info.WriteBufferSize)
|
||||
if (CurrentFill > FlashInfo.WriteBufferSize)
|
||||
{
|
||||
CurrentFill = Info.WriteBufferSize;
|
||||
CurrentFill = FlashInfo.WriteBufferSize;
|
||||
}
|
||||
|
||||
PartialHeader = new byte[CurrentFill];
|
||||
PartialHeaderAllocation.CopyFromThisAllocation(HeaderOffset, CurrentFill, PartialHeader, 0);
|
||||
Model.SendFfuHeaderV2(HeaderOffset + CurrentFill + 1, HeaderOffset, PartialHeader, Options); // Phone may crash here. USB write is done. USB read might fail due to crash. Happens on my own Lumia 650.
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(HeaderOffset + CurrentFill + 1, HeaderOffset, PartialHeader, Options); // Phone may crash here. USB write is done. USB read might fail due to crash. Happens on my own Lumia 650.
|
||||
LastHeaderV2Size = HeaderOffset + CurrentFill + 1;
|
||||
ExploitHeaderRemaining -= CurrentFill;
|
||||
HeaderOffset += CurrentFill;
|
||||
@@ -1178,7 +1220,7 @@ namespace WPinternals
|
||||
// Send custom payload
|
||||
Step = 3;
|
||||
Int32 payloadCount = 0;
|
||||
byte[] payloadBuffer = new byte[Info.WriteBufferSize];
|
||||
byte[] payloadBuffer = new byte[FlashInfo.WriteBufferSize];
|
||||
bool sendPayload = false;
|
||||
for (Int32 i = FlashInProgress ? 0 : -1; i < FlashingPhasePayloadCount; i++)
|
||||
{
|
||||
@@ -1192,7 +1234,7 @@ namespace WPinternals
|
||||
Step = 8;
|
||||
// This may fail. Normally with WPinternalsException for Invalid Hash or Data not aligned.
|
||||
// Or it may fail with a BadConnectionException when the phone crashes and drops the connection.
|
||||
Model.SendFfuPayloadV1(Buffer, 0);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuPayloadV1(Buffer, 0);
|
||||
if (!FlashInProgress)
|
||||
{
|
||||
Step = 9;
|
||||
@@ -1212,7 +1254,7 @@ namespace WPinternals
|
||||
|
||||
FlashingPayload payload = payloads[FlashingPhaseStartPayloadIndex + i];
|
||||
|
||||
if (payloadCount == ((Info.WriteBufferSize / FFU.ChunkSize) - 1))
|
||||
if (payloadCount == ((FlashInfo.WriteBufferSize / FFU.ChunkSize) - 1))
|
||||
{
|
||||
sendPayload = true;
|
||||
}
|
||||
@@ -1288,10 +1330,10 @@ namespace WPinternals
|
||||
if (i != -1 && sendPayload)
|
||||
{
|
||||
// This fails when sending multiple chunks per payload with 0x1003: Hash mismatch
|
||||
Model.SendFfuPayloadV2(payloadBuffer, ShowProgress ? (Int32)((FlashingPhaseStartPayloadIndex + i + 1) * 100 / payloads.Length) : 0);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuPayloadV2(payloadBuffer, ShowProgress ? (Int32)((FlashingPhaseStartPayloadIndex + i + 1) * 100 / payloads.Length) : 0);
|
||||
sendPayload = false;
|
||||
payloadCount = 0;
|
||||
payloadBuffer = new byte[Info.WriteBufferSize];
|
||||
payloadBuffer = new byte[FlashInfo.WriteBufferSize];
|
||||
}
|
||||
|
||||
DestinationChunkIndex++;
|
||||
@@ -1304,7 +1346,7 @@ namespace WPinternals
|
||||
if (!HeadersFull)
|
||||
{
|
||||
Step = 12;
|
||||
App.Config.SetProfile(Info.Type, Info.PlatformID, Info.ProductCode, Info.Firmware, FFU.GetFirmwareVersion(), CurrentGapFill, ExploitHeaderAllocationSize, AssumeImageHeaderFallsInGap, AllocateAsyncBuffersOnPhone);
|
||||
App.Config.SetProfile(PhoneInfo.Type, FlashInfo.PlatformID, PhoneInfo.ProductCode, FlashInfo.Firmware, FFU.GetFirmwareVersion(), CurrentGapFill, ExploitHeaderAllocationSize, AssumeImageHeaderFallsInGap, AllocateAsyncBuffersOnPhone);
|
||||
if (ShowProgress)
|
||||
{
|
||||
LogFile.Log("Custom flash succeeded!", LogType.FileAndConsole);
|
||||
@@ -1381,7 +1423,7 @@ namespace WPinternals
|
||||
|
||||
if (PhoneNeedsReset)
|
||||
{
|
||||
Model.ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
WaitForReset = true;
|
||||
}
|
||||
|
||||
@@ -1516,11 +1558,9 @@ namespace WPinternals
|
||||
break;
|
||||
}
|
||||
|
||||
Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
|
||||
// In case we are on an Engineering phone which isn't stuck in flashmode and booted to BootMgrApp
|
||||
Model.SwitchToFlashAppContext();
|
||||
Model.DisableRebootTimeOut();
|
||||
((LumiaBootManagerAppModel)Notifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).DisableRebootTimeOut();
|
||||
}
|
||||
|
||||
PhoneNeedsReset = false;
|
||||
@@ -1613,38 +1653,38 @@ namespace WPinternals
|
||||
ByteOperations.WriteUInt32(UefiMemorySim.Buffer, StoreHeaderAllocation.HeadStart + 4, 0); // Set allocation size to 0 in allocationhead
|
||||
if (CurrentGapFill > UefiMemorySim.PageSize)
|
||||
{
|
||||
Model.SendFfuHeaderV2(LastHeaderV2Size + 1, 0, new byte[1], Options);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(LastHeaderV2Size + 1, 0, new byte[1], Options);
|
||||
PartialHeader = new byte[UefiMemorySim.PageSize];
|
||||
Model.SendFfuHeaderV2(CurrentGapFill, 0, PartialHeader, Options); // Fill memory gap
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(CurrentGapFill, 0, PartialHeader, Options); // Fill memory gap
|
||||
}
|
||||
using (FileStream FfuFile = new(FFU.Path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
// On every flashing phase we need to send the full header again, because this triggers ffu_import_invalidate(), which is necessary to reset all the counters.
|
||||
FfuFile.Read(FfuHeader, 0, (int)CombinedFFUHeaderSize);
|
||||
Model.SendFfuHeaderV1(FfuHeader, Options);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV1(FfuHeader, Options);
|
||||
}
|
||||
PartialHeader = new byte[UefiMemorySim.PageSize];
|
||||
Model.SendFfuHeaderV2(ExploitHeaderAllocationSize, 0, PartialHeader, Options); // SkipWrite = 1 (only works on engineering phones)
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(ExploitHeaderAllocationSize, 0, PartialHeader, Options); // SkipWrite = 1 (only works on engineering phones)
|
||||
UInt32 ExploitHeaderRemaining = SecurityHeaderAllocation.TailEnd + 1 - PartialHeaderAllocation.ContentStart - (UInt32)PartialHeader.Length;
|
||||
HeaderOffset = (UInt32)PartialHeader.Length;
|
||||
while (ExploitHeaderRemaining > 0)
|
||||
{
|
||||
UInt32 CurrentFill = ExploitHeaderRemaining;
|
||||
if (CurrentFill > Info.WriteBufferSize)
|
||||
if (CurrentFill > FlashInfo.WriteBufferSize)
|
||||
{
|
||||
CurrentFill = Info.WriteBufferSize;
|
||||
CurrentFill = FlashInfo.WriteBufferSize;
|
||||
}
|
||||
|
||||
PartialHeader = new byte[CurrentFill];
|
||||
PartialHeaderAllocation.CopyFromThisAllocation(HeaderOffset, CurrentFill, PartialHeader, 0);
|
||||
Model.SendFfuHeaderV2(HeaderOffset + CurrentFill + 1, HeaderOffset, PartialHeader, Options);
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).SendFfuHeaderV2(HeaderOffset + CurrentFill + 1, HeaderOffset, PartialHeader, Options);
|
||||
LastHeaderV2Size = HeaderOffset + CurrentFill + 1;
|
||||
ExploitHeaderRemaining -= CurrentFill;
|
||||
HeaderOffset += CurrentFill;
|
||||
}
|
||||
|
||||
// Do the actual reset, which will result in a crash while cleaning up memory
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
|
||||
LogFile.Log("Phone performs hard exit", LogType.FileAndConsole);
|
||||
|
||||
@@ -1782,7 +1822,7 @@ namespace WPinternals
|
||||
else
|
||||
{
|
||||
// If we didn't do a hard exit, we need to do a normal reboot
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
((LumiaFlashAppModel)Notifier.CurrentModel).ResetPhone();
|
||||
}
|
||||
|
||||
if (Success)
|
||||
@@ -1964,11 +2004,11 @@ namespace WPinternals
|
||||
{
|
||||
LogFile.BeginAction("FlashCustomROM");
|
||||
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
// Use GetGptChunk() here instead of ReadGPT(), because ReadGPT() skips the first sector.
|
||||
// We need the fist sector if we want to write back the GPT.
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
|
||||
Partition Target;
|
||||
@@ -2049,7 +2089,10 @@ namespace WPinternals
|
||||
{
|
||||
StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
|
||||
TotalSizeSectors += StreamLengthInSectors;
|
||||
PartitionCount++;
|
||||
@@ -2170,7 +2213,7 @@ namespace WPinternals
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(false);
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo(false);
|
||||
|
||||
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
|
||||
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
|
||||
@@ -2354,11 +2397,11 @@ namespace WPinternals
|
||||
// Assumes phone is in flash mode
|
||||
internal async static Task LumiaV2FlashPartitions(PhoneNotifierViewModel Notifier, string EFIESPPath, string MainOSPath, string DataPath, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null)
|
||||
{
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
|
||||
// Use GetGptChunk() here instead of ReadGPT(), because ReadGPT() skips the first sector.
|
||||
// We need the fist sector if we want to write back the GPT.
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(FlashModel, 0x20000);
|
||||
byte[] GPTChunk = FlashModel.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
|
||||
Partition Target;
|
||||
@@ -2529,7 +2572,7 @@ namespace WPinternals
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(false);
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo(false);
|
||||
|
||||
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
|
||||
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
|
||||
|
||||
@@ -192,8 +192,8 @@ namespace WPinternals
|
||||
|
||||
try
|
||||
{
|
||||
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
PhoneInfo Info = Model.ReadPhoneInfo();
|
||||
LumiaFlashAppModel Model = (LumiaFlashAppModel)Notifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo Info = Model.ReadPhoneInfo();
|
||||
|
||||
if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV2)) == 0) // Exploit needs protocol v2 -> This check is not conclusive, because old phones also report support for this protocol, although it is really not supported.
|
||||
{
|
||||
@@ -282,7 +282,7 @@ namespace WPinternals
|
||||
store.WriteDescriptorLength += payload.GetStoreHeaderSize();
|
||||
}
|
||||
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Model, 0x20000);
|
||||
byte[] GPTChunk = Model.GetGptChunk(0x20000);
|
||||
GPT GPT = new(GPTChunk);
|
||||
UInt64 PlatEnd = 0;
|
||||
if (GPT.Partitions.Any(x => x.Name == "PLAT"))
|
||||
|
||||
@@ -45,7 +45,8 @@ namespace WPinternals
|
||||
Lumia_Bootloader,
|
||||
Qualcomm_Download,
|
||||
Qualcomm_Flash,
|
||||
Lumia_BadMassStorage
|
||||
Lumia_BadMassStorage,
|
||||
Lumia_PhoneInfo
|
||||
};
|
||||
|
||||
// Create this class on the UI thread, after the main-window of the application is initialized.
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace WPinternals
|
||||
|
||||
internal class NokiaBootloaderViewModel : ContextViewModel
|
||||
{
|
||||
private readonly NokiaFlashModel CurrentModel;
|
||||
private readonly LumiaBootManagerAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces> RequestModeSwitch;
|
||||
internal Action SwitchToGettingStarted;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
@@ -38,7 +38,7 @@ namespace WPinternals
|
||||
internal NokiaBootloaderViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces> RequestModeSwitch, Action SwitchToGettingStarted)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (NokiaFlashModel)CurrentModel;
|
||||
this.CurrentModel = (LumiaBootManagerAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
this.SwitchToGettingStarted = SwitchToGettingStarted;
|
||||
}
|
||||
@@ -63,6 +63,9 @@ namespace WPinternals
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace WPinternals
|
||||
|
||||
internal class NokiaFlashViewModel : ContextViewModel
|
||||
{
|
||||
private readonly NokiaFlashModel CurrentModel;
|
||||
private readonly LumiaFlashAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces> RequestModeSwitch;
|
||||
internal Action SwitchToGettingStarted;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
@@ -39,7 +39,7 @@ namespace WPinternals
|
||||
internal NokiaFlashViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces> RequestModeSwitch, Action SwitchToGettingStarted)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (NokiaFlashModel)CurrentModel;
|
||||
this.CurrentModel = (LumiaFlashAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
this.SwitchToGettingStarted = SwitchToGettingStarted;
|
||||
}
|
||||
@@ -95,21 +95,21 @@ namespace WPinternals
|
||||
SecurityFlags = (UInt32)CurrentModel.ReadSecurityFlags();
|
||||
LogFile.Log("Security flags: 0x" + SecurityFlags.ToString("X8"));
|
||||
|
||||
FinalConfigDakStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Dak);
|
||||
FinalConfigFastBootStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.FastBoot);
|
||||
FinalConfigFfuVerifyStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.FfuVerify);
|
||||
FinalConfigJtagStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Jtag);
|
||||
FinalConfigOemIdStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.OemId);
|
||||
FinalConfigProductionDoneStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.ProductionDone);
|
||||
FinalConfigPublicIdStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.PublicId);
|
||||
FinalConfigRkhStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Rkh);
|
||||
FinalConfigRpmWdogStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.RpmWdog);
|
||||
FinalConfigSecGenStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.SecGen);
|
||||
FinalConfigSecureBootStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.SecureBoot);
|
||||
FinalConfigShkStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Shk);
|
||||
FinalConfigSimlockStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Simlock);
|
||||
FinalConfigSpdmSecModeStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.SpdmSecMode);
|
||||
FinalConfigSsmStatus = CurrentModel.ReadFuseStatus(NokiaFlashModel.Fuse.Ssm);
|
||||
FinalConfigDakStatus = CurrentModel.ReadFuseStatus(Fuse.Dak);
|
||||
FinalConfigFastBootStatus = CurrentModel.ReadFuseStatus(Fuse.FastBoot);
|
||||
FinalConfigFfuVerifyStatus = CurrentModel.ReadFuseStatus(Fuse.FfuVerify);
|
||||
FinalConfigJtagStatus = CurrentModel.ReadFuseStatus(Fuse.Jtag);
|
||||
FinalConfigOemIdStatus = CurrentModel.ReadFuseStatus(Fuse.OemId);
|
||||
FinalConfigProductionDoneStatus = CurrentModel.ReadFuseStatus(Fuse.ProductionDone);
|
||||
FinalConfigPublicIdStatus = CurrentModel.ReadFuseStatus(Fuse.PublicId);
|
||||
FinalConfigRkhStatus = CurrentModel.ReadFuseStatus(Fuse.Rkh);
|
||||
FinalConfigRpmWdogStatus = CurrentModel.ReadFuseStatus(Fuse.RpmWdog);
|
||||
FinalConfigSecGenStatus = CurrentModel.ReadFuseStatus(Fuse.SecGen);
|
||||
FinalConfigSecureBootStatus = CurrentModel.ReadFuseStatus(Fuse.SecureBoot);
|
||||
FinalConfigShkStatus = CurrentModel.ReadFuseStatus(Fuse.Shk);
|
||||
FinalConfigSimlockStatus = CurrentModel.ReadFuseStatus(Fuse.Simlock);
|
||||
FinalConfigSpdmSecModeStatus = CurrentModel.ReadFuseStatus(Fuse.SpdmSecMode);
|
||||
FinalConfigSsmStatus = CurrentModel.ReadFuseStatus(Fuse.Ssm);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -222,15 +222,15 @@ namespace WPinternals
|
||||
LogFile.Log("Charging status: " + ChargingStatus);
|
||||
}
|
||||
|
||||
PhoneInfo Info = CurrentModel.ReadPhoneInfo(true);
|
||||
LumiaFlashAppPhoneInfo Info = CurrentModel.ReadPhoneInfo(true);
|
||||
BootloaderDescription = Info.FlashAppProtocolVersionMajor < 2 ? "Lumia Bootloader Spec A" : "Lumia Bootloader Spec B";
|
||||
|
||||
LogFile.Log("Bootloader: " + BootloaderDescription);
|
||||
|
||||
ProductCode = Info.ProductCode;
|
||||
ProductCode = "";//TODO: FIXME: Info.ProductCode;
|
||||
LogFile.Log("ProductCode: " + ProductCode);
|
||||
|
||||
ProductType = Info.Type;
|
||||
ProductType = "";//TODO: FIXME: Info.Type;
|
||||
LogFile.Log("ProductType: " + ProductType);
|
||||
|
||||
if (RootKeyHash == null)
|
||||
@@ -748,6 +748,9 @@ namespace WPinternals
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -101,11 +101,20 @@ namespace WPinternals
|
||||
IMEI = CurrentModel.ExecuteJsonMethodAsString("ReadSerialNumber", "SerialNumber"); // IMEI
|
||||
LogFile.Log("IMEI: " + IMEI);
|
||||
BluetoothMac = CurrentModel.ExecuteJsonMethodAsBytes("ReadBtId", "BtId"); // 6 bytes: bc c6 ...
|
||||
LogFile.Log("Bluetooth MAC: " + Converter.ConvertHexToString(BluetoothMac, " "));
|
||||
WlanMac = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress1"); // 6 bytes
|
||||
LogFile.Log("WLAN MAC: " + Converter.ConvertHexToString(WlanMac, " "));
|
||||
|
||||
IsBootloaderSecurityEnabled = (bool)CurrentModel.ExecuteJsonMethodAsBoolean("ReadProductionDoneState", "ProductionDone");
|
||||
if (BluetoothMac != null)
|
||||
{
|
||||
LogFile.Log("Bluetooth MAC: " + Converter.ConvertHexToString(BluetoothMac, " "));
|
||||
}
|
||||
|
||||
WlanMac = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress1"); // 6 bytes
|
||||
|
||||
if (WlanMac != null)
|
||||
{
|
||||
LogFile.Log("WLAN MAC: " + Converter.ConvertHexToString(WlanMac, " "));
|
||||
}
|
||||
|
||||
IsBootloaderSecurityEnabled = CurrentModel.ExecuteJsonMethodAsBoolean("ReadProductionDoneState", "ProductionDone") ?? false;
|
||||
LogFile.Log("Bootloader Security: " + ((bool)IsBootloaderSecurityEnabled ? "Enabled" : "Disabled"));
|
||||
|
||||
Params = new Dictionary<string, object>
|
||||
@@ -283,6 +292,9 @@ namespace WPinternals
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace WPinternals
|
||||
{
|
||||
internal class NokiaModeBootloaderViewModel : ContextViewModel
|
||||
{
|
||||
private readonly NokiaFlashModel CurrentModel;
|
||||
private readonly LumiaBootManagerAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces?> RequestModeSwitch;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
private bool DeviceInfoLoaded = false;
|
||||
@@ -33,7 +33,7 @@ namespace WPinternals
|
||||
internal NokiaModeBootloaderViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces?> RequestModeSwitch)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (NokiaFlashModel)CurrentModel;
|
||||
this.CurrentModel = (LumiaBootManagerAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
}
|
||||
|
||||
@@ -67,21 +67,9 @@ namespace WPinternals
|
||||
{
|
||||
try
|
||||
{
|
||||
PhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||
LumiaBootManagerPhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||
|
||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
||||
{
|
||||
UefiSecurityStatusResponse SecurityStatus = CurrentModel.ReadSecurityStatus();
|
||||
|
||||
if (SecurityStatus != null)
|
||||
{
|
||||
EffectiveBootloaderSecurityStatus = SecurityStatus.SecureFfuEfuseStatus && !SecurityStatus.AuthenticationStatus && !SecurityStatus.RdcStatus;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectiveBootloaderSecurityStatus = Info.UefiSecureBootEnabled;
|
||||
}
|
||||
//EffectiveBootloaderSecurityStatus = Info.UefiSecureBootEnabled; // FIXME
|
||||
|
||||
LogFile.Log("Effective Bootloader Security Status: " + EffectiveBootloaderSecurityStatus.ToString());
|
||||
}
|
||||
@@ -101,6 +89,9 @@ namespace WPinternals
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace WPinternals
|
||||
{
|
||||
internal class NokiaModeFlashViewModel : ContextViewModel
|
||||
{
|
||||
private readonly NokiaFlashModel CurrentModel;
|
||||
private readonly LumiaFlashAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces?> RequestModeSwitch;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
private bool DeviceInfoLoaded = false;
|
||||
@@ -33,7 +33,7 @@ namespace WPinternals
|
||||
internal NokiaModeFlashViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces?> RequestModeSwitch)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (NokiaFlashModel)CurrentModel;
|
||||
this.CurrentModel = (LumiaFlashAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace WPinternals
|
||||
{
|
||||
try
|
||||
{
|
||||
PhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||
LumiaFlashAppPhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||
|
||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
||||
{
|
||||
@@ -103,6 +103,12 @@ namespace WPinternals
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -41,6 +41,12 @@ namespace WPinternals
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
|
||||
@@ -63,6 +63,12 @@ namespace WPinternals
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -41,6 +41,12 @@ namespace WPinternals
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
// 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;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class NokiaModePhoneInfoViewModel : ContextViewModel
|
||||
{
|
||||
private readonly LumiaPhoneInfoAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces?> RequestModeSwitch;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
private bool DeviceInfoLoaded = false;
|
||||
|
||||
internal NokiaModePhoneInfoViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces?> RequestModeSwitch)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (LumiaPhoneInfoAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
}
|
||||
|
||||
internal override void EvaluateViewState()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
new Thread(() => StartLoadDeviceInfo()).Start();
|
||||
}
|
||||
}
|
||||
|
||||
private bool? _EffectivePhoneInfoSecurityStatus = null;
|
||||
public bool? EffectivePhoneInfoSecurityStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return _EffectivePhoneInfoSecurityStatus;
|
||||
}
|
||||
set
|
||||
{
|
||||
_EffectivePhoneInfoSecurityStatus = value;
|
||||
OnPropertyChanged(nameof(EffectivePhoneInfoSecurityStatus));
|
||||
}
|
||||
}
|
||||
|
||||
internal void StartLoadDeviceInfo()
|
||||
{
|
||||
lock (LockDeviceInfo)
|
||||
{
|
||||
if (!DeviceInfoLoaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
LumiaPhoneInfoAppPhoneInfo Info = CurrentModel.ReadPhoneInfo();
|
||||
|
||||
//EffectivePhoneInfoSecurityStatus = Info.UefiSecureBootEnabled; // FIXME
|
||||
|
||||
LogFile.Log("Effective Bootloader Security Status: " + EffectivePhoneInfoSecurityStatus.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogFile.Log("Reading status from Flash interface was aborted.");
|
||||
}
|
||||
DeviceInfoLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void RebootTo(string Mode)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
case "MassStorage":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage);
|
||||
break;
|
||||
case "Shutdown":
|
||||
RequestModeSwitch(null);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,17 +67,35 @@ namespace WPinternals
|
||||
|
||||
LogFile.Log("IMEI: " + IMEI);
|
||||
PublicID = CurrentModel.ExecuteJsonMethodAsBytes("ReadPublicId", "PublicId"); // 0x14 bytes: a5 e5 ...
|
||||
LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " "));
|
||||
if (PublicID != null)
|
||||
{
|
||||
LogFile.Log("Public ID: " + Converter.ConvertHexToString(PublicID, " "));
|
||||
}
|
||||
BluetoothMac = CurrentModel.ExecuteJsonMethodAsBytes("ReadBtId", "BtId"); // 6 bytes: bc c6 ...
|
||||
LogFile.Log("Bluetooth MAC: " + Converter.ConvertHexToString(BluetoothMac, " "));
|
||||
if (BluetoothMac != null)
|
||||
{
|
||||
LogFile.Log("Bluetooth MAC: " + Converter.ConvertHexToString(BluetoothMac, " "));
|
||||
}
|
||||
WlanMac1 = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress1"); // 6 bytes
|
||||
LogFile.Log("WLAN MAC 1: " + Converter.ConvertHexToString(WlanMac1, " "));
|
||||
if (WlanMac1 != null)
|
||||
{
|
||||
LogFile.Log("WLAN MAC 1: " + Converter.ConvertHexToString(WlanMac1, " "));
|
||||
}
|
||||
WlanMac2 = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress2"); // 6 bytes
|
||||
LogFile.Log("WLAN MAC 2: " + Converter.ConvertHexToString(WlanMac2, " "));
|
||||
if (WlanMac2 != null)
|
||||
{
|
||||
LogFile.Log("WLAN MAC 2: " + Converter.ConvertHexToString(WlanMac2, " "));
|
||||
}
|
||||
WlanMac3 = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress3"); // 6 bytes
|
||||
LogFile.Log("WLAN MAC 3: " + Converter.ConvertHexToString(WlanMac3, " "));
|
||||
if (WlanMac3 != null)
|
||||
{
|
||||
LogFile.Log("WLAN MAC 3: " + Converter.ConvertHexToString(WlanMac3, " "));
|
||||
}
|
||||
WlanMac4 = CurrentModel.ExecuteJsonMethodAsBytes("ReadWlanMacAddress", "WlanMacAddress4"); // 6 bytes
|
||||
LogFile.Log("WLAN MAC 4: " + Converter.ConvertHexToString(WlanMac4, " "));
|
||||
if (WlanMac4 != null)
|
||||
{
|
||||
LogFile.Log("WLAN MAC 4: " + Converter.ConvertHexToString(WlanMac4, " "));
|
||||
}
|
||||
|
||||
bool? ProductionDone = CurrentModel.ExecuteJsonMethodAsBoolean("ReadProductionDoneState", "ProductionDone");
|
||||
IsBootloaderSecurityEnabled = ProductionDone == null
|
||||
@@ -105,7 +123,10 @@ namespace WPinternals
|
||||
this.Pk = Pk;
|
||||
LogFile.Log("PK: " + Pk);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
private string _ProductCode = null;
|
||||
@@ -381,6 +402,12 @@ namespace WPinternals
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "PhoneInfo":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_PhoneInfo);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
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 NokiaPhoneInfoViewModel : ContextViewModel
|
||||
{
|
||||
private readonly LumiaPhoneInfoAppModel CurrentModel;
|
||||
private readonly Action<PhoneInterfaces> RequestModeSwitch;
|
||||
internal Action SwitchToGettingStarted;
|
||||
private readonly object LockDeviceInfo = new();
|
||||
private bool DeviceInfoLoaded = false;
|
||||
|
||||
internal NokiaPhoneInfoViewModel(NokiaPhoneModel CurrentModel, Action<PhoneInterfaces> RequestModeSwitch, Action SwitchToGettingStarted)
|
||||
: base()
|
||||
{
|
||||
this.CurrentModel = (LumiaPhoneInfoAppModel)CurrentModel;
|
||||
this.RequestModeSwitch = RequestModeSwitch;
|
||||
this.SwitchToGettingStarted = SwitchToGettingStarted;
|
||||
}
|
||||
|
||||
// Device info should be loaded only one time and only when the ViewModel is active
|
||||
internal override void EvaluateViewState()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
new Thread(() => StartLoadDeviceInfo()).Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartLoadDeviceInfo()
|
||||
{
|
||||
lock (LockDeviceInfo)
|
||||
{
|
||||
if (!DeviceInfoLoaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
* Version: 1.1.1.3
|
||||
* TYPE: RM-885
|
||||
* BTR: 059R0M0
|
||||
* LPSN: ...
|
||||
* HWID: 1000
|
||||
* CTR: 059S4B1
|
||||
* MC: 0205354
|
||||
* IMEI: ...
|
||||
*/
|
||||
string PhoneInfoData = CurrentModel.GetPhoneInfo();
|
||||
if (!string.IsNullOrEmpty(PhoneInfoData))
|
||||
{
|
||||
string[] Variables = PhoneInfoData.Split("\n");
|
||||
Dictionary<string, string> FormattedVariables = [];
|
||||
foreach (string Variable in Variables)
|
||||
{
|
||||
if (!Variable.Contains(":"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FormattedVariables.Add(Variable.Split(":")[0].Trim(), Variable.Split(":")[1].Trim());
|
||||
}
|
||||
|
||||
HWID = FormattedVariables["HWID"];
|
||||
LogFile.Log("HWID: " + HWID);
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppPhoneInfo Info = CurrentModel.ReadPhoneInfo(true);
|
||||
BootloaderDescription = Info.PhoneInfoAppVersionMajor < 2 ? "Lumia Bootloader Spec A" : "Lumia Bootloader Spec B";
|
||||
|
||||
LogFile.Log("Bootloader: " + BootloaderDescription);
|
||||
|
||||
ProductCode = Info.ProductCode;
|
||||
LogFile.Log("ProductCode: " + ProductCode);
|
||||
|
||||
ProductType = Info.Type;
|
||||
LogFile.Log("ProductType: " + ProductType);
|
||||
|
||||
IMEI = Info.Imei;
|
||||
LogFile.Log("IMEI: " + ProductType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogFile.Log("Reading status from Flash interface was aborted.");
|
||||
}
|
||||
DeviceInfoLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _BootloaderDescription = null;
|
||||
public string BootloaderDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return _BootloaderDescription;
|
||||
}
|
||||
set
|
||||
{
|
||||
_BootloaderDescription = value;
|
||||
OnPropertyChanged(nameof(BootloaderDescription));
|
||||
}
|
||||
}
|
||||
|
||||
private string _HWID = null;
|
||||
public string HWID
|
||||
{
|
||||
get
|
||||
{
|
||||
return _HWID;
|
||||
}
|
||||
set
|
||||
{
|
||||
_HWID = value;
|
||||
OnPropertyChanged(nameof(HWID));
|
||||
}
|
||||
}
|
||||
|
||||
private string _IMEI = null;
|
||||
public string IMEI
|
||||
{
|
||||
get
|
||||
{
|
||||
return _IMEI;
|
||||
}
|
||||
set
|
||||
{
|
||||
_IMEI = value;
|
||||
OnPropertyChanged(nameof(IMEI));
|
||||
}
|
||||
}
|
||||
|
||||
internal void RebootTo(string Mode)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case "Normal":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Normal);
|
||||
break;
|
||||
case "Flash":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Flash);
|
||||
break;
|
||||
case "BootMgr":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Bootloader);
|
||||
break;
|
||||
case "Label":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_Label);
|
||||
break;
|
||||
case "MassStorage":
|
||||
RequestModeSwitch(PhoneInterfaces.Lumia_MassStorage);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,10 @@ namespace WPinternals
|
||||
LogWatcher.Enabled = true;
|
||||
App.IsPnPEventLogMissing = false;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
private void PnPEventWritten(Object obj, EventRecordWrittenEventArgs arg)
|
||||
@@ -234,13 +237,12 @@ namespace WPinternals
|
||||
e.DevicePath.Contains("&PID_0A02", StringComparison.OrdinalIgnoreCase) || // VID_045E&PID_0A02 is for Lumia 950
|
||||
e.DevicePath.Contains("&PID_05EE", StringComparison.OrdinalIgnoreCase)) // VID_0421&PID_05EE is for early RX100
|
||||
{
|
||||
CurrentModel = new NokiaFlashModel(e.DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
FlashAppType type = FlashAppType.FlashApp;
|
||||
try
|
||||
{
|
||||
type = ((NokiaFlashModel)CurrentModel).GetFlashAppType();
|
||||
NokiaFlashModel tmpModel = new NokiaFlashModel(e.DevicePath);
|
||||
type = tmpModel.GetFlashAppType();
|
||||
tmpModel.Dispose();
|
||||
LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly);
|
||||
}
|
||||
catch
|
||||
@@ -252,6 +254,9 @@ namespace WPinternals
|
||||
{
|
||||
case FlashAppType.BootManager:
|
||||
{
|
||||
CurrentModel = new LumiaBootManagerAppModel(e.DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Bootloader;
|
||||
LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly);
|
||||
LogFile.Log("Device path: " + e.DevicePath, LogType.FileOnly);
|
||||
@@ -262,6 +267,9 @@ namespace WPinternals
|
||||
}
|
||||
case FlashAppType.FlashApp:
|
||||
{
|
||||
CurrentModel = new LumiaFlashAppModel(e.DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Flash;
|
||||
LogFile.Log("Found device on interface: " + ((USBNotifier)sender).Guid.ToString(), LogType.FileOnly);
|
||||
@@ -273,7 +281,11 @@ namespace WPinternals
|
||||
}
|
||||
case FlashAppType.PhoneInfoApp:
|
||||
{
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Bootloader;
|
||||
CurrentModel = new LumiaPhoneInfoAppModel(e.DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
CurrentInterface = PhoneInterfaces.Lumia_PhoneInfo;
|
||||
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);
|
||||
@@ -411,9 +423,80 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
private void InterfaceChanged(PhoneInterfaces NewInterface)
|
||||
private void InterfaceChanged(PhoneInterfaces NewInterface, string DevicePath)
|
||||
{
|
||||
CurrentInterface = NewInterface;
|
||||
LastInterface = CurrentInterface;
|
||||
|
||||
CurrentInterface = null;
|
||||
if (CurrentModel != null)
|
||||
{
|
||||
CurrentModel.Dispose();
|
||||
CurrentModel = null;
|
||||
LogFile.Log("Lumia disconnected", LogType.FileAndConsole);
|
||||
}
|
||||
|
||||
DeviceRemoved();
|
||||
|
||||
switch (NewInterface)
|
||||
{
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
{
|
||||
CurrentModel = new LumiaBootManagerAppModel(DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Bootloader;
|
||||
LogFile.Log("Found device on interface: " + LumiaFlashInterfaceGuid.ToString(), LogType.FileOnly);
|
||||
LogFile.Log("Device path: " + DevicePath, LogType.FileOnly);
|
||||
LogFile.Log("Connected device: Lumia", LogType.FileAndConsole);
|
||||
LogFile.Log("Mode: Bootloader", LogType.FileAndConsole);
|
||||
NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel));
|
||||
break;
|
||||
}
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
{
|
||||
CurrentModel = new LumiaFlashAppModel(DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Flash;
|
||||
LogFile.Log("Found device on interface: " + LumiaFlashInterfaceGuid.ToString(), LogType.FileOnly);
|
||||
LogFile.Log("Device path: " + DevicePath, LogType.FileOnly);
|
||||
LogFile.Log("Connected device: Lumia", LogType.FileAndConsole);
|
||||
LogFile.Log("Mode: Flash", LogType.FileAndConsole);
|
||||
NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel));
|
||||
break;
|
||||
}
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
{
|
||||
CurrentModel = new LumiaPhoneInfoAppModel(DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
CurrentInterface = PhoneInterfaces.Lumia_PhoneInfo;
|
||||
LogFile.Log("Found device on interface: " + LumiaFlashInterfaceGuid.ToString(), LogType.FileOnly);
|
||||
LogFile.Log("Device path: " + DevicePath, LogType.FileOnly);
|
||||
LogFile.Log("Connected device: Lumia", LogType.FileAndConsole);
|
||||
LogFile.Log("Mode: Bootloader (Phone Info)", LogType.FileAndConsole);
|
||||
NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LogFile.Log("Flash App Type could not be determined, assuming FlashApp", LogType.FileOnly);
|
||||
|
||||
CurrentModel = new LumiaFlashAppModel(DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
CurrentInterface = PhoneInterfaces.Lumia_Flash;
|
||||
LogFile.Log("Found device on interface: " + LumiaFlashInterfaceGuid.ToString(), LogType.FileOnly);
|
||||
LogFile.Log("Device path: " + DevicePath, LogType.FileOnly);
|
||||
LogFile.Log("Connected device: Lumia", LogType.FileAndConsole);
|
||||
LogFile.Log("Mode: Flash", LogType.FileAndConsole);
|
||||
NewDeviceArrived(new ArrivalEventArgs((PhoneInterfaces)CurrentInterface, CurrentModel));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LumiaNotifier_Removal(object sender, USBEvent e)
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace WPinternals
|
||||
Result = false;
|
||||
}
|
||||
|
||||
NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppModel Phone = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
BusyViewModel Busy = new("Restoring...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext);
|
||||
ProgressUpdater Updater = Busy.ProgressUpdater;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Policy;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -82,7 +83,7 @@ namespace WPinternals
|
||||
{
|
||||
if ((PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash))
|
||||
{
|
||||
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false);
|
||||
LumiaBootManagerPhoneInfo Info = ((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false);
|
||||
if (Info.BootManagerProtocolVersionMajor >= 2)
|
||||
{
|
||||
try
|
||||
@@ -95,13 +96,16 @@ namespace WPinternals
|
||||
// It does not disconnect / reconnect anymore and the apptype is changed immediately
|
||||
// NOKS still doesnt return a status
|
||||
// BootMgr v1 uses normal NOKS and waits for arrival of FlashApp
|
||||
((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
|
||||
// But this was called as a real switch, so we will raise an arrival event.
|
||||
PhoneNotifier.CurrentInterface = PhoneInterfaces.Lumia_Flash;
|
||||
PhoneNotifier.NotifyArrival();
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +234,12 @@ namespace WPinternals
|
||||
{
|
||||
IsSwitching = true;
|
||||
|
||||
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
|
||||
byte[] RebootCommandResult;
|
||||
|
||||
bool ModernFlashApp;
|
||||
|
||||
// Make switch and set message or navigate to error
|
||||
switch (CurrentMode)
|
||||
{
|
||||
@@ -284,7 +294,7 @@ namespace WPinternals
|
||||
Params.Add("ResetMethod", "HwReset");
|
||||
try
|
||||
{
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteJsonMethodAsync("SetDeviceMode", Params);
|
||||
((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteJsonMethodAsync("SetDeviceMode", Params);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
}
|
||||
catch (Exception Ex)
|
||||
@@ -295,15 +305,11 @@ namespace WPinternals
|
||||
}
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
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
|
||||
byte[] RebootCommandResult;
|
||||
IsSwitchingInterface = true;
|
||||
switch (TargetMode)
|
||||
{
|
||||
case null:
|
||||
((NokiaFlashModel)CurrentModel).Shutdown();
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).Shutdown();
|
||||
ModeSwitchProgressWrapper("Please disconnect your device. Waiting...", null);
|
||||
LogFile.Log("Please disconnect your device. Waiting...", LogType.FileAndConsole);
|
||||
new Thread(() =>
|
||||
@@ -313,24 +319,38 @@ namespace WPinternals
|
||||
}).Start();
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Normal:
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
||||
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModernFlashApp = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Phone Info mode...", null);
|
||||
LogFile.Log("Rebooting phone to Phone Info mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
SwitchFromFlashToLabelMode();
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash: // attempt to boot from limited flash to full flash
|
||||
byte[] RebootToFlashCommand = [0x4E, 0x4F, 0x4B, 0x53]; // NOKS
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootToFlashCommand);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
byte[] RebootToFlashCommand = [0x4E, 0x4F, 0x4B, 0x53]; // NOKS
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootToFlashCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
||||
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
|
||||
break;
|
||||
@@ -338,8 +358,136 @@ namespace WPinternals
|
||||
SwitchFromFlashToMassStorageMode();
|
||||
break;
|
||||
case PhoneInterfaces.Qualcomm_Download:
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE
|
||||
RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE // TODO
|
||||
RebootCommandResult = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
|
||||
{
|
||||
IsSwitchingInterface = false;
|
||||
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Qualcomm Download mode...", null);
|
||||
LogFile.Log("Rebooting phone to Qualcomm Download mode", LogType.FileAndConsole);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
IsSwitchingInterface = true;
|
||||
switch (TargetMode)
|
||||
{
|
||||
case PhoneInterfaces.Lumia_Normal:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToBootManagerContext();
|
||||
}
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
||||
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo: // attempt to boot from limited phone info to full phone info
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Phone Info mode...", null);
|
||||
LogFile.Log("Rebooting phone to Phone Info mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
SwitchFromPhoneInfoToLabelMode();
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModernFlashApp = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
||||
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_MassStorage:
|
||||
SwitchFromPhoneInfoToMassStorageMode();
|
||||
break;
|
||||
case PhoneInterfaces.Qualcomm_Download:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE // TODO
|
||||
RebootCommandResult = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
|
||||
{
|
||||
IsSwitchingInterface = false;
|
||||
ModeSwitchErrorWrapper("Failed to switch to Qualcomm Download mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Qualcomm Download mode...", null);
|
||||
LogFile.Log("Rebooting phone to Qualcomm Download mode", LogType.FileAndConsole);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
IsSwitchingInterface = true;
|
||||
switch (TargetMode)
|
||||
{
|
||||
case null:
|
||||
((LumiaBootManagerAppModel)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;
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Bootloader mode...", null);
|
||||
LogFile.Log("Rebooting phone to Bootloader mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
SwitchFromFlashToLabelMode();
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash: // attempt to boot from limited flash to full flash
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
byte[] RebootToFlashCommand = [0x4E, 0x4F, 0x4B, 0x53]; // NOKS
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootToFlashCommand);
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
||||
LogFile.Log("Rebooting phone to Flash mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_MassStorage:
|
||||
SwitchFromFlashToMassStorageMode();
|
||||
break;
|
||||
case PhoneInterfaces.Qualcomm_Download:
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE // TODO
|
||||
RebootCommandResult = ((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
if (RebootCommandResult?.Length == 4) // This means fail: NOKU (unknow command)
|
||||
{
|
||||
IsSwitchingInterface = false;
|
||||
@@ -347,7 +495,6 @@ namespace WPinternals
|
||||
}
|
||||
else
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Qualcomm Download mode...", null);
|
||||
LogFile.Log("Rebooting phone to Qualcomm Download mode", LogType.FileAndConsole);
|
||||
}
|
||||
@@ -361,26 +508,26 @@ namespace WPinternals
|
||||
switch (TargetMode)
|
||||
{
|
||||
case PhoneInterfaces.Lumia_Normal:
|
||||
((MassStorage)CurrentModel).Reboot();
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((MassStorage)PhoneNotifier.CurrentModel).Reboot();
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Normal mode...", null);
|
||||
LogFile.Log("Rebooting phone to Normal mode", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
((MassStorage)CurrentModel).Reboot();
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
||||
((MassStorage)PhoneNotifier.CurrentModel).Reboot();
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode...", null);
|
||||
LogFile.Log("Rebooting phone to Label mode...", LogType.FileAndConsole);
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
((MassStorage)CurrentModel).Reboot();
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
||||
((MassStorage)PhoneNotifier.CurrentModel).Reboot();
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Flash mode...", null);
|
||||
LogFile.Log("Rebooting phone to Flash mode...", LogType.FileAndConsole);
|
||||
break;
|
||||
case null:
|
||||
((MassStorage)CurrentModel).Reboot();
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrivedFromMassStorageMode;
|
||||
((MassStorage)PhoneNotifier.CurrentModel).Reboot();
|
||||
ModeSwitchProgressWrapper("First rebooting phone to Flash mode...", null);
|
||||
LogFile.Log("First rebooting phone to Bootloader mode...", LogType.FileAndConsole);
|
||||
break;
|
||||
@@ -420,6 +567,12 @@ namespace WPinternals
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Boot Manager mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Phone Info mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
||||
break;
|
||||
@@ -440,6 +593,12 @@ namespace WPinternals
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Boot Manager mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Phone Info mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
||||
break;
|
||||
@@ -468,18 +627,21 @@ namespace WPinternals
|
||||
// SwitchToFlashAppContext() will only switch context. Phone will not charge.
|
||||
// ResetPhoneToFlashMode() reboots to real flash app. Phone will charge. Works when in BootMgrApp, not when already in FlashApp.
|
||||
|
||||
((NokiaFlashModel)CurrentModel).ResetPhoneToFlashMode();
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).ResetPhoneToFlashMode();
|
||||
CurrentMode = PhoneInterfaces.Lumia_Flash;
|
||||
PhoneNotifier.NotifyArrival();
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentMode == TargetMode)
|
||||
{
|
||||
if (TargetMode == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
((NokiaFlashModel)CurrentModel).DisableRebootTimeOut();
|
||||
((NokiaFlashModel)PhoneNotifier.CurrentModel).DisableRebootTimeOut();
|
||||
}
|
||||
|
||||
ModeSwitchSuccessWrapper();
|
||||
@@ -505,10 +667,10 @@ namespace WPinternals
|
||||
else if ((CurrentMode == PhoneInterfaces.Lumia_Flash) && (TargetMode == PhoneInterfaces.Qualcomm_Download))
|
||||
{
|
||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE
|
||||
byte[] RebootToQualcommDownloadCommand = [0x4E, 0x4F, 0x4B, 0x58, 0x43, 0x42, 0x45]; // NOKXCBE // TODO
|
||||
IsSwitchingInterface = true;
|
||||
LogFile.Log("Sending command for rebooting to Emergency Download mode");
|
||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
byte[] RebootCommandResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(RebootToQualcommDownloadCommand);
|
||||
if (RebootCommandResult?.Length >= 8)
|
||||
{
|
||||
int ResultCode = (RebootCommandResult[6] << 8) + RebootCommandResult[7];
|
||||
@@ -536,6 +698,12 @@ namespace WPinternals
|
||||
case PhoneInterfaces.Lumia_Flash:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Flash mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Bootloader:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Boot Manager mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_PhoneInfo:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Phone Info mode");
|
||||
break;
|
||||
case PhoneInterfaces.Lumia_Label:
|
||||
ModeSwitchErrorWrapper("Failed to switch to Label mode");
|
||||
break;
|
||||
@@ -546,104 +714,485 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchFromFlashToLabelMode(bool Continuation = false)
|
||||
private void SwitchFromPhoneInfoToLabelMode(bool Continuation = false)
|
||||
{
|
||||
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
|
||||
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
}
|
||||
catch { }
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
||||
|
||||
if (Info.MmosOverUsbSupported)
|
||||
string ProgressText = Continuation ? "And now preparing to boot the phone to Label mode..." : "Preparing to boot the phone to Label mode...";
|
||||
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfoAppInfo = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||
|
||||
bool ModernFlashApp = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
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();
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
ModeSwitchProgressWrapper("Rebooting phone to Label mode", null);
|
||||
LogFile.Log("Rebooting phone to Label mode", LogType.FileAndConsole);
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
void Finish()
|
||||
{
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: true);
|
||||
|
||||
if (Info.MmosOverUsbSupported)
|
||||
{
|
||||
LogFile.BeginAction("SwitchToLabelMode");
|
||||
|
||||
try
|
||||
{
|
||||
ModeSwitchProgressWrapper(ProgressText, null);
|
||||
|
||||
string TempFolder = $@"{Environment.GetEnvironmentVariable("TEMP")}\WPInternals";
|
||||
|
||||
if (PhoneInfoAppInfo.Type == "RM-1152")
|
||||
{
|
||||
PhoneInfoAppInfo.Type = "RM-1151";
|
||||
}
|
||||
|
||||
(string ENOSWFileUrl, string DPLFileUrl) = LumiaDownloadModel.SearchENOSW(PhoneInfoAppInfo.Type, Info.Firmware);
|
||||
|
||||
UIContext?.Post(d => SetWorkingStatus($"Downloading {PhoneInfoAppInfo.Type} Test Mode package...", MaxProgressValue: 100), null);
|
||||
|
||||
DownloadEntry downloadEntry = new(ENOSWFileUrl, TempFolder, [ENOSWFileUrl], ENOSWDownloadCompleted, Info.Firmware);
|
||||
|
||||
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);
|
||||
UIContext?.Post(d => UpdateWorkingStatus(null, CurrentProgressValue: progressret), null);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
LogFile.LogException(Ex);
|
||||
ModeSwitchErrorWrapper(Ex.Message);
|
||||
}
|
||||
|
||||
LogFile.EndAction("SwitchToLabelMode");
|
||||
}
|
||||
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)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);
|
||||
}
|
||||
}
|
||||
|
||||
UIContext?.Post(d => Finish(), null);
|
||||
});
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaFlashAppPhoneInfo Info = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: true);
|
||||
|
||||
bool ModernFlashApp = ((LumiaFlashAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().FlashAppProtocolVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaFlashAppModel)PhoneNotifier.CurrentModel).SwitchToPhoneInfoAppContextLegacy();
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_PhoneInfo)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaPhoneInfoAppModel LumiaPhoneInfoAppModel = (LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaPhoneInfoAppPhoneInfo PhoneInfoAppInfo = LumiaPhoneInfoAppModel.ReadPhoneInfo(ExtendedInfo: true);
|
||||
|
||||
ModernFlashApp = PhoneInfoAppInfo.PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
LumiaPhoneInfoAppModel.SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
LumiaPhoneInfoAppModel.ContinueBoot();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
}
|
||||
|
||||
void Finish()
|
||||
{
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash)
|
||||
{
|
||||
throw new WPinternalsException("Unexpected Mode");
|
||||
}
|
||||
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
if (Info.MmosOverUsbSupported)
|
||||
{
|
||||
LogFile.BeginAction("SwitchToLabelMode");
|
||||
|
||||
try
|
||||
{
|
||||
ModeSwitchProgressWrapper(ProgressText, null);
|
||||
|
||||
string TempFolder = $@"{Environment.GetEnvironmentVariable("TEMP")}\WPInternals";
|
||||
|
||||
if (PhoneInfoAppInfo.Type == "RM-1152")
|
||||
{
|
||||
PhoneInfoAppInfo.Type = "RM-1151";
|
||||
}
|
||||
|
||||
(string ENOSWFileUrl, string DPLFileUrl) = LumiaDownloadModel.SearchENOSW(PhoneInfoAppInfo.Type, Info.Firmware);
|
||||
|
||||
UIContext?.Post(d => SetWorkingStatus($"Downloading {PhoneInfoAppInfo.Type} Test Mode package...", MaxProgressValue: 100), null);
|
||||
|
||||
DownloadEntry downloadEntry = new(ENOSWFileUrl, TempFolder, [ENOSWFileUrl], ENOSWDownloadCompleted, Info.Firmware);
|
||||
|
||||
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);
|
||||
UIContext?.Post(d => UpdateWorkingStatus(null, CurrentProgressValue: progressret), null);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
LogFile.LogException(Ex);
|
||||
ModeSwitchErrorWrapper(Ex.Message);
|
||||
}
|
||||
|
||||
LogFile.EndAction("SwitchToLabelMode");
|
||||
}
|
||||
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)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);
|
||||
}
|
||||
}
|
||||
|
||||
UIContext?.Post(d => Finish(), null);
|
||||
});
|
||||
}
|
||||
|
||||
private void ENOSWDownloadCompleted(string[] URLs, object State)
|
||||
{
|
||||
string Firmware = (string)State;
|
||||
string ENOSWFileUrl = URLs[0];
|
||||
string Name = DownloadsViewModel.GetFileNameFromURL(ENOSWFileUrl);
|
||||
string TempFolder = $@"{Environment.GetEnvironmentVariable("TEMP")}\WPInternals";
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
ModeSwitchProgressWrapper("Initializing Flash...", null);
|
||||
|
||||
string MMOSPath = Path.Combine(TempFolder, Name);
|
||||
|
||||
App.Config.AddSecWimToRepository(MMOSPath, Firmware);
|
||||
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
|
||||
FileInfo info = new(MMOSPath);
|
||||
uint length = uint.Parse(info.Length.ToString());
|
||||
|
||||
int maximumBufferSize = (int)Info.WriteBufferSize;
|
||||
|
||||
uint chunkCount = (uint)Math.Truncate((decimal)length / maximumBufferSize);
|
||||
|
||||
UIContext?.Post(d => SetWorkingStatus("Flashing Test Mode package...", MaxProgressValue: 100), null);
|
||||
|
||||
ProgressUpdater progressUpdater = new(chunkCount + 1, (int i, TimeSpan? time) => UpdateWorkingStatus(null, CurrentProgressValue: (ulong)i));
|
||||
|
||||
FlashModel.FlashMMOS(MMOSPath, progressUpdater);
|
||||
|
||||
ModeSwitchProgressWrapper("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.");
|
||||
});
|
||||
}
|
||||
|
||||
private void SwitchFromPhoneInfoToMassStorageMode(bool Continuation = false)
|
||||
{
|
||||
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
|
||||
|
||||
new Thread(async () =>
|
||||
{
|
||||
bool ModernFlashApp = ((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ReadPhoneInfo().PhoneInfoAppVersionMajor >= 2;
|
||||
if (ModernFlashApp)
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
((LumiaPhoneInfoAppModel)PhoneNotifier.CurrentModel).ContinueBoot();
|
||||
}
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo 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;
|
||||
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)
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
|
||||
((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModeSwitchErrorWrapper("Failed to switch to Mass Storage mode");
|
||||
IsSwitchingInterface = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
|
||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||
}
|
||||
}
|
||||
else if (IsUnlockedNew)
|
||||
{
|
||||
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)
|
||||
{
|
||||
string ProgressText = Continuation ? "And now rebooting phone to Mass Storage mode..." : "Rebooting phone to Mass Storage mode...";
|
||||
NokiaFlashModel FlashModel = (NokiaFlashModel)CurrentModel;
|
||||
if (CurrentMode == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
try
|
||||
{
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
((LumiaBootManagerAppModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFile.LogException(ex, LogType.FileOnly);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||
LumiaFlashAppModel FlashModel = (LumiaFlashAppModel)PhoneNotifier.CurrentModel;
|
||||
LumiaFlashAppPhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||
|
||||
MassStorageWarning = null;
|
||||
if (Info.FlashAppProtocolVersionMajor < 2)
|
||||
@@ -675,16 +1224,17 @@ namespace WPinternals
|
||||
byte[] RebootCommand = [0x4E, 0x4F, 0x4B, 0x52];
|
||||
byte[] RebootToMassStorageCommand = [0x4E, 0x4F, 0x4B, 0x4D]; // NOKM
|
||||
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)
|
||||
{
|
||||
BootModeFlagCommand[0x0F] = 0x4D;
|
||||
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||
byte[] BootFlagResult = ((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||
UInt16 ResultCode = BitConverter.ToUInt16(BootFlagResult, 6);
|
||||
if (ResultCode == 0)
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
((NokiaPhoneModel)CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
|
||||
((NokiaPhoneModel)PhoneNotifier.CurrentModel).ExecuteRawVoidMethod(RebootCommand);
|
||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||
}
|
||||
@@ -697,6 +1247,7 @@ namespace WPinternals
|
||||
else
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived += NewDeviceArrived;
|
||||
|
||||
ModeSwitchProgressWrapper(ProgressText, MassStorageWarning);
|
||||
LogFile.Log("Rebooting phone to Mass Storage mode");
|
||||
}
|
||||
|
||||
@@ -159,13 +159,16 @@ DEALINGS IN THE SOFTWARE.
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Column="0" Grid.Row="0">Producttype</TextBlock>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1">Productcode</TextBlock>
|
||||
<TextBlock Grid.Column="0" Grid.Row="2">Operatorcode</TextBlock>
|
||||
<TextBlock Grid.Column="0" Grid.Row="3">Firmwareversion</TextBlock>
|
||||
<TextBox Grid.Column="1" Grid.Row="0" Width="Auto" Margin="0,0,0,8" Text="{Binding ProductType, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="1" Width="Auto" Margin="0,0,0,8" Text="{Binding ProductCode, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="2" Width="Auto" Text="{Binding OperatorCode, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="2" Width="Auto" Margin="0,0,0,8" Text="{Binding OperatorCode, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="1" Grid.Row="3" Width="Auto" Text="{Binding FirmwareVersion, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
<StackPanel Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||
<Button Content="Search" Padding="0,5" Width="120" Margin="0,0,20,0" Command="{Binding Path=SearchCommand, Mode=OneWay}" IsDefault="True"/>
|
||||
|
||||
@@ -37,6 +37,9 @@ DEALINGS IN THE SOFTWARE.
|
||||
<DataTemplate DataType="{x:Type local:NokiaBootloaderViewModel}">
|
||||
<local:NokiaBootloaderView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type local:NokiaPhoneInfoViewModel}">
|
||||
<local:NokiaPhoneInfoView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type local:NokiaFlashViewModel}">
|
||||
<local:NokiaFlashView />
|
||||
</DataTemplate>
|
||||
@@ -58,6 +61,9 @@ DEALINGS IN THE SOFTWARE.
|
||||
<DataTemplate DataType="{x:Type local:NokiaModeBootloaderViewModel}">
|
||||
<local:NokiaModeBootloaderView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type local:NokiaModePhoneInfoViewModel}">
|
||||
<local:NokiaModePhoneInfoView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type local:NokiaModeLabelViewModel}">
|
||||
<local:NokiaModeLabelView />
|
||||
</DataTemplate>
|
||||
|
||||
@@ -99,9 +99,38 @@ DEALINGS IN THE SOFTWARE.
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25" Margin="0,0,0,20">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<local:GifImage x:Name="GifImage" Stretch="None"/>
|
||||
<Label Content="Phone is booting..." FontSize="20" Margin="10,0,0,0" VerticalContentAlignment="Center"/>
|
||||
<StackPanel>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<local:GifImage x:Name="GifImage" Stretch="None"/>
|
||||
<Label Content="Phone is booting..." FontSize="20" Margin="10,0,0,0" VerticalContentAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Margin="20,0,20,0" VerticalScrollBarVisibility="Auto">
|
||||
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded">
|
||||
<local:Paragraph TextAlignment="Center">
|
||||
<Run Text="When you connect the phone, it can take a moment before it is recognized. If it still isn't recognized after a while, you might need to install the necessary drivers first. For more information about the drivers, read the " />
|
||||
<Hyperlink NavigateUri="Getting started">Getting started</Hyperlink>
|
||||
<Run Text=" section. If the drivers are installed, but the phone is still not recognized, then try to perform a soft-reset, while the USB of the phone is connected. On Lumia phones you have to press-and-hold the power-button and volume-down-button at the same time for at least 10 seconds. If the tool detects the bootloader of the phone it will try to connect to the phone at this early boot-stage." />
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,-20,20,0" VerticalScrollBarVisibility="Auto" Visibility="{Binding InterruptBoot, RelativeSource={RelativeSource AncestorType={x:Type local:NokiaBootloaderView}}, Converter={StaticResource InverseVisibilityConverter}}">
|
||||
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded">
|
||||
<local:Paragraph TextAlignment="Center">
|
||||
<Run Text="You can "/>
|
||||
<Hyperlink NavigateUri="Interrupt boot">interrupt the boot-process</Hyperlink>
|
||||
<Run Text=" as soon as the bootloader is detected. This allows you to configure the phone or flash a ROM before it boots to the OS. You can also try this when the phone is not booting properly. When you unlocked the bootloader and the phone boots to a Blue Screen, you can still enter Mass Storage Mode if you want. To boot properly again, restore the bootloader. You can update to a supported OS version and try again after that."/>
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,-20,20,0" VerticalScrollBarVisibility="Auto" Visibility="{Binding InterruptBoot, RelativeSource={RelativeSource AncestorType={x:Type local:NokiaBootloaderView}}, Converter={StaticResource VisibilityConverter}}">
|
||||
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded">
|
||||
<local:Paragraph TextAlignment="Center">
|
||||
<Run Text="Windows Phone Internals is set to interrupt the boot-process as soon as the bootloader is detected. You can also allow the phone to "/>
|
||||
<Hyperlink NavigateUri="Normal boot">boot normally</Hyperlink>
|
||||
<Run Text="."/>
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25">
|
||||
|
||||
@@ -18,9 +18,13 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
@@ -29,13 +33,41 @@ namespace WPinternals
|
||||
/// </summary>
|
||||
public partial class NokiaBootloaderView : UserControl
|
||||
{
|
||||
private static PhoneNotifierViewModel PhoneNotifier;
|
||||
private static SynchronizationContext UIContext;
|
||||
|
||||
public NokiaBootloaderView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
InterruptBoot = App.InterruptBoot;
|
||||
UIContext = SynchronizationContext.Current;
|
||||
|
||||
// Setting these properties in XAML results in an error. Why?
|
||||
GifImage.GifSource = "/aerobusy.gif";
|
||||
GifImage.AutoStart = true;
|
||||
|
||||
Loaded += NokiaBootloaderView_Loaded;
|
||||
Unloaded += NokiaBootloaderView_Unloaded;
|
||||
}
|
||||
|
||||
private void NokiaBootloaderView_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PhoneNotifier.NewDeviceArrived -= PhoneNotifier_NewDeviceArrived;
|
||||
}
|
||||
|
||||
private void NokiaBootloaderView_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Find the phone notifier
|
||||
DependencyObject obj = (DependencyObject)sender;
|
||||
while (!(obj is MainWindow))
|
||||
{
|
||||
obj = VisualTreeHelper.GetParent(obj);
|
||||
}
|
||||
|
||||
PhoneNotifier = ((MainViewModel)((MainWindow)obj).DataContext).PhoneNotifier;
|
||||
|
||||
PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived;
|
||||
}
|
||||
|
||||
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
|
||||
@@ -43,10 +75,24 @@ namespace WPinternals
|
||||
Hyperlink link = args.Source as Hyperlink;
|
||||
if (link?.NavigateUri != null)
|
||||
{
|
||||
if (link.NavigateUri.ToString() == "GettingStarted")
|
||||
if (link.NavigateUri.ToString() == "Getting started")
|
||||
{
|
||||
(this.DataContext as NokiaBootloaderViewModel)?.SwitchToGettingStarted();
|
||||
} (this.DataContext as NokiaBootloaderViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||
App.NavigateToGettingStarted();
|
||||
}
|
||||
else if (link.NavigateUri.ToString() == "Unlock boot")
|
||||
{
|
||||
App.NavigateToUnlockBoot();
|
||||
}
|
||||
else if (link.NavigateUri.ToString() == "Interrupt boot")
|
||||
{
|
||||
InterruptBoot = true;
|
||||
}
|
||||
else if (link.NavigateUri.ToString() == "Normal boot")
|
||||
{
|
||||
InterruptBoot = false;
|
||||
}
|
||||
|
||||
(this.DataContext as NokiaBootloaderViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,5 +100,41 @@ namespace WPinternals
|
||||
{
|
||||
(sender as FlowDocument)?.AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty InterruptBootProperty =
|
||||
DependencyProperty.Register("InterruptBoot", typeof(Boolean), typeof(NokiaBootloaderView), new FrameworkPropertyMetadata(InterruptBootChanged));
|
||||
public bool InterruptBoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)GetValue(InterruptBootProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(InterruptBootProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void InterruptBootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
App.InterruptBoot = (bool)e.NewValue;
|
||||
|
||||
if ((bool)e.NewValue && PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
App.InterruptBoot = false;
|
||||
LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode.");
|
||||
Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash));
|
||||
}
|
||||
}
|
||||
|
||||
internal void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args)
|
||||
{
|
||||
if (App.InterruptBoot && Args.NewInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
App.InterruptBoot = false;
|
||||
LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode.");
|
||||
Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,16 @@ DEALINGS IN THE SOFTWARE.
|
||||
<Run Text="This will switch back to Windows Phone OS." />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Hyperlink NavigateUri="PhoneInfo">Switch to Phone-Info-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This will switch to Phone Info Mode." />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Hyperlink NavigateUri="BootMgr">Switch to Boot-Manager-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This will switch to Boot Manager Mode." />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Hyperlink NavigateUri="Label">Switch to Label-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This interface is meant for querying and provisioning the phone. This is normally used for configuring the phone during manufacturing." />
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<!--
|
||||
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.NokiaModePhoneInfoView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="700">
|
||||
<UserControl.Resources>
|
||||
<local:BooleanConverter x:Key="VisibilityConverter" OnTrue="Visible" OnFalse="Collapsed" />
|
||||
<local:BooleanConverter x:Key="InvisibilityConverter" OnTrue="Collapsed" OnFalse="Visible" />
|
||||
<local:BooleanConverter x:Key="InverseConverter" OnTrue="False" OnFalse="True" />
|
||||
</UserControl.Resources>
|
||||
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25">
|
||||
<local: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>
|
||||
<local:Paragraph>
|
||||
<Run Text="Nokia Lumia - Switch mode" FontSize="18" FontWeight="Bold" Foreground="#FF3753A6" />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run Text="Current mode: " />
|
||||
<Run Text="Bootloader (Phone Info)" 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="Flash">Switch to Flash-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This is the interface that can be used to flash a new ROM image. It can also be used to retrieve additional info and security status." />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Hyperlink NavigateUri="BootMgr">Switch to Boot-Manager-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This will switch to Boot Manager Mode." />
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Hyperlink NavigateUri="Label">Switch to Label-mode</Hyperlink>
|
||||
<LineBreak />
|
||||
<Run Text="This interface is meant for querying and provisioning the phone. This is normally used for configuring the phone during manufacturing." />
|
||||
<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. " />
|
||||
<local:CollapsibleRun IsVisible="{Binding EffectiveBootloaderSecurityStatus, Mode=OneWay}" Text="Your security flags indicate that this mode is prohibited on this phone."/>
|
||||
<local: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 />
|
||||
<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="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." />
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local: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 NokiaModePhoneInfoView.xaml
|
||||
/// </summary>
|
||||
public partial class NokiaModePhoneInfoView : UserControl
|
||||
{
|
||||
public NokiaModePhoneInfoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
|
||||
{
|
||||
if (args.Source is Hyperlink link)
|
||||
{
|
||||
(this.DataContext as NokiaModePhoneInfoViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void Document_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(sender as FlowDocument)?.AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
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.NokiaPhoneInfoView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="700">
|
||||
<UserControl.Resources>
|
||||
<BitmapImage x:Key="Busy" UriSource="..\aerobusy.gif" />
|
||||
<local:HexConverter x:Key="HexConverter" />
|
||||
<local:BooleanConverter x:Key="VisibilityConverter" OnTrue="Visible" OnFalse="Collapsed" OnNull="Collapsed"/>
|
||||
<local:BooleanConverter x:Key="InverseVisibilityConverter" OnTrue="Collapsed" OnFalse="Visible" OnNull="Collapsed" />
|
||||
<local:ObjectToVisibilityConverter x:Key="ObjectToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25" Margin="0,0,0,20">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0" VerticalScrollBarVisibility="Auto">
|
||||
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||
<local: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 Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Operating mode" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Bootloader (Phone Info)" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Product Type" Visibility="{Binding Path=ProductType, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding ProductType}" Visibility="{Binding Path=ProductType, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Product Code" Visibility="{Binding Path=ProductCode, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding ProductCode}" Visibility="{Binding Path=ProductCode, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Hardware version" Visibility="{Binding Path=HWID, Converter={StaticResource ObjectToVisibilityConverter}}"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding Path=HWID}" Visibility="{Binding Path=HWID, Converter={StaticResource ObjectToVisibilityConverter}}" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Bootloader" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" FontWeight="Bold" Foreground="#FF3753A6" TextWrapping="Wrap" Text="{Binding BootloaderDescription}"/>
|
||||
</Grid>
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" Margin="20,0" VerticalScrollBarVisibility="Auto">
|
||||
<FlowDocument FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||
<local:Paragraph>
|
||||
<LineBreak />
|
||||
<Run Text="To let the phone go back to Windows, boot to " />
|
||||
<Hyperlink NavigateUri="Normal">Normal</Hyperlink>
|
||||
<Run Text=" mode." />
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border BorderThickness="1" BorderBrush="#FFD4D4D4" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="25">
|
||||
<Expander Header="Phone identity" HorizontalContentAlignment="Stretch" Template="{DynamicResource TopicExpanderTemplate}" Margin="20,0">
|
||||
<local:FlowDocumentScrollViewerNoMouseWheel Grid.Column="1" VerticalScrollBarVisibility="Auto" >
|
||||
<FlowDocument x:Name="Document" FontFamily="Segoe UI" FontSize="12" Loaded="Document_Loaded" PagePadding="1">
|
||||
<local:Paragraph>
|
||||
<LineBreak />
|
||||
<Grid IsHitTestVisible="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="IMEI" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=IMEI}" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</local:Paragraph>
|
||||
</FlowDocument>
|
||||
</local:FlowDocumentScrollViewerNoMouseWheel>
|
||||
</Expander>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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 NokiaPhoneInfoView.xaml
|
||||
/// </summary>
|
||||
public partial class NokiaPhoneInfoView : UserControl
|
||||
{
|
||||
public NokiaPhoneInfoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
|
||||
{
|
||||
Hyperlink link = args.Source as Hyperlink;
|
||||
if (link?.NavigateUri != null)
|
||||
{
|
||||
if (link.NavigateUri.ToString() == "GettingStarted")
|
||||
{
|
||||
(this.DataContext as NokiaPhoneInfoViewModel)?.SwitchToGettingStarted();
|
||||
} (this.DataContext as NokiaPhoneInfoViewModel)?.RebootTo(link.NavigateUri.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void Document_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
(sender as FlowDocument)?.AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(HandleHyperlinkClick));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
|
||||
<PackageReference Include="System.Management" Version="8.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="DiscUtils\DiscUtils.Core\CoreCompat\" />
|
||||
|
||||
@@ -114,4 +114,9 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Preview-Test|AnyCPU'">
|
||||
<StartArguments>/Test</StartArguments>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\NokiaModePhoneInfoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -36,7 +36,7 @@ namespace WPinternals
|
||||
internal const bool IsPrerelease = false;
|
||||
#endif
|
||||
|
||||
internal static readonly DateTime ExpirationDate = new(2023, 12, 21);
|
||||
internal static readonly DateTime ExpirationDate = new(2024, 12, 21);
|
||||
|
||||
internal static void CheckExpiration()
|
||||
{
|
||||
@@ -220,6 +220,52 @@ namespace WPinternals
|
||||
|
||||
public List<FFUEntry> FFURepository = new();
|
||||
|
||||
internal void AddSecWimToRepository(string SecWimPath, string FirmwareVersion)
|
||||
{
|
||||
SecWimEntry Entry = SecWimRepository.Find(e => (e.FirmwareVersion == FirmwareVersion) && string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase));
|
||||
if (Entry == null)
|
||||
{
|
||||
LogFile.Log("Adding Secure WIM to repository: " + SecWimPath, LogType.FileAndConsole);
|
||||
if (FirmwareVersion != null)
|
||||
{
|
||||
LogFile.Log("Firmware version: " + FirmwareVersion, LogType.FileAndConsole);
|
||||
}
|
||||
|
||||
Entry = new SecWimEntry
|
||||
{
|
||||
Path = SecWimPath,
|
||||
FirmwareVersion = FirmwareVersion
|
||||
};
|
||||
SecWimRepository.Add(Entry);
|
||||
WriteConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.Log("Secure WIM not added, because it was already present in the repository.", LogType.FileAndConsole);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveSecWimFromRepository(string SecWimPath)
|
||||
{
|
||||
int Count = 0;
|
||||
SecWimRepository.Where(e => string.Equals(e.Path, SecWimPath, StringComparison.CurrentCultureIgnoreCase)).ToList().ForEach(e =>
|
||||
{
|
||||
Count++;
|
||||
SecWimRepository.Remove(e);
|
||||
});
|
||||
if (Count == 0)
|
||||
{
|
||||
LogFile.Log("Secure WIM was not removed from repository because it was not present.", LogType.FileAndConsole);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.Log("Removed Secure WIM from repository: " + SecWimPath, LogType.FileAndConsole);
|
||||
WriteConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public List<SecWimEntry> SecWimRepository = new();
|
||||
|
||||
public List<EmergencyFileEntry> EmergencyRepository = new();
|
||||
|
||||
internal void AddEmergencyToRepository(string Type, string ProgrammerPath, string PayloadPath)
|
||||
@@ -344,6 +390,17 @@ namespace WPinternals
|
||||
}
|
||||
}
|
||||
|
||||
public class SecWimEntry
|
||||
{
|
||||
public string FirmwareVersion;
|
||||
public string Path;
|
||||
|
||||
internal bool Exists()
|
||||
{
|
||||
return File.Exists(Path);
|
||||
}
|
||||
}
|
||||
|
||||
public class EmergencyFileEntry
|
||||
{
|
||||
public string Type;
|
||||
|
||||
Reference in New Issue
Block a user