mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: automatically regenerate initramfs on arch and debian-based systems
https://github.com/ilya-zlobintsev/LACT/issues/236 https://github.com/ilya-zlobintsev/LACT/issues/190
This commit is contained in:
parent
ea6d4d2733
commit
5610e72ab6
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1311,6 +1311,7 @@ dependencies = [
|
||||
"lact-schema",
|
||||
"libdrm_amdgpu_sys",
|
||||
"nix 0.27.1",
|
||||
"os-release",
|
||||
"pciid-parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -1588,6 +1589,15 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os-release"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82f29ae2f71b53ec19cc23385f8e4f3d90975195aa3d09171ba3bef7159bec27"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
@ -127,7 +127,7 @@ impl DaemonClient {
|
||||
}
|
||||
|
||||
request_plain!(get_system_info, SystemInfo, SystemInfo);
|
||||
request_plain!(enable_overdrive, EnableOverdrive, ());
|
||||
request_plain!(enable_overdrive, EnableOverdrive, String);
|
||||
request_plain!(generate_debug_snapshot, GenerateSnapshot, String);
|
||||
request_with_id!(get_device_info, DeviceInfo, DeviceInfo);
|
||||
request_with_id!(get_device_stats, DeviceStats, DeviceStats);
|
||||
|
@ -36,3 +36,4 @@ zbus = { version = "3.14.1", default-features = false, features = ["tokio"] }
|
||||
libdrm_amdgpu_sys = { optional = true, version = "0.4.0" }
|
||||
tar = "0.4.40"
|
||||
chrono = "0.4.31"
|
||||
os-release = "0.1.0"
|
||||
|
@ -1,11 +1,13 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use lact_schema::SystemInfo;
|
||||
use lact_schema::{InitramfsType, SystemInfo};
|
||||
use os_release::{OsRelease, OS_RELEASE};
|
||||
use std::{
|
||||
fs::{self, File, Permissions},
|
||||
io::Write,
|
||||
os::unix::prelude::PermissionsExt,
|
||||
process::Command,
|
||||
};
|
||||
use tracing::{info, warn};
|
||||
|
||||
const PP_OVERDRIVE_MASK: u64 = 0x4000;
|
||||
pub const PP_FEATURE_MASK_PATH: &str = "/sys/module/amdgpu/parameters/ppfeaturemask";
|
||||
@ -41,7 +43,7 @@ pub fn info() -> anyhow::Result<SystemInfo<'static>> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn enable_overdrive() -> anyhow::Result<()> {
|
||||
pub fn enable_overdrive() -> anyhow::Result<String> {
|
||||
let current_mask = read_current_mask()?;
|
||||
|
||||
let new_mask = current_mask | PP_OVERDRIVE_MASK;
|
||||
@ -58,7 +60,14 @@ pub fn enable_overdrive() -> anyhow::Result<()> {
|
||||
file.write_all(conf.as_bytes())
|
||||
.context("Could not write config")?;
|
||||
|
||||
Ok(())
|
||||
let message = match regenerate_initramfs() {
|
||||
Ok(initramfs_type) => {
|
||||
format!("Initramfs was successfully regenerated (detected type {initramfs_type:?})")
|
||||
}
|
||||
Err(err) => format!("{err:#}"),
|
||||
};
|
||||
|
||||
Ok(message)
|
||||
}
|
||||
|
||||
fn read_current_mask() -> anyhow::Result<u64> {
|
||||
@ -70,3 +79,102 @@ fn read_current_mask() -> anyhow::Result<u64> {
|
||||
|
||||
u64::from_str_radix(ppfeaturemask, 16).context("Invalid ppfeaturemask")
|
||||
}
|
||||
|
||||
fn regenerate_initramfs() -> anyhow::Result<InitramfsType> {
|
||||
let os_release = OS_RELEASE.as_ref().context("Could not detect distro")?;
|
||||
match detect_initramfs_type(os_release) {
|
||||
Some(initramfs_type) => {
|
||||
info!("Detected initramfs type {initramfs_type:?}, regenerating");
|
||||
let result = match initramfs_type {
|
||||
InitramfsType::Debian => run_command("update-initramfs", &["-u"]),
|
||||
InitramfsType::Mkinitcpio => run_command("mkinitcpio", &["-P"]),
|
||||
};
|
||||
result.map(|()| initramfs_type)
|
||||
}
|
||||
None => Err(anyhow!(
|
||||
"Could not determine initramfs type, manual initramfs regeneration may be required"
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_initramfs_type(os_release: &OsRelease) -> Option<InitramfsType> {
|
||||
let id_like: Vec<_> = os_release.id_like.split_whitespace().collect();
|
||||
|
||||
if os_release.id == "debian" || id_like.contains(&"debian") {
|
||||
Some(InitramfsType::Debian)
|
||||
} else if os_release.id == "arch" || id_like.contains(&"arch") {
|
||||
if Command::new("mkinitcpio").arg("--version").output().is_ok() {
|
||||
Some(InitramfsType::Mkinitcpio)
|
||||
} else {
|
||||
warn!(
|
||||
"Arch-based system with no mkinitcpio detected, refusing to regenerate initramfs"
|
||||
);
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn run_command(exec: &str, args: &[&str]) -> anyhow::Result<()> {
|
||||
info!("Running {exec} with args {args:?}");
|
||||
let output = Command::new(exec)
|
||||
.args(args)
|
||||
.output()
|
||||
.context("Could not run command")?;
|
||||
if output.status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
let stdout = String::from_utf8(output.stdout).context("stdout is not valid UTF-8")?;
|
||||
let stderr = String::from_utf8(output.stderr).context("stderr is not valid UTF-8")?;
|
||||
Err(anyhow!("Command exited with error: {stdout}\n{stderr}"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::server::system::detect_initramfs_type;
|
||||
use lact_schema::InitramfsType;
|
||||
use os_release::OsRelease;
|
||||
|
||||
#[test]
|
||||
fn detect_initramfs_debian() {
|
||||
let data = r#"
|
||||
PRETTY_NAME="Debian GNU/Linux trixie/sid"
|
||||
NAME="Debian GNU/Linux"
|
||||
VERSION_CODENAME=trixie
|
||||
ID=debian
|
||||
HOME_URL="https://www.debian.org/"
|
||||
SUPPORT_URL="https://www.debian.org/support"
|
||||
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||
"#;
|
||||
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
||||
assert_eq!(
|
||||
Some(InitramfsType::Debian),
|
||||
detect_initramfs_type(&os_release)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detect_initramfs_mint() {
|
||||
let data = r#"
|
||||
NAME="Linux Mint"
|
||||
VERSION="21.2 (Victoria)"
|
||||
ID=linuxmint
|
||||
ID_LIKE="ubuntu debian"
|
||||
PRETTY_NAME="Linux Mint 21.2"
|
||||
VERSION_ID="21.2"
|
||||
HOME_URL="https://www.linuxmint.com/"
|
||||
SUPPORT_URL="https://forums.linuxmint.com/"
|
||||
BUG_REPORT_URL="http://linuxmint-troubleshooting-guide.readthedocs.io/en/latest/"
|
||||
PRIVACY_POLICY_URL="https://www.linuxmint.com/"
|
||||
VERSION_CODENAME=victoria
|
||||
UBUNTU_CODENAME=jammy
|
||||
"#;
|
||||
let os_release: OsRelease = data.lines().map(str::to_owned).collect();
|
||||
assert_eq!(
|
||||
Some(InitramfsType::Debian),
|
||||
detect_initramfs_type(&os_release)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ impl App {
|
||||
}
|
||||
|
||||
fn enable_overclocking(&self) {
|
||||
let text = format!("This will enable the overdrive feature of the amdgpu driver by creating a file at <b>{MODULE_CONF_PATH}</b>. Are you sure you want to do this?");
|
||||
let text = format!("This will enable the overdrive feature of the amdgpu driver by creating a file at <b>{MODULE_CONF_PATH}</b> and updating the initramfs. Are you sure you want to do this? (Note: the GUI may freeze for a bit)");
|
||||
let dialog = MessageDialog::builder()
|
||||
.title("Enable Overclocking")
|
||||
.use_markup(true)
|
||||
@ -518,10 +518,10 @@ impl App {
|
||||
dialog.run_async(clone!(@strong self as app => move |diag, response| {
|
||||
if response == ResponseType::Ok {
|
||||
match app.daemon_client.enable_overdrive().and_then(|buffer| buffer.inner()) {
|
||||
Ok(_) => {
|
||||
Ok(msg) => {
|
||||
let success_dialog = MessageDialog::builder()
|
||||
.title("Success")
|
||||
.text("Overclocking successfully enabled. A system reboot is required to apply the changes")
|
||||
.text(format!("Overclocking successfully enabled. A system reboot is required to apply the changes.\nSystem message: {msg}"))
|
||||
.message_type(MessageType::Info)
|
||||
.buttons(ButtonsType::Ok)
|
||||
.build();
|
||||
|
@ -242,3 +242,9 @@ pub struct PowerState<T> {
|
||||
pub enabled: bool,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum InitramfsType {
|
||||
Debian,
|
||||
Mkinitcpio,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user