diff --git a/userspace/ksud_magic/src/boot_patch.rs b/userspace/ksud_magic/src/boot_patch.rs index 6abe37f4..0e7f789b 100644 --- a/userspace/ksud_magic/src/boot_patch.rs +++ b/userspace/ksud_magic/src/boot_patch.rs @@ -310,7 +310,7 @@ pub fn restore( let skip_init = kmi.starts_with("android12-"); - let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?; + let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?; println!("- Unpacking boot image"); let status = Command::new(&magiskboot) @@ -574,7 +574,7 @@ fn do_patch( let skip_init = kmi.starts_with("android12-"); 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, &magiskboot)?; let bootimage = bootimage.display().to_string(); @@ -855,16 +855,17 @@ fn find_boot_image( ota: bool, is_replace_kernel: bool, workdir: &Path, + magiskboot: &Path, ) -> Result<(PathBuf, Option)> { 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"); + bail!("- Please specify a boot image"); } let mut slot_suffix = utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from("")); @@ -877,27 +878,104 @@ fn find_boot_image( } }; - 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(); - let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init { - 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 { - format!("/dev/block/by-name/boot{slot_suffix}") - }; + 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}"); - println!("- Bootdevice: {boot_partition}"); + 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 { + 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) + } + + let mut selected_partition = &boot_partition; + + 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 { + if 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 { + if 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}"); let tmp_boot_path = workdir.join("boot.img"); - dd(&boot_partition, &tmp_boot_path)?; + dd(selected_partition, &tmp_boot_path)?; - ensure!(tmp_boot_path.exists(), "boot image not found"); + ensure!(tmp_boot_path.exists(), "- Tmp boot image not found"); bootimage = tmp_boot_path; - bootdevice = Some(boot_partition); + bootdevice = Some(selected_partition.to_string()); }; Ok((bootimage, bootdevice)) } diff --git a/userspace/ksud_overlayfs/src/boot_patch.rs b/userspace/ksud_overlayfs/src/boot_patch.rs index 6abe37f4..0e7f789b 100644 --- a/userspace/ksud_overlayfs/src/boot_patch.rs +++ b/userspace/ksud_overlayfs/src/boot_patch.rs @@ -310,7 +310,7 @@ pub fn restore( let skip_init = kmi.starts_with("android12-"); - let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir)?; + let (bootimage, bootdevice) = find_boot_image(&image, skip_init, false, false, workdir, &magiskboot)?; println!("- Unpacking boot image"); let status = Command::new(&magiskboot) @@ -574,7 +574,7 @@ fn do_patch( let skip_init = kmi.starts_with("android12-"); 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, &magiskboot)?; let bootimage = bootimage.display().to_string(); @@ -855,16 +855,17 @@ fn find_boot_image( ota: bool, is_replace_kernel: bool, workdir: &Path, + magiskboot: &Path, ) -> Result<(PathBuf, Option)> { 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"); + bail!("- Please specify a boot image"); } let mut slot_suffix = utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from("")); @@ -877,27 +878,104 @@ fn find_boot_image( } }; - 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(); - let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init { - 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 { - format!("/dev/block/by-name/boot{slot_suffix}") - }; + 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}"); - println!("- Bootdevice: {boot_partition}"); + 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 { + 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) + } + + let mut selected_partition = &boot_partition; + + 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 { + if 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 { + if 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}"); let tmp_boot_path = workdir.join("boot.img"); - dd(&boot_partition, &tmp_boot_path)?; + dd(selected_partition, &tmp_boot_path)?; - ensure!(tmp_boot_path.exists(), "boot image not found"); + ensure!(tmp_boot_path.exists(), "- Tmp boot image not found"); bootimage = tmp_boot_path; - bootdevice = Some(boot_partition); + bootdevice = Some(selected_partition.to_string()); }; Ok((bootimage, bootdevice)) }