manager: install: add choose partition support
manager: fix KsuCli cmd userspace: reuse choose_boot_device - manager: simplify find boot image Co-authored-by: weishu <twsxtd@gmail.com> Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com> Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
@@ -150,126 +150,40 @@ fn parse_kmi_from_boot(magiskboot: &Path, image: &PathBuf, workdir: &Path) -> Re
|
||||
parse_kmi_from_kernel(&image_path, workdir)
|
||||
}
|
||||
|
||||
fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cpio_path: &Path, cmd: &str) -> Result<()> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg("ramdisk.cpio")
|
||||
.arg(cpio_path)
|
||||
.arg(cmd)
|
||||
.status()?;
|
||||
|
||||
ensure!(status.success(), "magiskboot cpio {} failed", cmd);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_vendor_init_boot_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
let vendor_init_boot_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
fn is_magisk_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(vendor_init_boot_cpio)
|
||||
.arg(cmd)
|
||||
.arg(cpio_path)
|
||||
.arg("test")
|
||||
.status()?;
|
||||
|
||||
ensure!(status.success(), "magiskboot cpio {} failed", cmd);
|
||||
Ok(())
|
||||
// 0: stock, 1: magisk
|
||||
Ok(status.code() == Some(1))
|
||||
}
|
||||
|
||||
fn do_vendor_ramdisk_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(vendor_ramdisk_cpio)
|
||||
.arg(cmd)
|
||||
.status()?;
|
||||
|
||||
ensure!(status.success(), "magiskboot cpio {} failed", cmd);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_magisk_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args(["cpio", "ramdisk.cpio", "test"])
|
||||
.status()?;
|
||||
|
||||
// 0: stock, 1: magisk
|
||||
Ok(status.code() == Some(1))
|
||||
}
|
||||
|
||||
fn is_magisk_patched_vendor_init_boot(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let vendor_init_boot_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args(["cpio", vendor_init_boot_cpio.to_str().unwrap(), "test"])
|
||||
.status()?;
|
||||
|
||||
// 0: stock, 1: magisk
|
||||
Ok(status.code() == Some(1))
|
||||
}
|
||||
|
||||
fn is_magisk_patched_vendor_ramdisk(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args(["cpio", vendor_ramdisk_cpio.to_str().unwrap(), "test"])
|
||||
.status()?;
|
||||
|
||||
// 0: stock, 1: magisk
|
||||
Ok(status.code() == Some(1))
|
||||
}
|
||||
|
||||
fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args(["cpio", "ramdisk.cpio", "exists kernelsu.ko"])
|
||||
.status()?;
|
||||
|
||||
Ok(status.success())
|
||||
}
|
||||
|
||||
fn is_kernelsu_patched_vendor_init_boot(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args([
|
||||
"cpio",
|
||||
vendor_ramdisk_cpio.to_str().unwrap(),
|
||||
"exists kernelsu.ko",
|
||||
])
|
||||
.status()?;
|
||||
|
||||
Ok(status.success())
|
||||
}
|
||||
|
||||
fn is_kernelsu_patched_vendor_ramdisk(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.args([
|
||||
"cpio",
|
||||
vendor_ramdisk_cpio.to_str().unwrap(),
|
||||
"exists kernelsu.ko",
|
||||
])
|
||||
.arg(cpio_path)
|
||||
.arg("exists kernelsu.ko")
|
||||
.status()?;
|
||||
|
||||
Ok(status.success())
|
||||
@@ -305,10 +219,7 @@ pub fn restore(
|
||||
|
||||
let kmi = get_current_kmi().unwrap_or_else(|_| String::from(""));
|
||||
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
|
||||
let (bootimage, bootdevice) =
|
||||
find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?;
|
||||
let (bootimage, bootdevice) = find_boot_image(&image, &kmi, false, false, workdir, &None)?;
|
||||
|
||||
println!("- Unpacking boot image");
|
||||
let status = Command::new(&magiskboot)
|
||||
@@ -320,33 +231,36 @@ pub fn restore(
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
// let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let no_vendor_init_boot = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_init_boot =
|
||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_ramdisk =
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
is_kernelsu_patched
|
||||
|| is_kernelsu_patched_vendor_init_boot
|
||||
|| is_kernelsu_patched_vendor_ramdisk,
|
||||
"boot image is not patched by KernelSU"
|
||||
);
|
||||
let mut ramdisk = workdir.join("ramdisk.cpio");
|
||||
if !ramdisk.exists() {
|
||||
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
|
||||
}
|
||||
if !ramdisk.exists() {
|
||||
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
}
|
||||
if !ramdisk.exists() {
|
||||
bail!("No compatible ramdisk found.")
|
||||
}
|
||||
let ramdisk = ramdisk.as_path();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir, ramdisk)?;
|
||||
ensure!(is_kernelsu_patched, "boot image is not patched by KernelSU");
|
||||
|
||||
let mut new_boot = None;
|
||||
let mut from_backup = false;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
if do_cpio_cmd(&magiskboot, workdir, &format!("exists {BACKUP_FILENAME}")).is_ok() {
|
||||
if do_cpio_cmd(
|
||||
&magiskboot,
|
||||
workdir,
|
||||
ramdisk,
|
||||
&format!("exists {BACKUP_FILENAME}"),
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
do_cpio_cmd(
|
||||
&magiskboot,
|
||||
workdir,
|
||||
ramdisk,
|
||||
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
|
||||
@@ -369,81 +283,13 @@ pub fn restore(
|
||||
}
|
||||
|
||||
if new_boot.is_none() {
|
||||
if !no_ramdisk {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, ramdisk, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Restoring /vendor_ramdisk/init_boot");
|
||||
println!("- Removing /vendor_ramdisk/init_boot/kernelsu.ko");
|
||||
// vendor init_boot restore
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
println!("- Checking if init.real exists");
|
||||
let status =
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/init_boot/init.real to init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/init_boot/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/init_boot.cpio");
|
||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_init_boot)?;
|
||||
}
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk");
|
||||
println!("- Removing /vendor_ramdisk/ramdisk/kernelsu.ko");
|
||||
// vendor ramdisk restore
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
let status =
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real exists");
|
||||
println!("- Restoring /vendor_ramdisk/ramdisk/init.real to init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /vendor_ramdisk/ramdisk/init.real not found");
|
||||
println!("- Removing vendor_ramdisk/ramdisk.cpio");
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
} else {
|
||||
println!("- Restoring /ramdisk");
|
||||
println!("- Removing /ramdisk/kernelsu.ko");
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
println!("- Checking if init.real exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
println!("- /ramdisk/init.real exists");
|
||||
println!("- Restoring /ramdisk/init.real to init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
println!("- /ramdisk/init.real not found");
|
||||
println!("- Removing ramdisk.cpio");
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
// if init.real exists, restore it
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init.real init")?;
|
||||
}
|
||||
|
||||
println!("- Repacking boot image");
|
||||
@@ -452,7 +298,7 @@ pub fn restore(
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("repack")
|
||||
.arg(bootimage.display().to_string())
|
||||
.arg(&bootimage)
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot repack failed");
|
||||
new_boot = Some(workdir.join("new-boot.img"));
|
||||
@@ -498,8 +344,11 @@ pub fn patch(
|
||||
out: Option<PathBuf>,
|
||||
magiskboot: Option<PathBuf>,
|
||||
kmi: Option<String>,
|
||||
partition: Option<String>,
|
||||
) -> Result<()> {
|
||||
let result = do_patch(image, kernel, kmod, init, ota, flash, out, magiskboot, kmi);
|
||||
let result = do_patch(
|
||||
image, kernel, kmod, init, ota, flash, out, magiskboot, kmi, partition,
|
||||
);
|
||||
if let Err(ref e) = result {
|
||||
println!("- Install Error: {e}");
|
||||
}
|
||||
@@ -517,6 +366,7 @@ fn do_patch(
|
||||
out: Option<PathBuf>,
|
||||
magiskboot_path: Option<PathBuf>,
|
||||
kmi: Option<String>,
|
||||
partition: Option<String>,
|
||||
) -> Result<()> {
|
||||
println!(include_str!("banner"));
|
||||
|
||||
@@ -571,18 +421,10 @@ fn do_patch(
|
||||
}
|
||||
};
|
||||
|
||||
let skip_init = kmi.starts_with("android12-");
|
||||
let (bootimage, bootdevice) =
|
||||
find_boot_image(&image, &kmi, ota, is_replace_kernel, workdir, &partition)?;
|
||||
|
||||
let (bootimage, bootdevice) = find_boot_image(
|
||||
&image,
|
||||
skip_init,
|
||||
ota,
|
||||
is_replace_kernel,
|
||||
workdir,
|
||||
&magiskboot,
|
||||
)?;
|
||||
|
||||
let bootimage = bootimage.display().to_string();
|
||||
let bootimage = bootimage.as_path();
|
||||
|
||||
// try extract magiskboot/bootctl
|
||||
let _ = assets::ensure_binaries(false);
|
||||
@@ -617,98 +459,48 @@ fn do_patch(
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("unpack")
|
||||
.arg(&bootimage)
|
||||
.arg(bootimage)
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let no_vendor_init_boot = !workdir
|
||||
.join("vendor_ramdisk")
|
||||
.join("init_boot.cpio")
|
||||
.exists();
|
||||
let no_vendor_ramdisk = !workdir.join("vendor_ramdisk").join("ramdisk.cpio").exists();
|
||||
if no_ramdisk && no_vendor_init_boot && no_vendor_ramdisk {
|
||||
println!("- No compatible ramdisk found.");
|
||||
println!("- Will create our own ramdisk!");
|
||||
let mut ramdisk = workdir.join("ramdisk.cpio");
|
||||
if !ramdisk.exists() {
|
||||
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
|
||||
}
|
||||
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_init_boot =
|
||||
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_magisk_patched_vendor_ramdisk = is_magisk_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
!is_magisk_patched
|
||||
|| !is_magisk_patched_vendor_init_boot
|
||||
|| !is_magisk_patched_vendor_ramdisk,
|
||||
"Cannot work with Magisk patched image"
|
||||
);
|
||||
if !ramdisk.exists() {
|
||||
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||
}
|
||||
if !ramdisk.exists() {
|
||||
println!("- No ramdisk, create by default");
|
||||
ramdisk = "ramdisk.cpio".into();
|
||||
}
|
||||
let ramdisk = ramdisk.as_path();
|
||||
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir, ramdisk)?;
|
||||
ensure!(!is_magisk_patched, "Cannot work with Magisk patched image");
|
||||
|
||||
println!("- Adding KernelSU LKM");
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_init_boot =
|
||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched_vendor_ramdisk =
|
||||
is_kernelsu_patched_vendor_ramdisk(&magiskboot, workdir)?;
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir, ramdisk)?;
|
||||
|
||||
let mut need_backup = false;
|
||||
if (no_ramdisk && !is_kernelsu_patched_vendor_init_boot)
|
||||
|| (no_ramdisk && no_vendor_init_boot && !is_kernelsu_patched_vendor_ramdisk)
|
||||
|| !is_kernelsu_patched
|
||||
{
|
||||
if !no_ramdisk {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Checking if /vendor_ramdisk/init_boot/init exists");
|
||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/init_boot/init");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Checking if /vendor_ramdisk/ramdisk/init exists");
|
||||
let status = do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up vendor_ramdisk/ramdisk/init");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
} else {
|
||||
println!("- Checking if /ramdisk/init exists");
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
println!("- Backing up ramdisk/init");
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
if !is_kernelsu_patched {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init");
|
||||
if status.is_ok() {
|
||||
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
}
|
||||
|
||||
if !no_ramdisk {
|
||||
println!("- Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_init_boot {
|
||||
println!("- Patching /vendor_ramdisk/init_boot");
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else if !no_vendor_ramdisk {
|
||||
println!("- Patching /vendor_ramdisk/ramdisk");
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 init init")?;
|
||||
do_vendor_ramdisk_cpio_cmd(&magiskboot, workdir, "add 0750 kernelsu.ko kernelsu.ko")?;
|
||||
} else {
|
||||
println!("- Creating and Patching /ramdisk");
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
do_cpio_cmd(&magiskboot, workdir, ramdisk, "add 0755 init init")?;
|
||||
do_cpio_cmd(
|
||||
&magiskboot,
|
||||
workdir,
|
||||
ramdisk,
|
||||
"add 0755 kernelsu.ko kernelsu.ko",
|
||||
)?;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
if need_backup && let Err(e) = do_backup(&magiskboot, workdir, &bootimage) {
|
||||
if need_backup && let Err(e) = do_backup(&magiskboot, workdir, ramdisk, bootimage) {
|
||||
println!("- Backup stock image failed: {e}");
|
||||
}
|
||||
|
||||
@@ -719,7 +511,7 @@ fn do_patch(
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("repack")
|
||||
.arg(&bootimage)
|
||||
.arg(bootimage)
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot repack failed");
|
||||
let new_boot = workdir.join("new-boot.img");
|
||||
@@ -774,7 +566,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
fn do_backup(magiskboot: &Path, workdir: &Path, cpio_path: &Path, image: &Path) -> Result<()> {
|
||||
let sha1 = calculate_sha1(image)?;
|
||||
let filename = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
|
||||
|
||||
@@ -786,6 +578,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
||||
do_cpio_cmd(
|
||||
magiskboot,
|
||||
workdir,
|
||||
cpio_path,
|
||||
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||
)?;
|
||||
println!("- Stock image has been backup to");
|
||||
@@ -855,141 +648,117 @@ fn find_magiskboot(magiskboot_path: Option<PathBuf>, workdir: &Path) -> Result<P
|
||||
|
||||
fn find_boot_image(
|
||||
image: &Option<PathBuf>,
|
||||
skip_init: bool,
|
||||
kmi: &str,
|
||||
ota: bool,
|
||||
is_replace_kernel: bool,
|
||||
workdir: &Path,
|
||||
magiskboot: &Path,
|
||||
partition: &Option<String>,
|
||||
) -> Result<(PathBuf, Option<String>)> {
|
||||
let bootimage;
|
||||
let mut bootdevice = None;
|
||||
if let Some(ref image) = *image {
|
||||
ensure!(image.exists(), "- Boot image not found");
|
||||
ensure!(image.exists(), "boot image not found");
|
||||
bootimage = std::fs::canonicalize(image)?;
|
||||
} else {
|
||||
if cfg!(not(target_os = "android")) {
|
||||
println!("- Current OS is not android, refusing auto bootimage/bootdevice detection");
|
||||
bail!("- Please specify a boot image");
|
||||
}
|
||||
let mut slot_suffix =
|
||||
utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
|
||||
|
||||
if !slot_suffix.is_empty() && ota {
|
||||
if slot_suffix == "_a" {
|
||||
slot_suffix = "_b".to_string()
|
||||
} else {
|
||||
slot_suffix = "_a".to_string()
|
||||
}
|
||||
};
|
||||
|
||||
let init_boot_partition = format!("/dev/block/by-name/init_boot{slot_suffix}");
|
||||
let vendor_boot_partition = format!("/dev/block/by-name/vendor_boot{slot_suffix}");
|
||||
let boot_partition = format!("/dev/block/by-name/boot{slot_suffix}");
|
||||
|
||||
let init_boot_exist = Path::new(&init_boot_partition).exists();
|
||||
let vendor_boot_exist = Path::new(&vendor_boot_partition).exists();
|
||||
|
||||
// helper: unpack a partition and check for a ramdisk and init
|
||||
fn unpack_and_check_init(
|
||||
magiskboot: &Path,
|
||||
workdir: &Path,
|
||||
partition: &str,
|
||||
ramdisk_cpio: &str,
|
||||
) -> Result<bool> {
|
||||
let tmp_img = workdir.join("probe.img");
|
||||
dd(partition, &tmp_img)?;
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("unpack")
|
||||
.arg(&tmp_img)
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
return Ok(false);
|
||||
}
|
||||
let ramdisk_path = workdir.join(ramdisk_cpio);
|
||||
let has_init = if ramdisk_path.exists() {
|
||||
Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(ramdisk_cpio)
|
||||
.arg("exists init")
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Clean up
|
||||
let _ = std::fs::remove_file(&tmp_img);
|
||||
let _ = std::fs::remove_file(workdir.join("ramdisk.cpio"));
|
||||
let _ = std::fs::remove_dir_all(workdir.join("vendor_ramdisk"));
|
||||
Ok(has_init)
|
||||
bail!("Please specify a boot image");
|
||||
}
|
||||
|
||||
let mut selected_partition = &boot_partition;
|
||||
let slot_suffix = get_slot_suffix(ota);
|
||||
let boot_partition_name = choose_boot_partition(kmi, is_replace_kernel, partition);
|
||||
let boot_partition = format!("/dev/block/by-name/{boot_partition_name}{slot_suffix}");
|
||||
|
||||
if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
// try init_boot/ramdisk.cpio
|
||||
if unpack_and_check_init(magiskboot, workdir, &init_boot_partition, "ramdisk.cpio")? {
|
||||
println!("- Using init_boot partition (ramdisk.cpio).");
|
||||
selected_partition = &init_boot_partition;
|
||||
}
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/init_boot.cpio
|
||||
if selected_partition == &boot_partition
|
||||
&& !is_replace_kernel
|
||||
&& vendor_boot_exist
|
||||
&& !skip_init
|
||||
&& unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/init_boot.cpio",
|
||||
)?
|
||||
{
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/init_boot.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
|
||||
// try vendor_boot/vendor_ramdisk/ramdisk.cpio
|
||||
if selected_partition == &boot_partition
|
||||
&& !is_replace_kernel
|
||||
&& vendor_boot_exist
|
||||
&& !skip_init
|
||||
&& unpack_and_check_init(
|
||||
magiskboot,
|
||||
workdir,
|
||||
&vendor_boot_partition,
|
||||
"vendor_ramdisk/ramdisk.cpio",
|
||||
)?
|
||||
{
|
||||
println!("- Using vendor_boot partition (vendor_ramdisk/ramdisk.cpio).");
|
||||
selected_partition = &vendor_boot_partition;
|
||||
}
|
||||
|
||||
if selected_partition == &boot_partition {
|
||||
println!("- Using boot partition (ramdisk.cpio).");
|
||||
}
|
||||
|
||||
println!("- Bootdevice: {selected_partition}");
|
||||
println!("- Bootdevice: {boot_partition}");
|
||||
let tmp_boot_path = workdir.join("boot.img");
|
||||
|
||||
dd(selected_partition, &tmp_boot_path)?;
|
||||
dd(&boot_partition, &tmp_boot_path)?;
|
||||
|
||||
ensure!(tmp_boot_path.exists(), "- Tmp boot image not found");
|
||||
ensure!(tmp_boot_path.exists(), "boot image not found");
|
||||
|
||||
bootimage = tmp_boot_path;
|
||||
bootdevice = Some(selected_partition.to_string());
|
||||
bootdevice = Some(boot_partition);
|
||||
};
|
||||
Ok((bootimage, bootdevice))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn choose_boot_partition(
|
||||
kmi: &str,
|
||||
is_replace_kernel: bool,
|
||||
partition: &Option<String>,
|
||||
) -> String {
|
||||
let slot_suffix = get_slot_suffix(false);
|
||||
let skip_init_boot = kmi.starts_with("android12-");
|
||||
|
||||
let init_boot_exist = Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
|
||||
let vendor_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
|
||||
|
||||
// if specific partition is specified, use it
|
||||
if let Some(part) = partition {
|
||||
return match part.as_str() {
|
||||
"boot" | "init_boot" | "vendor_boot" => part.clone(),
|
||||
_ => "boot".to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
// if init_boot exists and not skipping it, use it
|
||||
if !is_replace_kernel && init_boot_exist && !skip_init_boot {
|
||||
return "init_boot".to_string();
|
||||
}
|
||||
|
||||
// if vendor_boot exists and not skipping it, use it
|
||||
if !is_replace_kernel && vendor_boot_exist && !skip_init_boot {
|
||||
return "vendor_boot".to_string();
|
||||
}
|
||||
|
||||
"boot".to_string()
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn choose_boot_partition(
|
||||
_kmi: &str,
|
||||
_is_replace_kernel: bool,
|
||||
_partition: &Option<String>,
|
||||
) -> String {
|
||||
"boot".to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn get_slot_suffix(ota: bool) -> String {
|
||||
let mut slot_suffix = utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from(""));
|
||||
if !slot_suffix.is_empty() && ota {
|
||||
if slot_suffix == "_a" {
|
||||
slot_suffix = "_b".to_string()
|
||||
} else {
|
||||
slot_suffix = "_a".to_string()
|
||||
}
|
||||
}
|
||||
slot_suffix
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn get_slot_suffix(_ota: bool) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn list_available_partitions() -> Vec<String> {
|
||||
let slot_suffix = get_slot_suffix(false);
|
||||
let candidates = vec!["boot", "init_boot", "vendor_boot"];
|
||||
candidates
|
||||
.into_iter()
|
||||
.filter(|name| Path::new(&format!("/dev/block/by-name/{}{}", name, slot_suffix)).exists())
|
||||
.map(|s| s.to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn list_available_partitions() -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn post_ota() -> Result<()> {
|
||||
use crate::defs::ADB_DIR;
|
||||
use assets::BOOTCTL_PATH;
|
||||
|
||||
@@ -107,6 +107,10 @@ enum Commands {
|
||||
/// KMI version, if specified, will use the specified KMI
|
||||
#[arg(long, default_value = None)]
|
||||
kmi: Option<String>,
|
||||
|
||||
/// target partition override (init_boot | boot | vendor_boot)
|
||||
#[arg(long, default_value = None)]
|
||||
partition: Option<String>,
|
||||
},
|
||||
|
||||
/// Restore boot or init_boot images patched by KernelSU
|
||||
@@ -156,7 +160,23 @@ enum BootInfo {
|
||||
CurrentKmi,
|
||||
|
||||
/// show supported kmi versions
|
||||
SupportedKmi,
|
||||
SupportedKmis,
|
||||
|
||||
/// check if device is A/B capable
|
||||
IsAbDevice,
|
||||
|
||||
/// show auto-selected boot partition name
|
||||
DefaultPartition,
|
||||
|
||||
/// list available partitions for current or OTA toggled slot
|
||||
AvailablePartitions,
|
||||
|
||||
/// show slot suffix for current or OTA toggled slot
|
||||
SlotSuffix {
|
||||
/// toggle to another slot
|
||||
#[arg(short = 'u', long, default_value = "false")]
|
||||
ota: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand, Debug)]
|
||||
@@ -524,7 +544,10 @@ pub fn run() -> Result<()> {
|
||||
out,
|
||||
magiskboot,
|
||||
kmi,
|
||||
} => crate::boot_patch::patch(boot, kernel, module, init, ota, flash, out, magiskboot, kmi),
|
||||
partition,
|
||||
} => crate::boot_patch::patch(
|
||||
boot, kernel, module, init, ota, flash, out, magiskboot, kmi, partition,
|
||||
),
|
||||
|
||||
Commands::BootInfo { command } => match command {
|
||||
BootInfo::CurrentKmi => {
|
||||
@@ -533,11 +556,34 @@ pub fn run() -> Result<()> {
|
||||
// return here to avoid printing the error message
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::SupportedKmi => {
|
||||
BootInfo::SupportedKmis => {
|
||||
let kmi = crate::assets::list_supported_kmi()?;
|
||||
kmi.iter().for_each(|kmi| println!("{kmi}"));
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::IsAbDevice => {
|
||||
let val = crate::utils::getprop("ro.build.ab_update")
|
||||
.unwrap_or_else(|| String::from("false"));
|
||||
let is_ab = val.trim().to_lowercase() == "true";
|
||||
println!("{}", if is_ab { "true" } else { "false" });
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::DefaultPartition => {
|
||||
let kmi = crate::boot_patch::get_current_kmi().unwrap_or_else(|_| String::from(""));
|
||||
let name = crate::boot_patch::choose_boot_partition(&kmi, false, &None);
|
||||
println!("{name}");
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::SlotSuffix { ota } => {
|
||||
let suffix = crate::boot_patch::get_slot_suffix(ota);
|
||||
println!("{suffix}");
|
||||
return Ok(());
|
||||
}
|
||||
BootInfo::AvailablePartitions => {
|
||||
let parts = crate::boot_patch::list_available_partitions();
|
||||
parts.iter().for_each(|p| println!("{p}"));
|
||||
return Ok(());
|
||||
}
|
||||
},
|
||||
Commands::BootRestore {
|
||||
boot,
|
||||
|
||||
Reference in New Issue
Block a user