ksud: support vendor_boot patching for some odd devices (#2650)

This will add support to patch vendor_boot with LKM for devices which
have their init ramdisk inside of vendor_boot and not boot/init_boot.

---------

Co-authored-by: Rifat Azad <rifat.44.azad.rifs@gmail.com>
Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
Co-authored-by: 5ec1cff <56485584+5ec1cff@users.noreply.github.com>
This commit is contained in:
ukriu
2025-07-20 11:16:47 +05:30
committed by GitHub
parent 6c61a8b7c7
commit 67fa81b60c
2 changed files with 68 additions and 39 deletions

View File

@@ -153,38 +153,40 @@ fn parse_kmi_from_boot(magiskboot: &Path, image: &PathBuf, workdir: &Path) -> Re
parse_kmi_from_kernel(&image_path, workdir) 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) let status = Command::new(magiskboot)
.current_dir(workdir) .current_dir(workdir)
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.arg("cpio") .arg("cpio")
.arg("ramdisk.cpio") .arg(cpio_path)
.arg(cmd) .arg(cmd)
.status()?; .status()?;
ensure!(status.success(), "magiskboot cpio {} failed", cmd); ensure!(status.success(), "magiskboot cpio {} failed", cmd);
Ok(()) Ok(())
} }
fn is_magisk_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> { fn is_magisk_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
let status = Command::new(magiskboot) let status = Command::new(magiskboot)
.current_dir(workdir) .current_dir(workdir)
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.args(["cpio", "ramdisk.cpio", "test"]) .arg("cpio")
.arg(cpio_path)
.arg("test")
.status()?; .status()?;
// 0: stock, 1: magisk // 0: stock, 1: magisk
Ok(status.code() == Some(1)) Ok(status.code() == Some(1))
} }
fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> { fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
let status = Command::new(magiskboot) let status = Command::new(magiskboot)
.current_dir(workdir) .current_dir(workdir)
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.args(["cpio", "ramdisk.cpio", "exists kernelsu.ko"]) .arg("cpio")
.arg(cpio_path)
.arg("exists kernelsu.ko")
.status()?; .status()?;
Ok(status.success()) Ok(status.success())
@@ -234,17 +236,36 @@ pub fn restore(
.status()?; .status()?;
ensure!(status.success(), "magiskboot unpack failed"); ensure!(status.success(), "magiskboot unpack failed");
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?; 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"); ensure!(is_kernelsu_patched, "boot image is not patched by KernelSU");
let mut new_boot = None; let mut new_boot = None;
let mut from_backup = false; let mut from_backup = false;
#[cfg(target_os = "android")] #[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( do_cpio_cmd(
&magiskboot, &magiskboot,
workdir, workdir,
ramdisk,
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"), &format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?; )?;
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?; let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
@@ -268,15 +289,12 @@ pub fn restore(
if new_boot.is_none() { if new_boot.is_none() {
// remove kernelsu.ko // remove kernelsu.ko
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?; do_cpio_cmd(&magiskboot, workdir, ramdisk, "rm kernelsu.ko")?;
// if init.real exists, restore it // if init.real exists, restore it
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok(); let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init.real").is_ok();
if status { if status {
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?; do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init.real init")?;
} else {
let ramdisk = workdir.join("ramdisk.cpio");
std::fs::remove_file(ramdisk)?;
} }
println!("- Repacking boot image"); println!("- Repacking boot image");
@@ -285,7 +303,7 @@ pub fn restore(
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.arg("repack") .arg("repack")
.arg(bootimage.display().to_string()) .arg(&bootimage)
.status()?; .status()?;
ensure!(status.success(), "magiskboot repack failed"); ensure!(status.success(), "magiskboot repack failed");
new_boot = Some(workdir.join("new-boot.img")); new_boot = Some(workdir.join("new-boot.img"));
@@ -409,7 +427,7 @@ fn do_patch(
let (bootimage, bootdevice) = let (bootimage, bootdevice) =
find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?; find_boot_image(&image, skip_init, ota, is_replace_kernel, workdir)?;
let bootimage = bootimage.display().to_string(); let bootimage = bootimage.as_path();
// try extract magiskboot/bootctl // try extract magiskboot/bootctl
let _ = assets::ensure_binaries(false); let _ = assets::ensure_binaries(false);
@@ -438,48 +456,54 @@ fn do_patch(
assets::copy_assets_to_file("ksuinit", init_file).context("copy ksuinit failed")?; assets::copy_assets_to_file("ksuinit", init_file).context("copy ksuinit failed")?;
} }
// magiskboot unpack boot.img
// magiskboot cpio ramdisk.cpio 'cp init init.real'
// magiskboot cpio ramdisk.cpio 'add 0755 ksuinit init'
// magiskboot cpio ramdisk.cpio 'add 0755 <kmod> kernelsu.ko'
println!("- Unpacking boot image"); println!("- Unpacking boot image");
let status = Command::new(&magiskboot) let status = Command::new(&magiskboot)
.current_dir(workdir) .current_dir(workdir)
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.arg("unpack") .arg("unpack")
.arg(&bootimage) .arg(bootimage)
.status()?; .status()?;
ensure!(status.success(), "magiskboot unpack failed"); ensure!(status.success(), "magiskboot unpack failed");
let no_ramdisk = !workdir.join("ramdisk.cpio").exists(); let mut ramdisk = workdir.join("ramdisk.cpio");
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?; if !ramdisk.exists() {
ensure!( ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
no_ramdisk || !is_magisk_patched, }
"Cannot work with Magisk patched image" 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_magisk_patched = is_magisk_patched(&magiskboot, workdir, ramdisk)?;
ensure!(!is_magisk_patched, "Cannot work with Magisk patched image");
println!("- Adding KernelSU LKM"); println!("- Adding KernelSU LKM");
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?; let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir, ramdisk)?;
let mut need_backup = false; let mut need_backup = false;
if !is_kernelsu_patched { if !is_kernelsu_patched {
// kernelsu.ko is not exist, backup init if necessary // kernelsu.ko is not exist, backup init if necessary
let status = do_cpio_cmd(&magiskboot, workdir, "exists init"); let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init");
if status.is_ok() { if status.is_ok() {
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?; do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init init.real")?;
} }
need_backup = flash; need_backup = flash;
} }
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?; do_cpio_cmd(&magiskboot, workdir, ramdisk, "add 0755 init init")?;
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?; do_cpio_cmd(
&magiskboot,
workdir,
ramdisk,
"add 0755 kernelsu.ko kernelsu.ko",
)?;
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
if need_backup { if need_backup {
if let Err(e) = do_backup(&magiskboot, workdir, &bootimage) { if let Err(e) = do_backup(&magiskboot, workdir, ramdisk, bootimage) {
println!("- Backup stock image failed: {e}"); println!("- Backup stock image failed: {e}");
} }
} }
@@ -491,7 +515,7 @@ fn do_patch(
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()) .stderr(Stdio::null())
.arg("repack") .arg("repack")
.arg(&bootimage) .arg(bootimage)
.status()?; .status()?;
ensure!(status.success(), "magiskboot repack failed"); ensure!(status.success(), "magiskboot repack failed");
let new_boot = workdir.join("new-boot.img"); let new_boot = workdir.join("new-boot.img");
@@ -546,7 +570,7 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
} }
#[cfg(target_os = "android")] #[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 sha1 = calculate_sha1(image)?;
let filename = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}"); let filename = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
@@ -558,6 +582,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
do_cpio_cmd( do_cpio_cmd(
magiskboot, magiskboot,
workdir, workdir,
cpio_path,
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"), &format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
)?; )?;
println!("- Stock image has been backup to"); println!("- Stock image has been backup to");
@@ -655,8 +680,12 @@ fn find_boot_image(
let init_boot_exist = let init_boot_exist =
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists(); 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();
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init { let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
format!("/dev/block/by-name/init_boot{slot_suffix}") format!("/dev/block/by-name/init_boot{slot_suffix}")
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
} else { } else {
format!("/dev/block/by-name/boot{slot_suffix}") format!("/dev/block/by-name/boot{slot_suffix}")
}; };