internal async void DoUnlockPhone() { try { IsSwitchingInterface = true; await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); bool HasNewBootloader = HasNewBootloaderFromMassStorage(); string EFIESPPath = HasNewBootloader ? null : ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\EFIESP\"; string MainOSPath = ((MassStorage)PhoneNotifier.CurrentModel).Drive + @"\"; bool HasV11Patches = HasV11PatchesFromMassStorage(); StartPatch(EFIESPPath, MainOSPath, HasNewBootloader, HasV11Patches); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, () => { Callback(); ActivateSubContext(null); })); } }
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 InterruptBootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { App.InterruptBoot = (bool)e.NewValue; if ((bool)e.NewValue && PhoneNotifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader) { App.InterruptBoot = false; LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); } }
internal 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 TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath) { LogFile.BeginAction("TestProgrammer"); try { LogFile.Log("Starting Firehose Test", LogType.FileAndConsole); PhoneNotifierViewModel Notifier = new(); 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.", "Could not switch the phone to Qualcomm Emergency 9008."); } LogFile.Log("Phone is in emergency mode.", LogType.FileAndConsole); } // Send and start programmer QualcommSerial Serial = (QualcommSerial)Notifier.CurrentModel; QualcommSahara Sahara = new(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 async void DoBackup(string EFIESPPath, string MainOSPath, string DataPath) { try { IsSwitchingInterface = true; await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); BackupTask(EFIESPPath, MainOSPath, DataPath); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
internal async void DoBackupArchiveProvisioning(string ArchiveProvisioningPath) { try { IsSwitchingInterface = true; await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_MassStorage, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); BackupArchiveProvisioningTask(ArchiveProvisioningPath); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
internal async void DoRestore(string EFIESPPath, string MainOSPath, string DataPath) { try { await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); RestoreTask(EFIESPPath, MainOSPath, DataPath); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
// Called from an event-handler. So, "async void" is valid here. internal async void FlashMMOS(string MMOSPath) { IsSwitchingInterface = true; // Prevents that a device is forced to Flash mode on this screen which is meant for flashing try { await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); FlashMMOSTask(MMOSPath); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
internal async void Exit() { IsSwitchingInterface = false; try { await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Normal, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); Callback(); ActivateSubContext(null); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args) { PhoneInterfaces?PreviousInterface = LastInterface; LastInterface = Args.NewInterface; if (App.InterruptBoot && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader)) { App.InterruptBoot = false; LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); } else { if (Args.NewInterface != PhoneInterfaces.Qualcomm_Download) { App.InterruptBoot = false; } if (ContextViewModel == null) { ContextViewModel = InfoViewModel; } else if (ContextViewModel.IsFlashModeOperation) { if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface == PhoneInterfaces.Lumia_Bootloader)) { // The current screen is marked as "Flash operation". // When the bootloader is detected at this stage, it means a phone is booting and // it is possible that the phone is in a non-booting stage (not possible to boot past UEFI). // We will try to boot straight to Flash-mode, so that it will be possible to flash a new ROM. LogFile.Log("Found Lumia BootMgr while mode is not being switched. Screen is marked as Flash Operation. Force to Flash-mode."); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); } } else { if ((!ContextViewModel.IsSwitchingInterface) && (Args.NewInterface != PhoneInterfaces.Lumia_Bootloader)) { ContextViewModel = InfoViewModel; } } } }
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); }
private void SwitchToFlashMode() { // SwitchModeViewModel must be created on the UI thread IsSwitchingInterface = true; UIContext.Post(async(t) => { LogFile.Log("Switching to Flash-mode"); try { await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }, null); }
// Called from eventhandler, so "async void" is valid here. internal async void OnModeSwitchRequested(PhoneInterfaces?TargetInterface) { IsSwitchingInterface = true; try { await SwitchModeViewModel.SwitchToWithStatus(PhoneNotifier, TargetInterface, SetWorkingStatus, UpdateWorkingStatus, null); // This is a manual switch. We don't care about which volume arrives. IsSwitchingInterface = false; Callback(); Refresh(); } catch (Exception Ex) { IsSwitchingInterface = false; ActivateSubContext(new MessageViewModel(Ex.Message, () => { Callback(); Refresh(); })); } }
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)); } } }
// Called from an event-handler. So, "async void" is valid here. internal async void FlashPartitions(string EFIESPPath, string MainOSPath, string DataPath) { IsSwitchingInterface = true; // Prevents that a device is forced to Flash mode on this screen which is meant for flashing try { await SwitchModeViewModel.SwitchToWithProgress(PhoneNotifier, PhoneInterfaces.Lumia_Flash, (msg, sub) => ActivateSubContext(new BusyViewModel(msg, sub))); if (((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo(ExtendedInfo: false).FlashAppProtocolVersionMajor < 2) { FlashPartitionsTask(EFIESPPath, MainOSPath, DataPath); } else { await Task.Run(async() => await LumiaV2UnlockBootViewModel.LumiaV2FlashPartitions(PhoneNotifier, EFIESPPath, MainOSPath, DataPath, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure)); } } catch (Exception Ex) { ActivateSubContext(new MessageViewModel(Ex.Message, Callback)); } }
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 void PhoneNotifier_NewDeviceArrived(ArrivalEventArgs Args) { if (App.InterruptBoot && Args.NewInterface == PhoneInterfaces.Lumia_Bootloader) { App.InterruptBoot = false; LogFile.Log("Found Lumia BootMgr and user forced to interrupt the boot process. Force to Flash-mode."); Task.Run(() => SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Lumia_Flash)); } UIContext.Send(s => { if (!App.InterruptBoot && Args.NewInterface == PhoneInterfaces.Lumia_Bootloader) { StatusText.Content = "Phone is booting..."; GifImage.Visibility = Visibility.Visible; } if (!App.InterruptBoot && Args.NewInterface != PhoneInterfaces.Lumia_Bootloader) { StatusText.Content = "Waiting for connection with phone..."; GifImage.Visibility = Visibility.Collapsed; } }, null); }
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(); }