diff --git a/userspace/ksud/src/assets.rs b/userspace/ksud/src/assets.rs index b9ed994d..ccfff71f 100644 --- a/userspace/ksud/src/assets.rs +++ b/userspace/ksud/src/assets.rs @@ -37,3 +37,13 @@ pub fn copy_assets_to_file(name: &str, dst: impl AsRef) -> Result<()> { std::fs::write(dst, asset.data)?; Ok(()) } + +pub fn list_supported_kmi() -> Result> { + let mut list = Vec::new(); + for file in Asset::iter() { + if let Some(kmi) = file.strip_suffix(".ko") { + list.push(kmi.to_string()); + } + } + Ok(list) +} diff --git a/userspace/ksud/src/boot_patch.rs b/userspace/ksud/src/boot_patch.rs index 03beac24..c0b4543b 100644 --- a/userspace/ksud/src/boot_patch.rs +++ b/userspace/ksud/src/boot_patch.rs @@ -53,7 +53,7 @@ fn parse_kmi(version: &str) -> Result { let re = Regex::new(r"(.* )?(\d+\.\d+)(\S+)?(android\d+)(.*)")?; let cap = re .captures(version) - .ok_or_else(|| anyhow::anyhow!("Unknown KMI, please choose manually."))?; + .ok_or_else(|| anyhow::anyhow!("Failed to get KMI from boot/modules"))?; let android_version = cap.get(4).map_or("", |m| m.as_str()); let kernel_version = cap.get(2).map_or("", |m| m.as_str()); Ok(format!("{android_version}-{kernel_version}")) @@ -85,13 +85,13 @@ fn parse_kmi_from_modules() -> Result { } #[cfg(target_os = "android")] -fn get_kmi() -> Result { +pub fn get_current_kmi() -> Result { parse_kmi_from_uname().or_else(|_| parse_kmi_from_modules()) } #[cfg(not(target_os = "android"))] -fn get_kmi() -> Result { - bail!("Unknown KMI, try use --kmi to specify it.") +pub fn get_current_kmi() -> Result { + bail!("Unsupported platform") } fn do_cpio_cmd(magiskboot: &Path, workding_dir: &Path, cmd: &str) -> Result<()> { @@ -261,7 +261,11 @@ fn do_patch( std::fs::copy(kmod, kmod_file).with_context(|| "copy kernel module failed".to_string())?; } else { // If kmod is not specified, extract from assets - let kmi = if let Some(kmi) = kmi { kmi } else { get_kmi()? }; + let kmi = if let Some(kmi) = kmi { + kmi + } else { + get_current_kmi().with_context(|| "Unknown KMI, please choose LKM manually")? + }; println!("- KMI: {kmi}"); let name = format!("{kmi}_kernelsu.ko"); assets::copy_assets_to_file(&name, kmod_file) @@ -331,8 +335,10 @@ fn do_patch( // if image is specified, write to output file let output_dir = out.unwrap_or(std::env::current_dir()?); let now = chrono::Utc::now(); - let output_image = - output_dir.join(format!("kernelsu_patched_{}.img", now.format("%Y%m%d_%H%M%S"))); + let output_image = output_dir.join(format!( + "kernelsu_patched_{}.img", + now.format("%Y%m%d_%H%M%S") + )); if std::fs::rename(&new_boot, &output_image).is_err() { std::fs::copy(&new_boot, &output_image) diff --git a/userspace/ksud/src/cli.rs b/userspace/ksud/src/cli.rs index 4f8537d5..fd995a8a 100644 --- a/userspace/ksud/src/cli.rs +++ b/userspace/ksud/src/cli.rs @@ -87,12 +87,28 @@ enum Commands { #[arg(long, default_value = None)] kmi: Option, }, + + /// Show boot information + BootInfo { + #[command(subcommand)] + command: BootInfo, + }, /// For developers Debug { #[command(subcommand)] command: Debug, }, } + +#[derive(clap::Subcommand, Debug)] +enum BootInfo { + /// show current kmi version + CurrentKmi, + + /// show supported kmi versions + SupportedKmi, +} + #[derive(clap::Subcommand, Debug)] enum Debug { /// Set the manager app, kernel CONFIG_KSU_DEBUG should be enabled. @@ -322,6 +338,20 @@ pub fn run() -> Result<()> { magiskboot, kmi, } => crate::boot_patch::patch(boot, kernel, module, init, ota, flash, out, magiskboot, kmi), + + Commands::BootInfo { command } => match command { + BootInfo::CurrentKmi => { + let kmi = crate::boot_patch::get_current_kmi()?; + println!("{}", kmi); + // return here to avoid printing the error message + return Ok(()); + } + BootInfo::SupportedKmi => { + let kmi = crate::assets::list_supported_kmi()?; + kmi.iter().for_each(|kmi| println!("{}", kmi)); + return Ok(()); + } + }, }; if let Err(e) = &result {