[skip ci]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:
@@ -153,82 +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 do_vendor_init_boot_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
fn is_magisk_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
|
||||||
let vendor_init_boot_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
|
||||||
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(vendor_init_boot_cpio)
|
.arg(cpio_path)
|
||||||
.arg(cmd)
|
.arg("test")
|
||||||
.status()?;
|
.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
|
// 0: stock, 1: magisk
|
||||||
Ok(status.code() == Some(1))
|
Ok(status.code() == Some(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_magisk_patched_vendor_init_boot(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
fn is_kernelsu_patched(magiskboot: &Path, workdir: &Path, cpio_path: &Path) -> Result<bool> {
|
||||||
let vendor_init_boot_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
|
||||||
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", vendor_init_boot_cpio.to_str().unwrap(), "test"])
|
.arg("cpio")
|
||||||
.status()?;
|
.arg(cpio_path)
|
||||||
|
.arg("exists kernelsu.ko")
|
||||||
// 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()?;
|
.status()?;
|
||||||
|
|
||||||
Ok(status.success())
|
Ok(status.success())
|
||||||
@@ -278,24 +236,37 @@ pub fn restore(
|
|||||||
.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_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
if !ramdisk.exists() {
|
||||||
let is_kernelsu_patched_vendor_init_boot =
|
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
|
||||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
}
|
||||||
ensure!(
|
if !ramdisk.exists() {
|
||||||
is_kernelsu_patched || is_kernelsu_patched_vendor_init_boot,
|
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||||
"boot image is not patched by KernelSU"
|
}
|
||||||
);
|
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 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,
|
||||||
&format!("extract {0} {0}", BACKUP_FILENAME),
|
ramdisk,
|
||||||
|
&format!("extract {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||||
)?;
|
)?;
|
||||||
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
|
let sha = std::fs::read(workdir.join(BACKUP_FILENAME))?;
|
||||||
let sha = String::from_utf8(sha)?;
|
let sha = String::from_utf8(sha)?;
|
||||||
@@ -317,29 +288,13 @@ pub fn restore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if new_boot.is_none() {
|
if new_boot.is_none() {
|
||||||
if no_ramdisk {
|
// remove kernelsu.ko
|
||||||
// vendor init_boot restore
|
do_cpio_cmd(&magiskboot, workdir, ramdisk, "rm kernelsu.ko")?;
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
|
||||||
// if init.real exists, restore it
|
// if init.real exists, restore it
|
||||||
let status =
|
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init.real").is_ok();
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
if status {
|
||||||
if status {
|
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init.real init")?;
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
|
||||||
} else {
|
|
||||||
let vendor_init_boot = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
|
||||||
std::fs::remove_file(vendor_init_boot)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// remove kernelsu.ko
|
|
||||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
|
||||||
// if init.real exists, restore it
|
|
||||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
|
||||||
if status {
|
|
||||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
|
||||||
} else {
|
|
||||||
let ramdisk = workdir.join("ramdisk.cpio");
|
|
||||||
std::fs::remove_file(ramdisk)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("- Repacking boot image");
|
println!("- Repacking boot image");
|
||||||
@@ -348,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"));
|
||||||
@@ -447,7 +402,7 @@ fn do_patch(
|
|||||||
match get_current_kmi() {
|
match get_current_kmi() {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("- {}", e);
|
println!("- {e}");
|
||||||
if let Some(image_path) = &image {
|
if let Some(image_path) = &image {
|
||||||
println!(
|
println!(
|
||||||
"- Trying to auto detect KMI version for {}",
|
"- Trying to auto detect KMI version for {}",
|
||||||
@@ -472,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);
|
||||||
@@ -501,71 +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 no_vendor_init_boot = !workdir
|
if !ramdisk.exists() {
|
||||||
.join("vendor_ramdisk")
|
ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio")
|
||||||
.join("init_boot.cpio")
|
}
|
||||||
.exists();
|
if !ramdisk.exists() {
|
||||||
if no_ramdisk && no_vendor_init_boot {
|
ramdisk = workdir.join("vendor_ramdisk").join("ramdisk.cpio");
|
||||||
|
}
|
||||||
|
if !ramdisk.exists() {
|
||||||
bail!("No compatible ramdisk found.");
|
bail!("No compatible ramdisk found.");
|
||||||
}
|
}
|
||||||
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir)?;
|
let ramdisk = ramdisk.as_path();
|
||||||
let is_magisk_patched_vendor_init_boot =
|
let is_magisk_patched = is_magisk_patched(&magiskboot, workdir, ramdisk)?;
|
||||||
is_magisk_patched_vendor_init_boot(&magiskboot, workdir)?;
|
ensure!(!is_magisk_patched, "Cannot work with Magisk patched image");
|
||||||
ensure!(
|
|
||||||
!is_magisk_patched || !is_magisk_patched_vendor_init_boot,
|
|
||||||
"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 is_kernelsu_patched_vendor_init_boot =
|
|
||||||
is_kernelsu_patched_vendor_init_boot(&magiskboot, workdir)?;
|
|
||||||
|
|
||||||
let mut need_backup = false;
|
let mut need_backup = false;
|
||||||
if !is_kernelsu_patched || (no_ramdisk && !is_kernelsu_patched_vendor_init_boot) {
|
if !is_kernelsu_patched {
|
||||||
if no_ramdisk {
|
// kernelsu.ko is not exist, backup init if necessary
|
||||||
// vendor init_boot patching
|
let status = do_cpio_cmd(&magiskboot, workdir, ramdisk, "exists init");
|
||||||
let status = do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "exists init");
|
if status.is_ok() {
|
||||||
if status.is_ok() {
|
do_cpio_cmd(&magiskboot, workdir, ramdisk, "mv init init.real")?;
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// kernelsu.ko is not exist, backup init if necessary
|
|
||||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
|
||||||
if status.is_ok() {
|
|
||||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
|
||||||
}
|
|
||||||
need_backup = flash;
|
|
||||||
}
|
}
|
||||||
|
need_backup = flash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if no_ramdisk {
|
do_cpio_cmd(&magiskboot, workdir, ramdisk, "add 0755 init init")?;
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
do_cpio_cmd(
|
||||||
do_vendor_init_boot_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
&magiskboot,
|
||||||
} else {
|
workdir,
|
||||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
ramdisk,
|
||||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
"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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,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");
|
||||||
@@ -587,7 +525,7 @@ fn do_patch(
|
|||||||
let output_dir = out.unwrap_or(std::env::current_dir()?);
|
let output_dir = out.unwrap_or(std::env::current_dir()?);
|
||||||
let now = chrono::Utc::now();
|
let now = chrono::Utc::now();
|
||||||
let output_image = output_dir.join(format!(
|
let output_image = output_dir.join(format!(
|
||||||
"SukiSU_patched_{}.img",
|
"kernelsu_patched_{}.img",
|
||||||
now.format("%Y%m%d_%H%M%S")
|
now.format("%Y%m%d_%H%M%S")
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -628,11 +566,11 @@ fn calculate_sha1(file_path: impl AsRef<Path>) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let result = hasher.finalize();
|
let result = hasher.finalize();
|
||||||
Ok(format!("{:x}", result))
|
Ok(format!("{result:x}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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}");
|
||||||
|
|
||||||
@@ -644,7 +582,8 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
|||||||
do_cpio_cmd(
|
do_cpio_cmd(
|
||||||
magiskboot,
|
magiskboot,
|
||||||
workdir,
|
workdir,
|
||||||
&format!("add 0755 {0} {0}", BACKUP_FILENAME),
|
cpio_path,
|
||||||
|
&format!("add 0755 {BACKUP_FILENAME} {BACKUP_FILENAME}"),
|
||||||
)?;
|
)?;
|
||||||
println!("- Stock image has been backup to");
|
println!("- Stock image has been backup to");
|
||||||
println!("- {target}");
|
println!("- {target}");
|
||||||
@@ -654,7 +593,7 @@ fn do_backup(magiskboot: &Path, workdir: &Path, image: &str) -> Result<()> {
|
|||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
fn clean_backup(sha1: &str) -> Result<()> {
|
fn clean_backup(sha1: &str) -> Result<()> {
|
||||||
println!("- Clean up backup");
|
println!("- Clean up backup");
|
||||||
let backup_name = format!("{}{}", KSU_BACKUP_FILE_PREFIX, sha1);
|
let backup_name = format!("{KSU_BACKUP_FILE_PREFIX}{sha1}");
|
||||||
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
|
let dir = std::fs::read_dir(defs::KSU_BACKUP_DIR)?;
|
||||||
for entry in dir.flatten() {
|
for entry in dir.flatten() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
|
|||||||
Reference in New Issue
Block a user