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 SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces?TargetMode) : base() { if ((PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Flash) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Label) && (PhoneNotifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)) { throw new ArgumentException(); } this.PhoneNotifier = PhoneNotifier; this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel; this.CurrentMode = PhoneNotifier.CurrentInterface; this.TargetMode = TargetMode; if (this.CurrentMode == null) { LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole); PhoneNotifier.NewDeviceArrived += NewDeviceArrived; } else { // Make sure this ViewModel has its View loaded before we continue, // or else loading of Views can get mixed up. if (SynchronizationContext.Current == null) { StartSwitch(); } else { SynchronizationContext.Current.Post((s) => { ((SwitchModeViewModel)s).StartSwitch(); }, this); } } }
internal BackupViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action Callback) : base() { IsFlashModeOperation = true; this.PhoneNotifier = PhoneNotifier; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.Callback = Callback; }
internal DownloadsViewModel(PhoneNotifierViewModel Notifier) { IsSwitchingInterface = false; IsFlashModeOperation = false; this.Notifier = Notifier; Notifier.NewDeviceArrived += Notifier_NewDeviceArrived; RegistryKey Key = Registry.CurrentUser.OpenSubKey(@"Software\WPInternals", true); if (Key == null) { Key = Registry.CurrentUser.CreateSubKey(@"Software\WPInternals"); } DownloadFolder = (string)Key.GetValue("DownloadFolder", @"C:\ProgramData\WPinternals\Repository"); Key.Close(); SpeedTimer = new Timer(TimerCallback, this, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); AddFFUCommand = new DelegateCommand(() => { string FFUPath = null; Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.DefaultExt = ".ffu"; // Default file extension dlg.Filter = "ROM images (.ffu)|*.ffu"; // Filter files by extension bool?result = dlg.ShowDialog(); if (result == true) { FFUPath = dlg.FileName; string FFUFile = System.IO.Path.GetFileName(FFUPath); try { App.Config.AddFfuToRepository(FFUPath); App.Config.WriteConfig(); LastStatusText = "File \"" + FFUFile + "\" was added to the repository."; } catch (WPinternalsException Ex) { LastStatusText = "Error: " + Ex.Message + ". File \"" + FFUFile + "\" was not added."; } catch { LastStatusText = "Error: File \"" + FFUFile + "\" was not added."; } } else { LastStatusText = null; } }); }
internal RestoreViewModel(PhoneNotifierViewModel PhoneNotifier, Action <PhoneInterfaces> RequestModeSwitch, Action SwitchToUnlockBoot, Action SwitchToFlashRom, Action Callback) : base() { IsSwitchingInterface = true; this.PhoneNotifier = PhoneNotifier; this.Callback = Callback; this.RequestModeSwitch = RequestModeSwitch; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToFlashRom = SwitchToFlashRom; }
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 LumiaModeViewModel(PhoneNotifierViewModel PhoneNotifier, Action Callback) : base() { this.PhoneNotifier = PhoneNotifier; this.Callback = Callback; CurrentInterface = PhoneNotifier.CurrentInterface; CurrentModel = PhoneNotifier.CurrentModel; PhoneNotifier.NewDeviceArrived += NewDeviceArrived; PhoneNotifier.DeviceRemoved += DeviceRemoved; }
internal BackupTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action <string> BackupArchiveCallback, Action <string, string, string> BackupCallback) : base() { this.PhoneNotifier = PhoneNotifier; this.BackupCallback = BackupCallback; this.BackupArchiveCallback = BackupArchiveCallback; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.DeviceRemoved += DeviceRemoved; new Thread(() => EvaluateViewState()).Start(); }
private void Empty_Loaded(object sender, RoutedEventArgs e) { // Find the phone notifier DependencyObject obj = (DependencyObject)sender; while (!(obj is MainWindow)) { obj = VisualTreeHelper.GetParent(obj); } PhoneNotifier = ((MainViewModel)(((MainWindow)obj).DataContext)).PhoneNotifier; PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived; }
internal LumiaUnlockRootViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, bool DoUnlock, Action Callback) : base() { IsSwitchingInterface = false; IsFlashModeOperation = true; this.PhoneNotifier = PhoneNotifier; this.SwitchToDumpRom = SwitchToDumpRom; this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.DoUnlock = DoUnlock; this.Callback = Callback; }
internal LumiaFlashRomViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToDumpFFU, Action SwitchToBackup, Action Callback) : base() { IsSwitchingInterface = false; IsFlashModeOperation = true; this.PhoneNotifier = PhoneNotifier; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToDumpFFU = SwitchToDumpFFU; this.SwitchToBackup = SwitchToBackup; this.Callback = Callback; }
internal LumiaInfoViewModel(PhoneNotifierViewModel PhoneNotifier, Action <PhoneInterfaces> ModeSwitchRequestCallback, Action SwitchToGettingStarted) : base() { this.PhoneNotifier = PhoneNotifier; this.ModeSwitchRequestCallback = ModeSwitchRequestCallback; this.SwitchToGettingStarted = SwitchToGettingStarted; CurrentInterface = PhoneNotifier.CurrentInterface; CurrentModel = PhoneNotifier.CurrentModel; PhoneNotifier.NewDeviceArrived += NewDeviceArrived; PhoneNotifier.DeviceRemoved += DeviceRemoved; }
internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath) { LogFile.BeginAction("TestProgrammer"); try { LogFile.Log("Starting Firehose Test", LogType.FileAndConsole); PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel(); UIContext.Send(s => Notifier.Start(), null); if (Notifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download) { LogFile.Log("Phone found in emergency mode", LogType.FileAndConsole); } else { LogFile.Log("Phone needs to be switched to emergency mode.", LogType.FileAndConsole); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_Flash); PhoneInfo Info = ((NokiaFlashModel)Notifier.CurrentModel).ReadPhoneInfo(); Info.Log(LogType.ConsoleOnly); await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Qualcomm_Download); if (Notifier.CurrentInterface != PhoneInterfaces.Qualcomm_Download) { throw new WPinternalsException("Switching mode failed."); } LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole); } // Send and start programmer QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel; QualcommSahara Sahara = new QualcommSahara(Serial); if (await Sahara.Reset(ProgrammerPath)) { LogFile.Log("Emergency programmer test succeeded", LogType.FileAndConsole); } else { LogFile.Log("Emergency programmer test failed", LogType.FileAndConsole); } } catch (Exception Ex) { LogFile.LogException(Ex); } finally { LogFile.EndAction("TestProgrammer"); } }
internal RestoreSourceSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action <PhoneInterfaces> RequestModeSwitch, Action SwitchToUnlockBoot, Action SwitchToFlashRom, Action <string, string, string> RestoreCallback) : base() { this.PhoneNotifier = PhoneNotifier; this.RestoreCallback = RestoreCallback; this.RequestModeSwitch = RequestModeSwitch; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToFlashRom = SwitchToFlashRom; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.DeviceRemoved += DeviceRemoved; new Thread(() => EvaluateViewState()).Start(); }
internal LumiaRootAccessTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action <string, string> UnlockImageCallback) : base() { this.PhoneNotifier = PhoneNotifier; this.SwitchToDumpRom = SwitchToDumpRom; this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.UnlockPhoneCallback = UnlockPhoneCallback; this.UnlockImageCallback = UnlockImageCallback; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.DeviceRemoved += DeviceRemoved; new Thread(() => EvaluateViewState()).Start(); }
internal LumiaFlashRomSourceSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToUnlockRoot, Action SwitchToDumpFFU, Action SwitchToBackup, Action <string, string, string> FlashPartitionsCallback, Action <string> FlashArchiveCallback, Action <string> FlashFFUCallback) : base() { this.PhoneNotifier = PhoneNotifier; this.SwitchToUnlockBoot = SwitchToUnlockBoot; this.SwitchToUnlockRoot = SwitchToUnlockRoot; this.SwitchToDumpFFU = SwitchToDumpFFU; this.SwitchToBackup = SwitchToBackup; this.FlashPartitionsCallback = FlashPartitionsCallback; this.FlashArchiveCallback = FlashArchiveCallback; this.FlashFFUCallback = FlashFFUCallback; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; this.PhoneNotifier.DeviceRemoved += DeviceRemoved; new Thread(() => EvaluateViewState()).Start(); }
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 LumiaUnlockBootViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToFlashRom, Action SwitchToUndoRoot, Action SwitchToDownload, bool DoUnlock, Action Callback) : base() { IsSwitchingInterface = false; IsFlashModeOperation = true; this.PhoneNotifier = PhoneNotifier; this.SwitchToFlashRom = SwitchToFlashRom; this.SwitchToUndoRoot = SwitchToUndoRoot; this.SwitchToDownload = SwitchToDownload; this.DoUnlock = DoUnlock; this.Callback = Callback; State = MachineState.Default; this.PhoneNotifier.NewDeviceArrived += NewDeviceArrived; // ViewState will be evaluated as soon as this object is set as DataContext }
internal static void InterruptBootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { App.InterruptBoot = (bool)e.NewValue; if ((bool)e.NewValue) { // Find the phone notifier DependencyObject obj = d; while (!(obj is MainWindow)) { obj = VisualTreeHelper.GetParent(obj); } PhoneNotifierViewModel PhoneNotifier = ((MainViewModel)(((MainWindow)obj).DataContext)).PhoneNotifier; if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { App.InterruptBoot = false; LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); } } }
internal async static Task <IDisposable> SwitchToWithStatus(PhoneNotifierViewModel Notifier, PhoneInterfaces?TargetMode, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, string RequestedVolumeForMassStorage = "MainOS") { if (Notifier.CurrentInterface == TargetMode) { return(Notifier.CurrentModel); } IDisposable Result = null; string LocalErrorMessage = null; AsyncAutoResetEvent Event = new AsyncAutoResetEvent(false); SwitchModeViewModel Switch = new SwitchModeViewModel( Notifier, TargetMode, null, (string ErrorMessage) => { LocalErrorMessage = ErrorMessage; Event.Set(); }, (IDisposable NewModel, PhoneInterfaces NewInterface) => { Result = NewModel; Event.Set(); }, SetWorkingStatus, UpdateWorkingStatus ); await Event.WaitAsync(Timeout.InfiniteTimeSpan); if (LocalErrorMessage != null) { throw new WPinternalsException(LocalErrorMessage); } return(Result); }
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(); }
public void StartOperation() { IsMenuEnabled = true; _GettingStartedViewModel = new GettingStartedViewModel( () => { ContextViewModel = new DisclaimerViewModel( () => ContextViewModel = _GettingStartedViewModel ); }, SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToBackup, SwitchToDumpFFU, SwitchToFlashRom, SwitchToDownload ); this.ContextViewModel = _GettingStartedViewModel; PhoneNotifier = new PhoneNotifierViewModel(); PhoneNotifier.NewDeviceArrived += PhoneNotifier_NewDeviceArrived; PhoneNotifier.DeviceRemoved += PhoneNotifier_DeviceRemoved; InfoViewModel = new LumiaInfoViewModel(PhoneNotifier, (TargetInterface) => { ModeViewModel.OnModeSwitchRequested(TargetInterface); ContextViewModel = ModeViewModel; }, () => { ContextViewModel = _GettingStartedViewModel; }); InfoViewModel.ActivateSubContext(null); ModeViewModel = new LumiaModeViewModel(PhoneNotifier, SwitchToInfoViewModel); ModeViewModel.ActivateSubContext(null); BootUnlockViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, true, SwitchToInfoViewModel); BootUnlockViewModel.ActivateSubContext(null); BootRestoreViewModel = new LumiaUnlockBootViewModel(PhoneNotifier, SwitchToFlashRom, SwitchToUndoRoot, SwitchToDownload, false, SwitchToInfoViewModel); BootRestoreViewModel.ActivateSubContext(null); RootUnlockViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, true, SwitchToInfoViewModel); RootUnlockViewModel.ActivateSubContext(null); RootRestoreViewModel = new LumiaUnlockRootViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpFFU, SwitchToFlashRom, false, SwitchToInfoViewModel); RootRestoreViewModel.ActivateSubContext(null); BackupViewModel = new BackupViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToInfoViewModel); BackupViewModel.ActivateSubContext(null); RestoreViewModel = new RestoreViewModel(PhoneNotifier, SwitchToDifferentInterface, SwitchToUnlockBoot, SwitchToFlashRom, SwitchToInfoViewModel); RestoreViewModel.ActivateSubContext(null); LumiaFlashRomViewModel = new LumiaFlashRomViewModel(PhoneNotifier, SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToDumpFFU, SwitchToBackup, SwitchToInfoViewModel); LumiaFlashRomViewModel.ActivateSubContext(null); DumpRomViewModel = new DumpRomViewModel(SwitchToUnlockBoot, SwitchToUnlockRoot, SwitchToFlashRom); DumpRomViewModel.ActivateSubContext(null); DownloadsViewModel = new DownloadsViewModel(PhoneNotifier); App.DownloadManager = DownloadsViewModel; PhoneNotifier.Start(); }
internal SwitchModeViewModel(PhoneNotifierViewModel PhoneNotifier, PhoneInterfaces?TargetMode, ModeSwitchProgressHandler ModeSwitchProgress, ModeSwitchErrorHandler ModeSwitchError, ModeSwitchSuccessHandler ModeSwitchSuccess, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null) : base() { if ((PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) && (TargetMode == PhoneInterfaces.Lumia_Flash)) { PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(false); if (Info.BootManagerProtocolVersionMajor >= 2) { try { // The implementation of SwitchToFlashAppContext() is improved // SwitchToFlashAppContext() should only be used with BootMgr v2 // For switching from BootMgr to FlashApp, it will use NOKS // That will switch to a charging state, whereas a normal context switch will not start charging // The implementation of NOKS in BootMgr mode has changed in BootMgr v2 // It does not disconnect / reconnect anymore and the apptype is changed immediately // NOKS still doesnt return a status // BootMgr v1 uses normal NOKS and waits for arrival of FlashApp ((NokiaFlashModel)PhoneNotifier.CurrentModel).SwitchToFlashAppContext(); // But this was called as a real switch, so we will raise an arrival event. PhoneNotifier.CurrentInterface = PhoneInterfaces.Lumia_Flash; PhoneNotifier.NotifyArrival(); } catch { } } } if (PhoneNotifier.CurrentInterface == TargetMode) { ModeSwitchSuccess(PhoneNotifier.CurrentModel, (PhoneInterfaces)PhoneNotifier.CurrentInterface); } else { this.PhoneNotifier = PhoneNotifier; this.CurrentModel = (NokiaPhoneModel)PhoneNotifier.CurrentModel; this.CurrentMode = PhoneNotifier.CurrentInterface; this.TargetMode = TargetMode; if (ModeSwitchProgress != null) { this.ModeSwitchProgress += ModeSwitchProgress; } if (ModeSwitchError != null) { this.ModeSwitchError += ModeSwitchError; } if (ModeSwitchSuccess != null) { this.ModeSwitchSuccess += ModeSwitchSuccess; } if (SetWorkingStatus != null) { this.SetWorkingStatus = SetWorkingStatus; } if (UpdateWorkingStatus != null) { this.UpdateWorkingStatus = UpdateWorkingStatus; } if (this.CurrentMode == null) { LogFile.Log("Waiting for phone to connect...", LogType.FileAndConsole); PhoneNotifier.NewDeviceArrived += NewDeviceArrived; } else { // Make sure this ViewModel has its View loaded before we continue, // or else loading of Views can get mixed up. if (SynchronizationContext.Current == null) { StartSwitch(); } else { SynchronizationContext.Current.Post((s) => { ((SwitchModeViewModel)s).StartSwitch(); }, this); } } } }
internal async static Task <IDisposable> SwitchTo(PhoneNotifierViewModel Notifier, PhoneInterfaces?TargetMode, string RequestedVolumeForMassStorage = "MainOS") { return(await SwitchToWithProgress(Notifier, TargetMode, null, RequestedVolumeForMassStorage)); }
// 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"); } } } }
public LumiaUndoRootTargetSelectionViewModel(PhoneNotifierViewModel PhoneNotifier, Action SwitchToUnlockBoot, Action SwitchToDumpRom, Action SwitchToFlashRom, Action UnlockPhoneCallback, Action <string, string> UnlockImageCallback) : base(PhoneNotifier, SwitchToUnlockBoot, SwitchToDumpRom, SwitchToFlashRom, UnlockPhoneCallback, UnlockImageCallback) { }