internal void FlashPartitionsTask(string EFIESPPath, string MainOSPath, string DataPath) { new Thread(() => { bool Result = true; ActivateSubContext(new BusyViewModel("Initializing flash...")); NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; GPT GPT = Phone.ReadGPT(); ulong TotalSizeSectors = 0; int PartitionCount = 0; ulong MainOSOldSectorCount = 0; ulong MainOSNewSectorCount = 0; ulong DataOldSectorCount = 0; ulong DataNewSectorCount = 0; ulong FirstMainOSSector = 0; try { if (EFIESPPath != null) { using (Stream Stream = new DecompressedStream(File.Open(EFIESPPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "EFIESP", true) == 0).FirstOrDefault(); if (StreamLengthInSectors > Partition.SizeInSectors) { LogFile.Log("Flash failed! Size of partition 'EFIESP' is too big."); ExitFailure("Flash failed!", "Size of partition 'EFIESP' is too big."); return; } } } if (MainOSPath != null) { using (Stream Stream = new DecompressedStream(File.Open(MainOSPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).FirstOrDefault(); MainOSOldSectorCount = Partition.SizeInSectors; MainOSNewSectorCount = StreamLengthInSectors; FirstMainOSSector = Partition.FirstSector; } } if (DataPath != null) { using (Stream Stream = new DecompressedStream(File.Open(DataPath, FileMode.Open))) { ulong StreamLengthInSectors = (ulong)Stream.Length / 0x200; TotalSizeSectors += StreamLengthInSectors; PartitionCount++; Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).FirstOrDefault(); DataOldSectorCount = Partition.SizeInSectors; DataNewSectorCount = StreamLengthInSectors; } } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } if ((MainOSNewSectorCount > 0) && (DataNewSectorCount > 0)) { if ((MainOSNewSectorCount > MainOSOldSectorCount) || (DataNewSectorCount > DataOldSectorCount)) { UInt64 OSSpace = GPT.LastUsableSector - FirstMainOSSector + 1; if ((MainOSNewSectorCount + DataNewSectorCount) <= OSSpace) { // MainOS and Data partitions need to be re-aligned! Partition MainOSPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).Single(); Partition DataPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).Single(); MainOSPartition.LastSector = MainOSPartition.FirstSector + MainOSNewSectorCount - 1; DataPartition.FirstSector = MainOSPartition.LastSector + 1; DataPartition.LastSector = DataPartition.FirstSector + DataNewSectorCount - 1; Phone.WriteGPT(GPT); } else { LogFile.Log("Flash failed! Size of partitions 'MainOS' and 'Data' together are too big."); ExitFailure("Flash failed!", "Sizes of partitions 'MainOS' and 'Data' together are too big."); return; } } } else if ((MainOSNewSectorCount > 0) && (MainOSNewSectorCount > MainOSOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'MainOS' is too big."); ExitFailure("Flash failed!", "Size of partition 'MainOS' is too big."); return; } else if ((DataNewSectorCount > 0) && (DataNewSectorCount > DataOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'Data' is too big."); ExitFailure("Flash failed!", "Size of partition 'Data' together is too big."); return; } BusyViewModel Busy = new BusyViewModel("Flashing...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; if (Result) { try { if (EFIESPPath != null) { i++; Busy.Message = "Flashing partition EFIESP (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(EFIESPPath, "EFIESP", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (MainOSPath != null) { i++; Busy.Message = "Flashing partition MainOS (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(MainOSPath, "MainOS", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (Result) { try { if (DataPath != null) { i++; Busy.Message = "Flashing partition Data (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(DataPath, "Data", Updater); } } catch (Exception Ex) { LogFile.LogException(Ex); Result = false; } } if (!Result) { ExitFailure("Flash failed!", null); return; } ExitSuccess("Flash successful! Make sure you disable Windows Update on the phone!", null); }).Start(); }
internal void FlashArchiveTask(string ArchivePath) { new Thread(() => { ActivateSubContext(new BusyViewModel("Initializing flash...")); NokiaFlashModel Phone = (NokiaFlashModel)PhoneNotifier.CurrentModel; ulong TotalSizeSectors = 0; int PartitionCount = 0; ulong MainOSOldSectorCount = 0; ulong MainOSNewSectorCount = 0; ulong DataOldSectorCount = 0; ulong DataNewSectorCount = 0; ulong FirstMainOSSector = 0; bool GPTChanged = false; try { GPT GPT = Phone.ReadGPT(); using (FileStream FileStream = new FileStream(ArchivePath, FileMode.Open)) { using (ZipArchive Archive = new ZipArchive(FileStream, ZipArchiveMode.Read)) { foreach (ZipArchiveEntry Entry in Archive.Entries) { // Determine if there is a partition layout present ZipArchiveEntry PartitionEntry = Archive.GetEntry("Partitions.xml"); if (PartitionEntry == null) { GPT.MergePartitions(null, false, Archive); GPTChanged |= GPT.HasChanged; } else { using (Stream ZipStream = PartitionEntry.Open()) { using (StreamReader ZipReader = new StreamReader(ZipStream)) { string PartitionXml = ZipReader.ReadToEnd(); GPT.MergePartitions(PartitionXml, false, Archive); GPTChanged |= GPT.HasChanged; } } } // First determine if we need a new GPT! if (!Entry.FullName.Contains("/")) // No subfolders { string PartitionName = System.IO.Path.GetFileNameWithoutExtension(Entry.Name); int P = PartitionName.IndexOf('.'); if (P >= 0) { PartitionName = PartitionName.Substring(0, P); // Example: Data.bin.gz -> Data } Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, PartitionName, true) == 0).FirstOrDefault(); if (Partition != null) { DecompressedStream DecompressedStream = new DecompressedStream(Entry.Open()); ulong StreamLengthInSectors = (ulong)Entry.Length / 0x200; try { StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; } catch { } TotalSizeSectors += StreamLengthInSectors; PartitionCount++; if (string.Compare(PartitionName, "MainOS", true) == 0) { MainOSOldSectorCount = Partition.SizeInSectors; MainOSNewSectorCount = StreamLengthInSectors; FirstMainOSSector = Partition.FirstSector; } else if (string.Compare(PartitionName, "Data", true) == 0) { DataOldSectorCount = Partition.SizeInSectors; DataNewSectorCount = StreamLengthInSectors; } else if (StreamLengthInSectors > Partition.SizeInSectors) { LogFile.Log("Flash failed! Size of partition '" + PartitionName + "' is too big."); ExitFailure("Flash failed!", "Size of partition '" + PartitionName + "' is too big."); return; } } } } if ((MainOSNewSectorCount > 0) && (DataNewSectorCount > 0)) { if ((MainOSNewSectorCount > MainOSOldSectorCount) || (DataNewSectorCount > DataOldSectorCount)) { UInt64 OSSpace = GPT.LastUsableSector - FirstMainOSSector + 1; if ((MainOSNewSectorCount + DataNewSectorCount) <= OSSpace) { // MainOS and Data partitions need to be re-aligned! Partition MainOSPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "MainOS", true) == 0).Single(); Partition DataPartition = GPT.Partitions.Where(p => string.Compare(p.Name, "Data", true) == 0).Single(); MainOSPartition.LastSector = MainOSPartition.FirstSector + MainOSNewSectorCount - 1; DataPartition.FirstSector = MainOSPartition.LastSector + 1; DataPartition.LastSector = DataPartition.FirstSector + DataNewSectorCount - 1; GPTChanged = true; } else { LogFile.Log("Flash failed! Size of partitions 'MainOS' and 'Data' together are too big."); ExitFailure("Flash failed!", "Sizes of partitions 'MainOS' and 'Data' together are too big."); return; } } } else if ((MainOSNewSectorCount > 0) && (MainOSNewSectorCount > MainOSOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'MainOS' is too big."); ExitFailure("Flash failed!", "Size of partition 'MainOS' is too big."); return; } else if ((DataNewSectorCount > 0) && (DataNewSectorCount > DataOldSectorCount)) { LogFile.Log("Flash failed! Size of partition 'Data' is too big."); ExitFailure("Flash failed!", "Size of partition 'Data' is too big."); return; } if (GPTChanged) { Phone.WriteGPT(GPT); } if (PartitionCount > 0) { BusyViewModel Busy = new BusyViewModel("Flashing...", MaxProgressValue: TotalSizeSectors, UIContext: UIContext); ProgressUpdater Updater = Busy.ProgressUpdater; ActivateSubContext(Busy); int i = 0; foreach (ZipArchiveEntry Entry in Archive.Entries) { // "MainOS.bin.gz" => "MainOS" string PartitionName = Entry.Name; int Pos = PartitionName.IndexOf('.'); if (Pos >= 0) { PartitionName = PartitionName.Substring(0, Pos); } Partition Partition = GPT.Partitions.Where(p => string.Compare(p.Name, PartitionName, true) == 0).FirstOrDefault(); if (Partition != null) { Stream DecompressedStream = new DecompressedStream(Entry.Open()); ulong StreamLengthInSectors = (ulong)Entry.Length / 0x200; try { StreamLengthInSectors = (ulong)DecompressedStream.Length / 0x200; } catch { } if (StreamLengthInSectors <= Partition.SizeInSectors) { i++; Busy.Message = "Flashing partition " + Partition.Name + " (" + i.ToString() + @"/" + PartitionCount.ToString() + ")"; Phone.FlashRawPartition(DecompressedStream, Partition.Name, Updater); } DecompressedStream.Close(); } } } else { LogFile.Log("Flash failed! No valid partitions found in the archive."); ExitFailure("Flash failed!", "No valid partitions found in the archive"); return; } } } } catch (Exception Ex) { LogFile.LogException(Ex); if (Ex is WPinternalsException) { ExitFailure("Flash failed!", ((WPinternalsException)Ex).SubMessage); } else { ExitFailure("Flash failed!", null); } return; } ExitSuccess("Flash successful! Make sure you disable Windows Update on the phone!", null); }).Start(); }