public Conclusion MembootFel(Tasker tasker, Object syncObject = null) { tasker.SetStatus(Resources.Membooting); if (hakchi.Shell.IsOnline) return Conclusion.Abort; // check and adjust kernel size byte[] kernel = hakchi.GetMembootImage().ToArray(); var size = Shared.CalcKernelSize(kernel); if (size > kernel.Length || size > Fel.transfer_max_size) throw new Exception(Resources.InvalidKernelSize + " " + size); size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } // clovershell override "hex-edit" boot.img if (ConfigIni.Instance.ForceClovershell || ConfigIni.Instance.ForceNetwork) { kernel.InPlaceStringEdit(64, 512, 0, (string str) => { str.Replace("hakchi-shell", "").Replace("hakchi-clovershell", ""); if (ConfigIni.Instance.ForceClovershell) str += " hakchi-clovershell"; else if (ConfigIni.Instance.ForceNetwork) str += " hakchi-shell"; return str; }); } // upload kernel through fel int progress = 0; int maxProgress = (int)((double)kernel.Length / (double)67000 + 50); fel.WriteMemory(Fel.transfer_base_m, kernel, delegate (Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.WritingMemory: tasker.SetStatus(Resources.UploadingKernel); break; } progress++; tasker.SetProgress(progress, maxProgress); } ); var bootCommand = string.Format("boota {0:x}", Fel.transfer_base_m); tasker.SetStatus(Resources.ExecutingCommand + " " + bootCommand); fel.RunUbootCmd(bootCommand, true); return Conclusion.Success; }
public Conclusion Memboot(Tasker tasker, Object syncObject = null) { // load appropriate kernel byte[] kernel; if (stockKernel != null && stockKernel.Length > 0) { kernel = stockKernel.ToArray(); } else { stockKernel = null; // double-safety kernel = hakchi.GetMembootImage().ToArray(); } tasker.SetStatus(Resources.Membooting); if (hakchi.Shell.IsOnline) { // override arguments string addedArgs = ConfigIni.Instance.ForceClovershell ? " hakchi-clovershell" : ""; // skip to built-in recovery if running latest version if (stockKernel == null && hakchi.CanInteract && !hakchi.SystemEligibleForRootfsUpdate()) { if (hakchi.Shell.Execute("[ -e /bin/detached ]") == 0) // detached recovery function? { try { hakchi.Shell.ExecuteSimple("/bin/detached recovery" + addedArgs, 100); } catch { } // no-op return(Conclusion.Success); } } try { hakchi.Shell.ExecuteSimple("uistop"); hakchi.Shell.ExecuteSimple("mkdir -p /tmp/kexec/", throwOnNonZero: true); hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "kexec.static"), "/tmp/kexec/kexec"); TrackableStream kernelStream = new TrackableStream(kernel); kernelStream.OnProgress += tasker.OnProgress; if (stockKernel == null) { hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "detached-fallback"), "/tmp/kexec/detached-fallback"); hakchi.UploadFile(kernelStream, "/tmp/kexec/boot.img", false); try { hakchi.Shell.ExecuteSimple("cd /tmp/kexec/; /bin/sh /tmp/kexec/detached-fallback recovery /tmp/kexec/boot.img" + addedArgs, 100); } catch { } // no-op } else { hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "unpackbootimg.static"), "/tmp/kexec/unpackbootimg"); hakchi.Shell.Execute( command: "cat > /tmp/kexec/boot.img; cd /tmp/kexec/; ./unpackbootimg -i boot.img", stdin: kernelStream, throwOnNonZero: true ); hakchi.Shell.ExecuteSimple("cd /tmp/kexec/ && ./kexec -l -t zImage boot.img-zImage \"--command-line=$(cat boot.img-cmdline)\" --ramdisk=boot.img-ramdisk.gz --atags", 0, true); hakchi.Shell.ExecuteSimple("cd /tmp/; umount -ar", 0); try { hakchi.Shell.ExecuteSimple("/tmp/kexec/kexec -e", 100); } catch { } // no-op } } catch { try { hakchi.Shell.ExecuteSimple("uistart"); } catch { } // no-op throw; } } else { // check and adjust kernel size var size = Shared.CalcKernelSize(kernel); if (size > kernel.Length || size > Fel.transfer_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } // clovershell override "hex-edit" boot.img if (stockKernel == null && ConfigIni.Instance.ForceClovershell) { kernel.InPlaceStringEdit(64, 512, 0, (string str) => { if (str.IndexOf("hakchi-shell") != -1) { return(str.Replace("hakchi-shell", "hakchi-clovershell")); } else { return(str + " hakchi-clovershell"); } }); } // upload kernel through fel int progress = 0; int maxProgress = (int)((double)kernel.Length / (double)67000 + 50); fel.WriteMemory(Fel.transfer_base_m, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.WritingMemory: tasker.SetStatus(Resources.UploadingKernel); break; } progress++; tasker.SetProgress(progress, maxProgress); } ); var bootCommand = string.Format("boota {0:x}", Fel.transfer_base_m); tasker.SetStatus(Resources.ExecutingCommand + " " + bootCommand); fel.RunUbootCmd(bootCommand, true); } return(Conclusion.Success); }
public void FlashKernel() { int progress = 0; int maxProgress = 115 + (string.IsNullOrEmpty(Mod) ? 0 : 30) + ((hmodsInstall != null && hmodsInstall.Count() > 0) ? 75 : 0); var hmods = hmodsInstall; hmodsInstall = null; if (WaitForFelFromThread() != DialogResult.OK) { DialogResult = DialogResult.Abort; return; } progress += 5; SetProgress(progress, maxProgress); byte[] kernel; if (!string.IsNullOrEmpty(Mod)) { kernel = CreatePatchedKernel(); progress += 5; SetProgress(progress, maxProgress); } else { kernel = File.ReadAllBytes(KernelDump); } var size = CalcKernelSize(kernel); if (size > kernel.Length || size > Fel.kernel_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } fel.WriteFlash(Fel.kernel_base_f, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); break; case Fel.CurrentAction.WritingMemory: SetStatus(Resources.UploadingKernel); break; } progress++; SetProgress(progress, maxProgress); } ); var r = fel.ReadFlash((UInt32)Fel.kernel_base_f, (UInt32)kernel.Length, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); break; case Fel.CurrentAction.ReadingMemory: SetStatus(Resources.Verifying); break; } progress++; SetProgress(progress, maxProgress); } ); if (!kernel.SequenceEqual(r)) { throw new Exception(Resources.VerifyFailed); } hmodsInstall = hmods; if (hmodsInstall != null && hmodsInstall.Count() > 0) { Memboot(maxProgress, progress); // Lets install some mods } else { var shutdownCommand = string.Format("shutdown", Fel.kernel_base_m); SetStatus(Resources.ExecutingCommand + " " + shutdownCommand); fel.RunUbootCmd(shutdownCommand, true); SetStatus(Resources.Done); SetProgress(maxProgress, maxProgress); } }
public void FlashKernel() { int progress = 5; int maxProgress = 120 + (string.IsNullOrEmpty(Mod) ? 0 : 5); SetProgress(progress, maxProgress); byte[] kernel; if (!string.IsNullOrEmpty(Mod)) { kernel = CreatePatchedKernel(Mod); progress += 5; SetProgress(progress, maxProgress); } else { kernel = File.ReadAllBytes(KernelDump); } var size = CalKernelSize(kernel); if (size > kernel.Length || size > kernel_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + sector_size - 1) / sector_size; size = size * sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } bool flashCommandExecuted = false; try { fel.WriteFlash(kernel_base_f, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); flashCommandExecuted = true; break; case Fel.CurrentAction.WritingMemory: SetStatus(Resources.UploadingKernel); break; } progress++; SetProgress(progress, maxProgress); } ); } catch (USBException ex) { fel.Close(); if (flashCommandExecuted) { SetStatus(Resources.WaitingForDevice); waitDeviceResult = null; WaitForDeviceInvoke(vid, pid); while (waitDeviceResult == null) { Thread.Sleep(100); } if (!(waitDeviceResult ?? false)) { DialogResult = DialogResult.Abort; return; } Thread.Sleep(500); fel = new Fel(); fel.Fes1Bin = Resources.fes1; fel.UBootBin = Resources.uboot; fel.Open(vid, pid); SetStatus(Resources.UploadingFes1); fel.InitDram(true); } else { throw ex; } } var r = fel.ReadFlash((UInt32)kernel_base_f, (UInt32)kernel.Length, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); break; case Fel.CurrentAction.ReadingMemory: SetStatus(Resources.Verifying); break; } progress++; SetProgress(progress, maxProgress); } ); for (int i = 0; i < kernel.Length; i++) { if (kernel[i] != r[i]) { throw new Exception(Resources.VerifyFailed); } } var bootCommand = string.Format("boota {0:x}", kernel_base_m); SetStatus(Resources.ExecutingCommand + " " + bootCommand); fel.RunUbootCmd(bootCommand, true); SetStatus(Resources.Done); SetProgress(maxProgress, maxProgress); }
public void FlashKernel() { int progress = 5; int maxProgress = 120 + (string.IsNullOrEmpty(Mod) ? 0 : 5); SetProgress(progress, maxProgress); byte[] kernel; int pos = 0, totalFiles; if (!string.IsNullOrEmpty(Mod)) { kernel = CreatePatchedKernel(ref pos, out totalFiles); progress += 5; SetProgress(progress, maxProgress); } else { kernel = File.ReadAllBytes(KernelDump); } var size = CalKernelSize(kernel); if (size > kernel.Length || size > Fel.kernel_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } fel.WriteFlash(Fel.kernel_base_f, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); break; case Fel.CurrentAction.WritingMemory: SetStatus(Resources.UploadingKernel); break; } progress++; SetProgress(progress, maxProgress); } ); var r = fel.ReadFlash((UInt32)Fel.kernel_base_f, (UInt32)kernel.Length, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.RunningCommand: SetStatus(Resources.ExecutingCommand + " " + command); break; case Fel.CurrentAction.ReadingMemory: SetStatus(Resources.Verifying); break; } progress++; SetProgress(progress, maxProgress); } ); if (!kernel.SequenceEqual(r)) { throw new Exception(Resources.VerifyFailed); } if (string.IsNullOrEmpty(Mod)) { var shutdownCommand = string.Format("shutdown", Fel.kernel_base_m); SetStatus(Resources.ExecutingCommand + " " + shutdownCommand); fel.RunUbootCmd(shutdownCommand, true); } SetStatus(Resources.Done); SetProgress(maxProgress, maxProgress); }
public void RunCommand(Fel fel, string command, bool noreturn = false) { fel.RunUbootCmd(command, noreturn); }