mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-13 19:06:41 +10:00
Implemented the new flashing hack
This new flashing hack exploits a bug in flash app where it will not properly check the integrity of catalog files used in FFU files
This commit is contained in:
+22
-1
@@ -670,7 +670,7 @@ namespace WPinternals
|
||||
Info = FlashModel.ReadPhoneInfo();
|
||||
Info.Log(LogType.ConsoleOnly);
|
||||
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
|
||||
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)((Info.RdcPresent || !Info.SecureFfuEnabled || Info.Authenticated) ? FlashOptions.SkipSignatureCheck : 0)));
|
||||
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
|
||||
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
|
||||
Notifier.Stop();
|
||||
}
|
||||
@@ -1608,6 +1608,24 @@ namespace WPinternals
|
||||
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
|
||||
}
|
||||
break;
|
||||
case "rewritepartitionsfrommassstorage":
|
||||
if (args.Length < 2)
|
||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RewritePartitionsFromMassStorage <Path to folder containing img partitions> \n The name of the imgs must be the partition names. For example, DPP.img will get written to the DPP partition.");
|
||||
|
||||
await TestCode.RewriteParts(args[2]);
|
||||
break;
|
||||
case "restoregptusingedl":
|
||||
if (args.Length < 3)
|
||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingEDL <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)> <Loaders path>");
|
||||
|
||||
await TestCode.RecoverBadGPT(args[2], args[3]);
|
||||
break;
|
||||
case "restoregptusingmassstorage":
|
||||
if (args.Length < 2)
|
||||
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingMassStorage <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)>");
|
||||
|
||||
await TestCode.RewriteGPT(args[2]);
|
||||
break;
|
||||
default:
|
||||
LogFile.Log("", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals commandline usage:", LogType.ConsoleOnly);
|
||||
@@ -1671,6 +1689,9 @@ namespace WPinternals
|
||||
LogFile.Log(" <Optional: Destination folder>", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals -DumpUEFI <UEFI binary or FFU file> <Destination folder>", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals -TestProgrammer <EDE file>", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals -RewritePartitionsFromMassStorage <Path to folder containing img partitions>", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals -RestoreGPTUsingEDL <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)> <Loaders path>", LogType.ConsoleOnly);
|
||||
LogFile.Log("WPinternals -RestoreGPTUsingMassStorage <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)>", LogType.ConsoleOnly);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,7 +620,7 @@ namespace WPinternals
|
||||
|
||||
PhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
|
||||
FlashAppType OriginalAppType = Info.App;
|
||||
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent);
|
||||
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure);
|
||||
if (Switch)
|
||||
SwitchToBootManagerContext();
|
||||
|
||||
@@ -943,6 +943,8 @@ namespace WPinternals
|
||||
Result.State = PhoneInfoState.Extended;
|
||||
}
|
||||
|
||||
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
||||
|
||||
if (!PhoneInfoLogged)
|
||||
Result.Log(LogType.FileOnly);
|
||||
|
||||
@@ -1193,6 +1195,8 @@ namespace WPinternals
|
||||
public bool UefiSecureBootEnabled;
|
||||
public bool SecondaryHardwareKeyPresent;
|
||||
|
||||
public bool IsBootloaderSecure;
|
||||
|
||||
internal void Log(LogType Type)
|
||||
{
|
||||
if (State == PhoneInfoState.Extended)
|
||||
@@ -1227,12 +1231,12 @@ namespace WPinternals
|
||||
break;
|
||||
}
|
||||
|
||||
LogFile.Log("SecureBoot: " + ((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled"), Type);
|
||||
LogFile.Log("SecureBoot: " + ((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled") + " (Platform Secure Boot: " + (PlatformSecureBootEnabled ? "Enabled" : "Disabled") + ", UEFI Secure Boot: " + (PlatformSecureBootEnabled ? "Enabled" : "Disabled") + ")", Type);
|
||||
|
||||
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
|
||||
LogFile.Log("Flash app security: " + ((!SecureFfuEnabled || RdcPresent || Authenticated) ? "Disabled" : "Enabled"), LogType.ConsoleOnly);
|
||||
LogFile.Log("Flash app security: " + (!IsBootloaderSecure ? "Disabled" : "Enabled"), LogType.ConsoleOnly);
|
||||
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
|
||||
LogFile.Log("Flash app security: " + ((!SecureFfuEnabled || RdcPresent || Authenticated) ? "Disabled" : "Enabled") + " (FFU security: " + (SecureFfuEnabled ? "Enabled" : "Disabled") + ", RDC: " + (RdcPresent ? "Present" : "Not found") + ", Authenticated: " + (Authenticated ? "True" : "False") + ")", LogType.FileOnly);
|
||||
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);
|
||||
}
|
||||
|
||||
+201
@@ -19,6 +19,9 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WPinternals
|
||||
@@ -36,6 +39,204 @@ namespace WPinternals
|
||||
// MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
|
||||
}
|
||||
|
||||
internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath)
|
||||
{
|
||||
byte[] GPT = File.ReadAllBytes(GPTPath);
|
||||
|
||||
PhoneNotifierViewModel PhoneNotifier = new PhoneNotifierViewModel();
|
||||
PhoneNotifier.Start();
|
||||
await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download);
|
||||
|
||||
byte[] RootKeyHash = null;
|
||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
|
||||
{
|
||||
QualcommDownload Download2 = new QualcommDownload((QualcommSerial)PhoneNotifier.CurrentModel);
|
||||
RootKeyHash = Download2.GetRKH();
|
||||
}
|
||||
|
||||
List<QualcommPartition> PossibleLoaders = null;
|
||||
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
|
||||
{
|
||||
try
|
||||
{
|
||||
PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash);
|
||||
if (PossibleLoaders.Count == 0)
|
||||
{
|
||||
throw new Exception("Error: No matching loaders found for RootKeyHash.");
|
||||
}
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
LogFile.LogException(Ex);
|
||||
throw new Exception("Error: Unexpected error during scanning for loaders.");
|
||||
}
|
||||
}
|
||||
|
||||
QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel;
|
||||
QualcommDownload Download = new QualcommDownload(Serial);
|
||||
if (Download.IsAlive())
|
||||
{
|
||||
int Attempt = 1;
|
||||
bool Result = false;
|
||||
foreach (QualcommPartition Loader in PossibleLoaders)
|
||||
{
|
||||
LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly);
|
||||
|
||||
try
|
||||
{
|
||||
Download.SendToPhoneMemory(0x2A000000, Loader.Binary);
|
||||
Download.StartBootloader(0x2A000000);
|
||||
Result = true;
|
||||
LogFile.Log("Loader sent successfully", LogType.ConsoleOnly);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (Result)
|
||||
break;
|
||||
|
||||
Attempt++;
|
||||
}
|
||||
Serial.Close();
|
||||
|
||||
if (!Result)
|
||||
LogFile.Log("Loader failed", LogType.ConsoleOnly);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly);
|
||||
throw new BadConnectionException();
|
||||
}
|
||||
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
await PhoneNotifier.WaitForArrival();
|
||||
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
|
||||
throw new WPinternalsException("Phone failed to switch to emergency flash mode.");
|
||||
|
||||
// Flash bootloader
|
||||
QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel;
|
||||
Serial2.EncodeCommands = false;
|
||||
|
||||
QualcommFlasher Flasher = new QualcommFlasher(Serial2);
|
||||
|
||||
Flasher.Hello();
|
||||
Flasher.SetSecurityMode(0);
|
||||
Flasher.OpenPartition(0x21);
|
||||
|
||||
LogFile.Log("Partition opened.", LogType.ConsoleOnly);
|
||||
|
||||
LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly);
|
||||
Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte.
|
||||
|
||||
Flasher.ClosePartition();
|
||||
|
||||
LogFile.Log("Partition closed. Flashing ready. Rebooting.");
|
||||
|
||||
Flasher.Reboot();
|
||||
|
||||
Flasher.CloseSerial();
|
||||
}
|
||||
|
||||
internal static async Task RewriteGPT(string GPTPath)
|
||||
{
|
||||
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
|
||||
Notifier.Start();
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
|
||||
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
|
||||
|
||||
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
|
||||
MassStorage.WriteSectors(1, GPTPath);
|
||||
}
|
||||
|
||||
internal static async Task RewriteMBRGPT()
|
||||
{
|
||||
FFU FFU = new FFU(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu");
|
||||
string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin";
|
||||
|
||||
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
|
||||
Notifier.Start();
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
|
||||
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
|
||||
|
||||
byte[] MBR = FFU.GetSectors(0, 1);
|
||||
LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly);
|
||||
MassStorage.WriteSectors(0, MBR);
|
||||
|
||||
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
|
||||
MassStorage.WriteSectors(1, GPTPath);
|
||||
}
|
||||
|
||||
internal static async Task RewriteParts(string PartPath)
|
||||
{
|
||||
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
|
||||
Notifier.Start();
|
||||
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
|
||||
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
|
||||
|
||||
foreach (var part in Directory.EnumerateFiles(PartPath))
|
||||
{
|
||||
var partname = part.Split('\\').Last().Replace(".img", "");
|
||||
try
|
||||
{
|
||||
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
|
||||
|
||||
LogFile.Log("", LogType.ConsoleOnly);
|
||||
|
||||
MassStorage.RestorePartition(part, partname, (v, t) =>
|
||||
{
|
||||
LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly);
|
||||
});
|
||||
LogFile.Log("", LogType.ConsoleOnly);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogFile.Log("", LogType.ConsoleOnly);
|
||||
LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static void PatchImg(string dump)
|
||||
{
|
||||
using (var fil = File.Open(dump, FileMode.Open))
|
||||
{
|
||||
byte[] gptbuffer = new byte[0x4200];
|
||||
|
||||
fil.Seek(0x200, SeekOrigin.Begin);
|
||||
fil.Read(gptbuffer, 0, 0x4200);
|
||||
|
||||
uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20);
|
||||
uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30);
|
||||
|
||||
LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly);
|
||||
LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly);
|
||||
|
||||
uint NewBackupLBA = 62078975u;
|
||||
uint NewLastUsableLBA = 62078942u;
|
||||
|
||||
ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA);
|
||||
ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA);
|
||||
|
||||
uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C);
|
||||
uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10);
|
||||
|
||||
LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly);
|
||||
|
||||
ByteOperations.WriteUInt32(gptbuffer, 0x10, 0);
|
||||
uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize);
|
||||
|
||||
LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly);
|
||||
|
||||
ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC);
|
||||
|
||||
LogFile.Log("Writing", LogType.ConsoleOnly);
|
||||
|
||||
fil.Seek(0x200, SeekOrigin.Begin);
|
||||
fil.Write(gptbuffer, 0, 0x4200);
|
||||
|
||||
LogFile.Log("Done!", LogType.ConsoleOnly);
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath)
|
||||
{
|
||||
LogFile.BeginAction("TestProgrammer");
|
||||
|
||||
@@ -527,6 +527,8 @@ namespace WPinternals
|
||||
FlashParts.Add(Part);
|
||||
}
|
||||
|
||||
bool ClearFlashingStatus = true;
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -536,13 +538,15 @@ namespace WPinternals
|
||||
Part.StartSector = (UInt32)Target.FirstSector;
|
||||
Part.Stream = new MemoryStream(new byte[0x40000]);
|
||||
FlashParts.Add(Part);
|
||||
|
||||
ClearFlashingStatus = false;
|
||||
}
|
||||
|
||||
if (FlashParts.Count > 0)
|
||||
{
|
||||
ActivateSubContext(new BusyViewModel("Restoring bootloader..."));
|
||||
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
|
||||
LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, FFUPath, false, false, FlashParts, true, ClearFlashingStatusAtEnd: false,
|
||||
LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, FFUPath, false, false, FlashParts, true, ClearFlashingStatusAtEnd: ClearFlashingStatus,
|
||||
SetWorkingStatus: (m, s, v, a, st) =>
|
||||
{
|
||||
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
|
||||
@@ -583,7 +587,7 @@ namespace WPinternals
|
||||
BusyViewModel Busy = new BusyViewModel("Flashing original FFU...", MaxProgressValue: FFU.TotalChunkCount, UIContext: UIContext);
|
||||
ActivateSubContext(Busy);
|
||||
byte Options = 0;
|
||||
if (!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent)
|
||||
if (!Info.IsBootloaderSecure)
|
||||
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
|
||||
Phone.FlashFFU(FFU, Busy.ProgressUpdater, true, Options);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace WPinternals
|
||||
|
||||
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo();
|
||||
if (SecurityStatus == null)
|
||||
IsBootLoaderUnlocked = (Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
|
||||
IsBootLoaderUnlocked = !Info.IsBootloaderSecure;
|
||||
|
||||
if (RootKeyHash == null)
|
||||
{
|
||||
@@ -210,8 +210,6 @@ namespace WPinternals
|
||||
GPT GPT = FlashModel.ReadGPT();
|
||||
if ((GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null))
|
||||
{
|
||||
//ExitMessage("Phone is already unlocked", null);
|
||||
//return;
|
||||
AlreadyUnlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,33 +104,42 @@ namespace WPinternals
|
||||
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
|
||||
if (ExitFailure == null) ExitFailure = (m, s) => { };
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, FFUPath, DoResetFirst, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
|
||||
SetWorkingStatus("Booting phone...");
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
ExitFailure tmpExitFailure = (m, s) =>
|
||||
{
|
||||
ExitFailure("Failed to relock phone", "Your phone is half relocked. You may need to reflash a stock ROM");
|
||||
return;
|
||||
}
|
||||
ExitFailure(m, s);
|
||||
};
|
||||
|
||||
ExitSuccess tmpExitSuccess = async (m, s) =>
|
||||
{
|
||||
SetWorkingStatus("Booting phone...");
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
{
|
||||
ExitFailure("Failed to relock phone", "Your phone is half relocked. You may need to reflash a stock ROM");
|
||||
return;
|
||||
}
|
||||
|
||||
ExitSuccess("Bootloader restored successfully!");
|
||||
};
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, FFUPath, DoResetFirst, SetWorkingStatus, UpdateWorkingStatus, tmpExitSuccess, tmpExitFailure);
|
||||
|
||||
ExitSuccess("Bootloader restored successfully!");
|
||||
}
|
||||
|
||||
internal static async Task LumiaV2UnlockUEFI(PhoneNotifierViewModel Notifier, string ProfileFFUPath, string EDEPath, string SupportedFFUPath, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, bool ReUnlockDevice = false)
|
||||
@@ -140,33 +149,42 @@ namespace WPinternals
|
||||
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
|
||||
if (ExitFailure == null) ExitFailure = (m, s) => { };
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFUPath, EDEPath, SupportedFFUPath, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure, ReUnlockDevice: ReUnlockDevice);
|
||||
|
||||
SetWorkingStatus("Booting phone...");
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
ExitFailure tmpExitFailure = (m, s) =>
|
||||
{
|
||||
ExitFailure("Failed to unlock phone", "Your phone is half unlocked. You may need to reflash a stock ROM");
|
||||
return;
|
||||
}
|
||||
ExitFailure(m, s);
|
||||
};
|
||||
|
||||
ExitSuccess tmpExitSuccess = async (m, s) =>
|
||||
{
|
||||
SetWorkingStatus("Booting phone...");
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
|
||||
|
||||
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
|
||||
{
|
||||
ExitFailure("Failed to unlock phone", "Your phone is half unlocked. You may need to reflash a stock ROM");
|
||||
return;
|
||||
}
|
||||
|
||||
ExitSuccess("Bootloader unlocked successfully!", null);
|
||||
};
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFUPath, EDEPath, SupportedFFUPath, SetWorkingStatus, UpdateWorkingStatus, tmpExitSuccess, tmpExitFailure, ReUnlockDevice: ReUnlockDevice);
|
||||
|
||||
ExitSuccess("Bootloader unlocked successfully!", null);
|
||||
}
|
||||
|
||||
// Magic!
|
||||
@@ -1278,7 +1296,7 @@ namespace WPinternals
|
||||
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
|
||||
FlashAppType OriginalAppType = Info.App;
|
||||
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent);
|
||||
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure);
|
||||
if (Switch)
|
||||
FlashModel.SwitchToBootManagerContext();
|
||||
|
||||
@@ -1608,15 +1626,14 @@ namespace WPinternals
|
||||
}
|
||||
|
||||
LogFile.Log("Phone is relocked", LogType.FileAndConsole);
|
||||
LogFile.EndAction("RelockPhone");
|
||||
ExitSuccess("Phone is relocked", null);
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
LogFile.LogException(Ex);
|
||||
ExitFailure("Error: " + Ex.Message, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogFile.EndAction("RelockPhone");
|
||||
ExitFailure("Error: " + Ex.Message, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1640,14 +1657,12 @@ namespace WPinternals
|
||||
PhoneInfo Info = FlashModel.ReadPhoneInfo();
|
||||
bool IsSpecB = Info.FlashAppProtocolVersionMajor >= 2;
|
||||
|
||||
bool IsBootLoaderSecure = !Info.Authenticated && !Info.RdcPresent && Info.SecureFfuEnabled;
|
||||
|
||||
if (ProfileFFUPath == null)
|
||||
throw new ArgumentNullException("Profile FFU path is missing");
|
||||
|
||||
FFU ProfileFFU = new FFU(ProfileFFUPath);
|
||||
|
||||
if (IsBootLoaderSecure)
|
||||
if (Info.IsBootloaderSecure)
|
||||
{
|
||||
if (!Info.PlatformID.StartsWith(ProfileFFU.PlatformID, StringComparison.OrdinalIgnoreCase))
|
||||
throw new ArgumentNullException("Profile FFU has wrong Platform ID for connected phone");
|
||||
@@ -1677,13 +1692,91 @@ namespace WPinternals
|
||||
|
||||
LumiaUnlockBootloaderViewModel.LumiaPatchEFIESP(SupportedFFU, UnlockedEFIESP, IsSpecB);
|
||||
|
||||
// Create backup-partition for EFIESP
|
||||
byte[] GPTChunk = GetGptChunk(FlashModel, (UInt32)ProfileFFU.ChunkSize);
|
||||
byte[] GPTChunkBackup = new byte[GPTChunk.Length];
|
||||
Buffer.BlockCopy(GPTChunk, 0, GPTChunkBackup, 0, GPTChunk.Length);
|
||||
GPT GPT = new GPT(GPTChunk);
|
||||
bool GPTChanged = false;
|
||||
|
||||
LogFile.Log("Enabling Test Signing", LogType.FileAndConsole);
|
||||
SetWorkingStatus("Enabling Test Signing", null, null);
|
||||
|
||||
List<FlashPart> Parts = new List<FlashPart>();
|
||||
FlashPart Part;
|
||||
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
}
|
||||
Part = new FlashPart();
|
||||
Partition TargetPartition = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)TargetPartition.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
string SBRes = IsSpecB ? "WPinternals.SB" : "WPinternals.SBA";
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
// Magic!
|
||||
// The SB(A) resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream(SBRes);
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
|
||||
if (GPTChanged)
|
||||
{
|
||||
GPT.Rebuild();
|
||||
Part = new FlashPart();
|
||||
Part.StartSector = 0;
|
||||
Part.Stream = new MemoryStream(GPTChunk);
|
||||
Parts.Add(Part);
|
||||
}
|
||||
|
||||
foreach (FlashPart _part in Parts)
|
||||
{
|
||||
_part.ProgressText = "Enabling Test Signing...";
|
||||
}
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, false, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
|
||||
|
||||
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
|
||||
throw new WPinternalsException("Error: 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.");
|
||||
|
||||
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
|
||||
{
|
||||
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
FlashModel.SwitchToFlashAppContext();
|
||||
}
|
||||
|
||||
GPTChanged = false;
|
||||
|
||||
// Create backup-partition for EFIESP
|
||||
|
||||
bool SBL3Eng = GPT.GetPartition("IS_UNLOCKED_SBL3") != null;
|
||||
|
||||
bool ShouldApplyOldEFIESPMethod = true;
|
||||
@@ -1695,8 +1788,8 @@ namespace WPinternals
|
||||
if (!IsSpecB && !SBL3Eng)
|
||||
ShouldApplyOldEFIESPMethod = false;
|
||||
|
||||
List<FlashPart> Parts = ShouldApplyOldEFIESPMethod ? new List<FlashPart>() : LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
|
||||
FlashPart Part;
|
||||
Parts = ShouldApplyOldEFIESPMethod ? new List<FlashPart>() : LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
|
||||
Part = null;
|
||||
|
||||
UInt32 OriginalEfiespSizeInSectors = (UInt32)GPT.GetPartition("EFIESP").SizeInSectors;
|
||||
UInt32 OriginalEfiespLastSector = (UInt32)GPT.GetPartition("EFIESP").LastSector;
|
||||
@@ -1805,52 +1898,6 @@ namespace WPinternals
|
||||
Parts.Add(Part);
|
||||
}
|
||||
|
||||
if (IsSpecB)
|
||||
Parts[0].ProgressText = "Flashing unlocked bootloader (part 1)...";
|
||||
else
|
||||
Parts[0].ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
}
|
||||
Part = new FlashPart();
|
||||
Partition TargetPartition = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)TargetPartition.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
string SBRes = IsSpecB ? "WPinternals.SB" : "WPinternals.SBA";
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
// Magic!
|
||||
// The SB(A) resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream(SBRes);
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
|
||||
if (GPTChanged)
|
||||
{
|
||||
GPT.Rebuild();
|
||||
@@ -1860,7 +1907,19 @@ namespace WPinternals
|
||||
Parts.Add(Part);
|
||||
}
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, false, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
|
||||
foreach (FlashPart _part in Parts)
|
||||
{
|
||||
if (IsSpecB)
|
||||
{
|
||||
_part.ProgressText = "Flashing unlocked bootloader (part 1)...";
|
||||
}
|
||||
else
|
||||
{
|
||||
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
}
|
||||
}
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
|
||||
|
||||
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
|
||||
await Notifier.WaitForArrival();
|
||||
@@ -1969,7 +2028,7 @@ namespace WPinternals
|
||||
|
||||
// Copy the backed up unlocked EFIESP for future use
|
||||
BackupUnlockedEFIESP = new byte[UnlockedEFIESP.Length];
|
||||
Buffer.BlockCopy(BackupEFIESP, 0, BackupUnlockedEFIESP, 0, BackupEFIESP.Length);
|
||||
Buffer.BlockCopy(BackupEFIESP, 0, BackupUnlockedEFIESP, 0, UnlockedEFIESP.Length);
|
||||
|
||||
LumiaUnlockBootloaderViewModel.LumiaPatchEFIESP(SupportedFFU, BackupUnlockedEFIESP, IsSpecB);
|
||||
}
|
||||
@@ -2083,7 +2142,6 @@ namespace WPinternals
|
||||
Part = new FlashPart();
|
||||
Part.StartSector = 0;
|
||||
Part.Stream = new MemoryStream(GPTChunk);
|
||||
Part.ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
Parts.Add(Part);
|
||||
Part = new FlashPart();
|
||||
Part.StartSector = OriginalEfiespFirstSector;
|
||||
@@ -2094,6 +2152,11 @@ namespace WPinternals
|
||||
Part.Stream = new MemoryStream(BackupEFIESP);
|
||||
Parts.Add(Part);
|
||||
|
||||
foreach (FlashPart _part in Parts)
|
||||
{
|
||||
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
}
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
|
||||
}
|
||||
else
|
||||
@@ -2146,10 +2209,17 @@ namespace WPinternals
|
||||
|
||||
Parts = LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
|
||||
|
||||
if (IsSpecB)
|
||||
Parts[0].ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
else
|
||||
Parts[0].ProgressText = "Flashing unlocked bootloader (part 3)...";
|
||||
foreach (FlashPart _part in Parts)
|
||||
{
|
||||
if (IsSpecB)
|
||||
{
|
||||
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
|
||||
}
|
||||
else
|
||||
{
|
||||
_part.ProgressText = "Flashing unlocked bootloader (part 3)...";
|
||||
}
|
||||
}
|
||||
|
||||
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
|
||||
|
||||
@@ -2157,14 +2227,22 @@ namespace WPinternals
|
||||
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
|
||||
}
|
||||
|
||||
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
|
||||
await Notifier.WaitForArrival();
|
||||
|
||||
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
|
||||
throw new WPinternalsException("Error: 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.");
|
||||
|
||||
LogFile.Log("Bootloader unlocked!", LogType.FileAndConsole);
|
||||
LogFile.EndAction("UnlockBootloader");
|
||||
ExitSuccess("Bootloader unlocked!", null);
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
LogFile.LogException(Ex);
|
||||
LogFile.EndAction("UnlockBootloader");
|
||||
ExitFailure(Ex.Message, Ex is WPinternalsException ? ((WPinternalsException)Ex).SubMessage : null);
|
||||
}
|
||||
LogFile.EndAction("UnlockBootloader");
|
||||
}
|
||||
|
||||
// Magic!
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace WPinternals
|
||||
|
||||
SetWorkingStatus("Scanning for flashing-profile", "Your phone may appear to be in a reboot-loop. This is expected behavior. Don't interfere this process.", null, Status: WPinternalsStatus.Scanning);
|
||||
|
||||
await LumiaV2CustomFlash(Notifier, FFUPath, false, !Info.SecureFfuEnabled || Info.RdcPresent || Info.Authenticated, null, DoResetFirst, Experimental: Experimental, SetWorkingStatus:
|
||||
await LumiaV2CustomFlash(Notifier, FFUPath, false, !Info.IsBootloaderSecure, null, DoResetFirst, Experimental: Experimental, SetWorkingStatus:
|
||||
(m, s, v, a, st) =>
|
||||
{
|
||||
if (st == WPinternalsStatus.SwitchingMode)
|
||||
@@ -440,8 +440,47 @@ namespace WPinternals
|
||||
await LumiaV2CustomFlash(Notifier, FFUPath, PerformFullFlashFirst, SkipWrite, Parts, DoResetFirst, ClearFlashingStatusAtEnd, CheckSectorAlignment, ShowProgress, Experimental);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
||||
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Model, 131072u);
|
||||
|
||||
GPT GPT = new GPT(GPTChunk);
|
||||
|
||||
Partition UefiBSNV = GPT.GetPartition("UEFI_BS_NV");
|
||||
|
||||
bool UseOlderExploit = Info.UefiSecureBootEnabled;
|
||||
|
||||
if (!UseOlderExploit && ClearFlashingStatusAtEnd)
|
||||
{
|
||||
if (FlashParts == null)
|
||||
{
|
||||
UseOlderExploit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var part in FlashParts)
|
||||
{
|
||||
if (part.StartSector >= UefiBSNV.FirstSector && part.StartSector <= UefiBSNV.LastSector)
|
||||
{
|
||||
UseOlderExploit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UseOlderExploit || !ClearFlashingStatusAtEnd)
|
||||
await LumiaV20CustomFlash(Notifier, FFUPath, PerformFullFlashFirst, SkipWrite, FlashParts, DoResetFirst, ClearFlashingStatusAtEnd, CheckSectorAlignment, ShowProgress, Experimental, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure, ProgrammerPath);
|
||||
else
|
||||
await LumiaV3FlashRomViewModel.LumiaV3CustomFlash(Notifier, FlashParts, CheckSectorAlignment, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
}
|
||||
|
||||
// Magic!
|
||||
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) //, string LoaderPath = null)
|
||||
internal async static Task LumiaV20CustomFlash(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) //, string LoaderPath = null)
|
||||
{
|
||||
// Both SecurityHeader and StoreHeader need to be modified.
|
||||
// Those should both not fall in a memory-gap to allow modification.
|
||||
@@ -528,7 +567,7 @@ namespace WPinternals
|
||||
byte Options = 0;
|
||||
if (SkipWrite)
|
||||
Options = (byte)FlashOptions.SkipWrite;
|
||||
if (!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent)
|
||||
if (!Info.IsBootloaderSecure)
|
||||
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
|
||||
|
||||
// Gap fill calculation:
|
||||
@@ -1801,6 +1840,8 @@ namespace WPinternals
|
||||
bool IsUnlocked = false;
|
||||
bool GPTChanged = false;
|
||||
|
||||
bool ClearFlashingStatus = true;
|
||||
|
||||
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
|
||||
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
|
||||
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
|
||||
@@ -1896,6 +1937,7 @@ namespace WPinternals
|
||||
IsUnlockedFlag.LastSector = 0x40;
|
||||
GPT.Partitions.Add(IsUnlockedFlag);
|
||||
GPTChanged = true;
|
||||
ClearFlashingStatus = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1905,6 +1947,7 @@ namespace WPinternals
|
||||
{
|
||||
GPT.Partitions.Remove(IsUnlockedFlag);
|
||||
GPTChanged = true;
|
||||
ClearFlashingStatus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1952,46 +1995,81 @@ namespace WPinternals
|
||||
return;
|
||||
}
|
||||
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
if (!ClearFlashingStatus)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
if (!IsUnlocked)
|
||||
{
|
||||
// Undo secure boot exploit
|
||||
Partition NvBackupPartition = GPT.GetPartition("BACKUP_BS_NV");
|
||||
if (NvBackupPartition != null)
|
||||
{
|
||||
// This must be a left over of a half unlocked bootloader
|
||||
Partition NvPartition = GPT.GetPartition("UEFI_BS_NV");
|
||||
NvBackupPartition.Name = "UEFI_BS_NV";
|
||||
NvBackupPartition.PartitionGuid = NvPartition.PartitionGuid;
|
||||
NvBackupPartition.PartitionTypeGuid = NvPartition.PartitionTypeGuid;
|
||||
GPT.Partitions.Remove(NvPartition);
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
PhoneInfo 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)
|
||||
{
|
||||
// ClearNV
|
||||
Part = new FlashPart();
|
||||
Partition Target2 = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target2.FirstSector;
|
||||
Part.Stream = new MemoryStream(new byte[0x40000]);
|
||||
Parts.Add(Part);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
Part = new FlashPart();
|
||||
Target = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
|
||||
// Magic!
|
||||
// The SB resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
}
|
||||
}
|
||||
Part = new FlashPart();
|
||||
Target = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
|
||||
// Magic!
|
||||
// The SB resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
|
||||
if (GPTChanged)
|
||||
{
|
||||
@@ -2037,7 +2115,7 @@ namespace WPinternals
|
||||
});
|
||||
|
||||
// Do actual flashing!
|
||||
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, false, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, ClearFlashingStatus, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2116,6 +2194,7 @@ namespace WPinternals
|
||||
Partition Partition;
|
||||
bool IsUnlocked = false;
|
||||
bool GPTChanged = false;
|
||||
bool ClearFlashingStatus = true;
|
||||
|
||||
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
|
||||
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
|
||||
@@ -2155,6 +2234,7 @@ namespace WPinternals
|
||||
IsUnlockedFlag.LastSector = 0x40;
|
||||
GPT.Partitions.Add(IsUnlockedFlag);
|
||||
GPTChanged = true;
|
||||
ClearFlashingStatus = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2164,6 +2244,7 @@ namespace WPinternals
|
||||
{
|
||||
GPT.Partitions.Remove(IsUnlockedFlag);
|
||||
GPTChanged = true;
|
||||
ClearFlashingStatus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2230,45 +2311,81 @@ namespace WPinternals
|
||||
return;
|
||||
}
|
||||
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
if (!ClearFlashingStatus)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
if (!IsUnlocked)
|
||||
{
|
||||
// Undo secure boot exploit
|
||||
Partition NvBackupPartition = GPT.GetPartition("BACKUP_BS_NV");
|
||||
if (NvBackupPartition != null)
|
||||
{
|
||||
// This must be a left over of a half unlocked bootloader
|
||||
Partition NvPartition = GPT.GetPartition("UEFI_BS_NV");
|
||||
NvBackupPartition.Name = "UEFI_BS_NV";
|
||||
NvBackupPartition.PartitionGuid = NvPartition.PartitionGuid;
|
||||
NvBackupPartition.PartitionTypeGuid = NvPartition.PartitionTypeGuid;
|
||||
GPT.Partitions.Remove(NvPartition);
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
PhoneInfo 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)
|
||||
{
|
||||
// ClearNV
|
||||
Part = new FlashPart();
|
||||
Partition Target2 = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target2.FirstSector;
|
||||
Part.Stream = new MemoryStream(new byte[0x40000]);
|
||||
Parts.Add(Part);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Now add NV partition
|
||||
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
|
||||
Partition UEFI_BS_NV;
|
||||
if (BACKUP_BS_NV == null)
|
||||
{
|
||||
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
|
||||
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
|
||||
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
|
||||
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
|
||||
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
|
||||
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
|
||||
UEFI_BS_NV = new Partition();
|
||||
UEFI_BS_NV.Name = "UEFI_BS_NV";
|
||||
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
|
||||
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
|
||||
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
|
||||
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
|
||||
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
|
||||
GPT.Partitions.Add(UEFI_BS_NV);
|
||||
GPTChanged = true;
|
||||
}
|
||||
|
||||
Part = new FlashPart();
|
||||
Target = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
|
||||
// Magic!
|
||||
// The SB resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
}
|
||||
}
|
||||
Part = new FlashPart();
|
||||
Target = GPT.GetPartition("UEFI_BS_NV");
|
||||
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
|
||||
Part.Stream = new SeekableStream(() =>
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
|
||||
// Magic!
|
||||
// The SB resource is a compressed version of a raw NV-variable-partition.
|
||||
// In this partition the SecureBoot variable is disabled.
|
||||
// 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.
|
||||
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
|
||||
|
||||
return new DecompressedStream(stream);
|
||||
});
|
||||
Parts.Add(Part);
|
||||
|
||||
if (GPTChanged)
|
||||
{
|
||||
@@ -2318,7 +2435,7 @@ namespace WPinternals
|
||||
}
|
||||
|
||||
// Do actual flashing!
|
||||
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, false, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, ClearFlashingStatus, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal class LumiaV3FlashRomViewModel : ContextViewModel
|
||||
{
|
||||
|
||||
private static void RoundUpToChunks(Stream stream, UInt32 chunkSize)
|
||||
{
|
||||
Int64 Size = stream.Length;
|
||||
if ((Size % chunkSize) > 0)
|
||||
{
|
||||
Int64 padding = (UInt32)(((Size / chunkSize) + 1) * chunkSize) - Size;
|
||||
stream.Write(new byte[padding], 0, (Int32)padding);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ImageHeader
|
||||
{
|
||||
public UInt32 Size = 24;
|
||||
public string Signature = "ImageFlash ";
|
||||
public UInt32 ManifestLength;
|
||||
public UInt32 ChunkSize = 128;
|
||||
}
|
||||
|
||||
public class StoreHeader
|
||||
{
|
||||
public UInt32 UpdateType = 0; // Full update
|
||||
|
||||
public UInt16 MajorVersion = 1;
|
||||
public UInt16 MinorVersion = 0;
|
||||
public UInt16 FullFlashMajorVersion = 2;
|
||||
public UInt16 FullFlashMinorVersion = 0;
|
||||
|
||||
// Size is 0xC0
|
||||
public string PlatformId;
|
||||
|
||||
public UInt32 BlockSizeInBytes = 131072;
|
||||
public UInt32 WriteDescriptorCount;
|
||||
public UInt32 WriteDescriptorLength;
|
||||
public UInt32 ValidateDescriptorCount = 0;
|
||||
public UInt32 ValidateDescriptorLength = 0;
|
||||
public UInt32 InitialTableIndex = 0;
|
||||
public UInt32 InitialTableCount = 0;
|
||||
public UInt32 FlashOnlyTableIndex = 0; // Should be the index of the critical partitions, but for now we don't implement that
|
||||
public UInt32 FlashOnlyTableCount = 1;
|
||||
public UInt32 FinalTableIndex; //= WriteDescriptorCount - FinalTableCount;
|
||||
public UInt32 FinalTableCount = 0;
|
||||
}
|
||||
|
||||
public class SecurityHeader
|
||||
{
|
||||
public UInt32 Size = 32;
|
||||
public string Signature = "SignedImage ";
|
||||
public UInt32 ChunkSizeInKb = 128;
|
||||
public UInt32 HashAlgorithm = 32780; // SHA256 algorithm id
|
||||
public UInt32 CatalogSize;
|
||||
public UInt32 HashTableSize;
|
||||
}
|
||||
|
||||
internal class ManifestIni
|
||||
{
|
||||
internal static string BuildUpManifest(FullFlash fullFlash, Store store)
|
||||
{
|
||||
string Manifest = "[FullFlash]\r\n";
|
||||
if (!string.IsNullOrEmpty(fullFlash.AntiTheftVersion))
|
||||
Manifest += "AntiTheftVersion = " + fullFlash.AntiTheftVersion + "\r\n";
|
||||
if (!string.IsNullOrEmpty(fullFlash.OSVersion))
|
||||
Manifest += "OSVersion = " + fullFlash.OSVersion + "\r\n";
|
||||
if (!string.IsNullOrEmpty(fullFlash.Description))
|
||||
Manifest += "Description = " + fullFlash.Description + "\r\n";
|
||||
if (!string.IsNullOrEmpty(fullFlash.Version))
|
||||
Manifest += "Version = " + fullFlash.Version + "\r\n";
|
||||
if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId0))
|
||||
Manifest += "DevicePlatformId0 = " + fullFlash.DevicePlatformId0 + "\r\n";
|
||||
|
||||
Manifest += "\r\n[Store]\r\n";
|
||||
Manifest += "SectorSize = " + store.SectorSize + "\r\n";
|
||||
Manifest += "MinSectorCount = " + store.MinSectorCount + "\r\n";
|
||||
Manifest += "\r\n";
|
||||
|
||||
return Manifest;
|
||||
}
|
||||
}
|
||||
|
||||
internal class FullFlash
|
||||
{
|
||||
public string AntiTheftVersion = "1.1"; // Allow flashing on all devices
|
||||
public string OSVersion;
|
||||
public string Description = "Update on: " + DateTime.Now.ToString("u") + "::\r\n";
|
||||
public string Version = "2.0";
|
||||
public string DevicePlatformId0;
|
||||
}
|
||||
|
||||
internal class Store
|
||||
{
|
||||
public UInt32 SectorSize;
|
||||
public UInt32 MinSectorCount;
|
||||
}
|
||||
|
||||
// V3 exploit
|
||||
// Magic
|
||||
//
|
||||
private static byte[] GenerateCatalogFile(byte[] hashData)
|
||||
{
|
||||
byte[] catalog_first_part = new byte[] { 0x30, 0x82, 0x01, 0x44, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x01, 0x35, 0x30, 0x82, 0x01, 0x31, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x82, 0x01, 0x26, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x01, 0xA0, 0x82, 0x01, 0x17, 0x30, 0x82, 0x01, 0x13, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x01, 0x04, 0x10, 0xA8, 0xCA, 0xD9, 0x7D, 0xBF, 0x6D, 0x67, 0x4D, 0xB1, 0x4D, 0x62, 0xFB, 0xE6, 0x26, 0x22, 0xD4, 0x17, 0x0D, 0x32, 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x32, 0x31, 0x32, 0x32, 0x37, 0x5A, 0x30, 0x0E, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x02, 0x05, 0x00, 0x30, 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x04, 0x1E, 0x48, 0x00, 0x61, 0x00, 0x73, 0x00, 0x68, 0x00, 0x54, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x2E, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x62, 0x00, 0x00, 0x00, 0x31, 0x81, 0xAB, 0x30, 0x45, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x31, 0x37, 0x30, 0x35, 0x30, 0x10, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x19, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
|
||||
byte[] catalog_second_part = new byte[] { 0x30, 0x62, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x02, 0x02, 0x31, 0x54, 0x30, 0x52, 0x1E, 0x4C, 0x00, 0x7B, 0x00, 0x44, 0x00, 0x45, 0x00, 0x33, 0x00, 0x35, 0x00, 0x31, 0x00, 0x41, 0x00, 0x34, 0x00, 0x32, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x45, 0x00, 0x35, 0x00, 0x39, 0x00, 0x2D, 0x00, 0x31, 0x00, 0x31, 0x00, 0x44, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x43, 0x00, 0x34, 0x00, 0x37, 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30, 0x00, 0x43, 0x00, 0x30, 0x00, 0x34, 0x00, 0x46, 0x00, 0x43, 0x00, 0x32, 0x00, 0x39, 0x00, 0x35, 0x00, 0x45, 0x00, 0x45, 0x00, 0x7D, 0x02, 0x02, 0x02, 0x00, 0x31, 0x00 };
|
||||
|
||||
byte[] hash = new SHA1Managed().ComputeHash(hashData);
|
||||
|
||||
byte[] catalog = new byte[catalog_first_part.Length + hash.Length + catalog_second_part.Length];
|
||||
System.Buffer.BlockCopy(catalog_first_part, 0, catalog, 0, catalog_first_part.Length);
|
||||
System.Buffer.BlockCopy(hash, 0, catalog, catalog_first_part.Length, hash.Length);
|
||||
System.Buffer.BlockCopy(catalog_second_part, 0, catalog, catalog_first_part.Length + hash.Length, catalog_second_part.Length);
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
// V3 exploit
|
||||
// Magic
|
||||
//
|
||||
internal async static Task LumiaV3CustomFlash(PhoneNotifierViewModel Notifier, List<FlashPart> FlashParts, bool CheckSectorAlignment = true, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null)
|
||||
{
|
||||
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
|
||||
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
|
||||
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
|
||||
if (ExitFailure == null) ExitFailure = (m, s) => { };
|
||||
|
||||
uint chunkSize = 131072u;
|
||||
int chunkSizes = 131072;
|
||||
|
||||
if (FlashParts != null)
|
||||
{
|
||||
foreach (FlashPart Part in FlashParts)
|
||||
{
|
||||
if (Part.Stream == null)
|
||||
throw new ArgumentException("Stream is null");
|
||||
if (!Part.Stream.CanSeek)
|
||||
throw new ArgumentException("Streams must be seekable");
|
||||
if (((Part.StartSector * 0x200) % chunkSize) != 0)
|
||||
throw new ArgumentException("Invalid StartSector alignment");
|
||||
if (CheckSectorAlignment)
|
||||
{
|
||||
if ((Part.Stream.Length % chunkSize) != 0)
|
||||
throw new ArgumentException("Invalid Data length");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
|
||||
PhoneInfo 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.
|
||||
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.
|
||||
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 + ".");
|
||||
|
||||
if (Info.UefiSecureBootEnabled)
|
||||
throw new WPinternalsException("Flash failed!", "UEFI Secureboot must be disabled for the Flash V3 exploit to work.");
|
||||
|
||||
// The payloads must be ordered by the number of locations
|
||||
//
|
||||
// FlashApp processes payloads like this:
|
||||
// - First payloads which are with one location, those can be sent in bulk
|
||||
// - Then payloads with more than one location, those should not be sent in bulk
|
||||
//
|
||||
// If you do not order payloads like this, you will get an error, most likely hash mismatch
|
||||
//
|
||||
LumiaV2UnlockBootViewModel.FlashingPayload[] payloads = new LumiaV2UnlockBootViewModel.FlashingPayload[0];
|
||||
if (FlashParts != null)
|
||||
{
|
||||
payloads = LumiaV2UnlockBootViewModel.GetNonOptimizedPayloads(FlashParts, chunkSizes, (uint)(Info.WriteBufferSize / chunkSize), SetWorkingStatus, UpdateWorkingStatus).OrderBy(x => x.TargetLocations.Count()).ToArray();
|
||||
}
|
||||
|
||||
MemoryStream Headerstream1 = new MemoryStream();
|
||||
|
||||
// ==============================
|
||||
// Header 1 start
|
||||
|
||||
ImageHeader image = new ImageHeader();
|
||||
FullFlash ffimage = new FullFlash();
|
||||
Store simage = new Store();
|
||||
|
||||
// Todo make this read the image itself
|
||||
ffimage.OSVersion = "10.0.11111.0";
|
||||
ffimage.DevicePlatformId0 = Info.PlatformID;
|
||||
ffimage.AntiTheftVersion = "1.1";
|
||||
|
||||
simage.SectorSize = 512;
|
||||
simage.MinSectorCount = Info.EmmcSizeInSectors;
|
||||
|
||||
//Logging.Log("Generating image manifest...");
|
||||
string manifest = ManifestIni.BuildUpManifest(ffimage, simage);//, partitions);
|
||||
|
||||
byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(manifest);
|
||||
|
||||
image.ManifestLength = (UInt32)TextBytes.Length;
|
||||
|
||||
byte[] ImageHeaderBuffer = new byte[0x18];
|
||||
|
||||
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0, image.Size);
|
||||
ByteOperations.WriteAsciiString(ImageHeaderBuffer, 0x04, image.Signature);
|
||||
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0x10, image.ManifestLength);
|
||||
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0x14, image.ChunkSize);
|
||||
|
||||
Headerstream1.Write(ImageHeaderBuffer, 0, 0x18);
|
||||
Headerstream1.Write(TextBytes, 0, TextBytes.Length);
|
||||
|
||||
RoundUpToChunks(Headerstream1, chunkSize);
|
||||
|
||||
// Header 1 stop + round
|
||||
// ==============================
|
||||
|
||||
MemoryStream Headerstream2 = new MemoryStream();
|
||||
|
||||
// ==============================
|
||||
// Header 2 start
|
||||
|
||||
StoreHeader store = new StoreHeader();
|
||||
|
||||
store.WriteDescriptorCount = (UInt32)payloads.Count();
|
||||
store.FinalTableIndex = (UInt32)payloads.Count() - store.FinalTableCount;
|
||||
store.PlatformId = Info.PlatformID;
|
||||
|
||||
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
|
||||
{
|
||||
store.WriteDescriptorLength += payload.GetStoreHeaderSize();
|
||||
}
|
||||
|
||||
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
|
||||
{
|
||||
/*if (payload.TargetLocations.First() > PlatEnd)
|
||||
break;*/
|
||||
store.FlashOnlyTableIndex += 1;
|
||||
}
|
||||
|
||||
byte[] StoreHeaderBuffer = new byte[0xF8];
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0, store.UpdateType);
|
||||
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x04, store.MajorVersion);
|
||||
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x06, store.MinorVersion);
|
||||
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x08, store.FullFlashMajorVersion);
|
||||
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x0A, store.FullFlashMinorVersion);
|
||||
ByteOperations.WriteAsciiString(StoreHeaderBuffer, 0x0C, store.PlatformId);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xCC, store.BlockSizeInBytes);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD0, store.WriteDescriptorCount);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD4, store.WriteDescriptorLength);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD8, store.ValidateDescriptorCount);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xDC, store.ValidateDescriptorLength);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE0, store.InitialTableIndex);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE4, store.InitialTableCount);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE8, store.FlashOnlyTableIndex);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xEC, store.FlashOnlyTableCount);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xF0, store.FinalTableIndex);
|
||||
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xF4, store.FinalTableCount);
|
||||
Headerstream2.Write(StoreHeaderBuffer, 0, 0xF8);
|
||||
|
||||
byte[] descriptorsBuffer = new byte[store.WriteDescriptorLength];
|
||||
|
||||
UInt32 NewWriteDescriptorOffset = 0;
|
||||
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
|
||||
{
|
||||
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x00, (UInt32)payload.TargetLocations.Count()); // Location count
|
||||
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x04, payload.ChunkCount); // Chunk count
|
||||
NewWriteDescriptorOffset += 0x08;
|
||||
|
||||
foreach (UInt32 location in payload.TargetLocations)
|
||||
{
|
||||
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x00, 0x00000000); // Disk access method (0 = Begin, 2 = End)
|
||||
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x04, location); // Chunk index
|
||||
NewWriteDescriptorOffset += 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
Headerstream2.Write(descriptorsBuffer, 0, (Int32)store.WriteDescriptorLength);
|
||||
|
||||
RoundUpToChunks(Headerstream2, chunkSize);
|
||||
|
||||
// Header 2 stop + round
|
||||
// ==============================
|
||||
|
||||
SecurityHeader security = new SecurityHeader();
|
||||
|
||||
Headerstream1.Seek(0, SeekOrigin.Begin);
|
||||
Headerstream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
security.HashTableSize = 0x20 * (UInt32)((Headerstream1.Length + Headerstream2.Length) / chunkSize);
|
||||
|
||||
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
|
||||
{
|
||||
security.HashTableSize += payload.GetSecurityHeaderSize();
|
||||
}
|
||||
|
||||
byte[] HashTable = new byte[security.HashTableSize];
|
||||
BinaryWriter bw = new BinaryWriter(new MemoryStream(HashTable));
|
||||
|
||||
SHA256 crypto = SHA256.Create();
|
||||
for (int i = 0; i < Headerstream1.Length / chunkSize; i++)
|
||||
{
|
||||
byte[] buffer = new byte[chunkSize];
|
||||
Headerstream1.Read(buffer, 0, (Int32)chunkSize);
|
||||
byte[] hash = crypto.ComputeHash(buffer);
|
||||
bw.Write(hash, 0, hash.Length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Headerstream2.Length / chunkSize; i++)
|
||||
{
|
||||
byte[] buffer = new byte[chunkSize];
|
||||
Headerstream2.Read(buffer, 0, (Int32)chunkSize);
|
||||
byte[] hash = crypto.ComputeHash(buffer);
|
||||
bw.Write(hash, 0, hash.Length);
|
||||
}
|
||||
|
||||
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
|
||||
{
|
||||
bw.Write(payload.ChunkHashes[0], 0, payload.ChunkHashes[0].Length);
|
||||
}
|
||||
|
||||
bw.Close();
|
||||
|
||||
//Logging.Log("Generating image catalog...");
|
||||
byte[] catalog = GenerateCatalogFile(HashTable);
|
||||
|
||||
security.CatalogSize = (UInt32)catalog.Length;
|
||||
|
||||
byte[] SecurityHeaderBuffer = new byte[0x20];
|
||||
|
||||
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0, security.Size);
|
||||
ByteOperations.WriteAsciiString(SecurityHeaderBuffer, 0x04, security.Signature);
|
||||
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x10, security.ChunkSizeInKb);
|
||||
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x14, security.HashAlgorithm);
|
||||
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x18, security.CatalogSize);
|
||||
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x1C, security.HashTableSize);
|
||||
|
||||
MemoryStream retstream = new MemoryStream();
|
||||
|
||||
retstream.Write(SecurityHeaderBuffer, 0, 0x20);
|
||||
|
||||
retstream.Write(catalog, 0, (Int32)security.CatalogSize);
|
||||
retstream.Write(HashTable, 0, (Int32)security.HashTableSize);
|
||||
|
||||
RoundUpToChunks(retstream, chunkSize);
|
||||
|
||||
Headerstream1.Seek(0, SeekOrigin.Begin);
|
||||
Headerstream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
byte[] buff = new byte[Headerstream1.Length];
|
||||
Headerstream1.Read(buff, 0, (Int32)Headerstream1.Length);
|
||||
|
||||
Headerstream1.Close();
|
||||
|
||||
retstream.Write(buff, 0, buff.Length);
|
||||
|
||||
buff = new byte[Headerstream2.Length];
|
||||
Headerstream2.Read(buff, 0, (Int32)Headerstream2.Length);
|
||||
|
||||
Headerstream2.Close();
|
||||
|
||||
retstream.Write(buff, 0, buff.Length);
|
||||
|
||||
// --------
|
||||
|
||||
// Go back to the beginning
|
||||
retstream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
byte[] FfuHeader = new byte[retstream.Length];
|
||||
await retstream.ReadAsync(FfuHeader, 0, (int)retstream.Length);
|
||||
retstream.Close();
|
||||
|
||||
byte Options = 0;
|
||||
if (!Info.IsBootloaderSecure)
|
||||
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
|
||||
|
||||
LogFile.Log("Flash in progress...", LogType.ConsoleOnly);
|
||||
SetWorkingStatus("Flashing...", null, (UInt64?)payloads.Count(), Status: WPinternalsStatus.Flashing);
|
||||
|
||||
Model.SendFfuHeaderV1(FfuHeader, Options);
|
||||
|
||||
UInt64 counter = 0;
|
||||
|
||||
int numberOfPayloadsToSendAtOnce = (int)Math.Round((double)Info.WriteBufferSize / chunkSize);
|
||||
byte[] payloadBuffer;
|
||||
|
||||
for (int i = 0; i < payloads.Count(); i+= numberOfPayloadsToSendAtOnce)
|
||||
{
|
||||
if (i + numberOfPayloadsToSendAtOnce - 1 >= payloads.Count())
|
||||
{
|
||||
numberOfPayloadsToSendAtOnce = payloads.Count() - i;
|
||||
}
|
||||
|
||||
payloadBuffer = new byte[numberOfPayloadsToSendAtOnce * chunkSizes];
|
||||
|
||||
string ProgressText = "Flashing resources";
|
||||
|
||||
for (int j = 0; j < numberOfPayloadsToSendAtOnce; j++)
|
||||
{
|
||||
LumiaV2UnlockBootViewModel.FlashingPayload payload = payloads[i + j];
|
||||
|
||||
UInt32 StreamIndex = payload.StreamIndexes.First();
|
||||
FlashPart flashPart = FlashParts[(int)StreamIndex];
|
||||
|
||||
if (flashPart.ProgressText != null)
|
||||
ProgressText = flashPart.ProgressText;
|
||||
|
||||
Stream Stream = flashPart.Stream;
|
||||
Stream.Seek(payload.StreamLocations.First(), SeekOrigin.Begin);
|
||||
Stream.Read(payloadBuffer, j * chunkSizes, chunkSizes);
|
||||
counter++;
|
||||
}
|
||||
|
||||
Model.SendFfuPayloadV2(payloadBuffer, int.Parse((counter * 100 / (ulong)payloads.Count()).ToString()));
|
||||
UpdateWorkingStatus(ProgressText, null, counter, WPinternalsStatus.Flashing);
|
||||
}
|
||||
|
||||
Model.ResetPhone();
|
||||
|
||||
await Notifier.WaitForRemoval();
|
||||
|
||||
ExitSuccess("Flash succeeded!", null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new WPinternalsException("Custom flash failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,7 +272,7 @@ namespace WPinternals
|
||||
LogFile.Log("Bootloader Security Authentication Status: " + BootloaderSecurityAuthenticationStatus.ToString());
|
||||
BootloaderSecurityRdcStatus = Info.RdcPresent;
|
||||
LogFile.Log("Bootloader Security Rdc Status: " + BootloaderSecurityRdcStatus.ToString());
|
||||
EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent;
|
||||
EffectiveBootloaderSecurityStatus = !Info.IsBootloaderSecure;
|
||||
LogFile.Log("Effective Bootloader Security Status: " + EffectiveBootloaderSecurityStatus.ToString());
|
||||
|
||||
NativeDebugStatus = !Info.JtagDisabled;
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace WPinternals
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent;
|
||||
EffectiveBootloaderSecurityStatus = !Info.IsBootloaderSecure;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -229,13 +229,22 @@ namespace WPinternals
|
||||
}
|
||||
else if ((e.DevicePath.IndexOf("&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_0714 is for Lumia 930
|
||||
(e.DevicePath.IndexOf("&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_045E&PID_0A02 is for Lumia 950
|
||||
(e.DevicePath.IndexOf("&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_045E&PID_0A02 is for Lumia 950
|
||||
(e.DevicePath.IndexOf("&PID_05EE", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_0421&PID_05EE is for early RX100
|
||||
{
|
||||
CurrentModel = new NokiaFlashModel(e.DevicePath);
|
||||
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
|
||||
|
||||
FlashAppType type = ((NokiaFlashModel)CurrentModel).GetFlashAppType();
|
||||
LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly);
|
||||
FlashAppType type = FlashAppType.FlashApp;
|
||||
try
|
||||
{
|
||||
type = ((NokiaFlashModel)CurrentModel).GetFlashAppType();
|
||||
LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogFile.Log("Flash App Type could not be determined, assuming " + type.ToString(), LogType.FileOnly);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -406,6 +415,7 @@ namespace WPinternals
|
||||
(e.DevicePath.IndexOf("VID_0421&PID_06FC", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_0421&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_0421&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_0421&PID_05EE", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
(e.DevicePath.IndexOf("VID_05C6&PID_9008", StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
|
||||
@@ -641,7 +641,7 @@ namespace WPinternals
|
||||
GPT GPT = FlashModel.ReadGPT();
|
||||
IsUnlockedNew = ((GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null));
|
||||
}
|
||||
bool IsOriginalEngineeringLumia = ((!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent) && !IsUnlockedNew);
|
||||
bool IsOriginalEngineeringLumia = (!Info.IsBootloaderSecure && !IsUnlockedNew);
|
||||
|
||||
if (IsOldLumia || IsOriginalEngineeringLumia)
|
||||
{
|
||||
@@ -650,7 +650,7 @@ namespace WPinternals
|
||||
byte[] RebootToMassStorageCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x4D }; // NOKM
|
||||
IsSwitchingInterface = true;
|
||||
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
|
||||
if ((RebootCommandResult != null) && (RebootCommandResult.Length == 4)) // This means fail: NOKU (unknow command)
|
||||
if ((RebootCommandResult != null) && (RebootCommandResult.Length == 4)) // This means fail: NOKU (unknown command)
|
||||
{
|
||||
BootModeFlagCommand[0x0F] = 0x4D;
|
||||
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
|
||||
|
||||
@@ -928,6 +928,7 @@
|
||||
<Compile Include="ViewModels\BusyViewModel.cs" />
|
||||
<Compile Include="ViewModels\DisclaimerAndNdaViewModel.cs" />
|
||||
<Compile Include="ViewModels\DownloadsViewModel.cs" />
|
||||
<Compile Include="ViewModels\LumiaV3FlashRomViewModel.cs" />
|
||||
<Compile Include="ViewModels\NokiaBootloaderViewModel.cs" />
|
||||
<Compile Include="ViewModels\NokiaModeBootloaderViewModel.cs" />
|
||||
<Compile Include="ViewModels\RegistrationViewModel.cs" />
|
||||
|
||||
+89
-88
@@ -4,6 +4,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
VisualStudioVersion = 16.0.29123.89
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPinternals", "WPinternals.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPinternals.Core", "WPinternals.Core.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6F}"
|
||||
EndProject
|
||||
Global
|
||||
@@ -54,6 +55,94 @@ Global
|
||||
Release-Test|Any CPU = Release-Test|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.ActiveCfg = Debug-Test|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.Build.0 = Debug-Test|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
@@ -142,94 +231,6 @@ Global
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release-Test|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Reference in New Issue
Block a user