mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: add support for dumping VBIOS to a file (#305)
* feat: vbios dump daemon implementation * feat: vbios dump ui
This commit is contained in:
parent
06e061b88e
commit
6dc35200d7
@ -126,6 +126,7 @@ impl DaemonClient {
|
||||
);
|
||||
request_with_id!(get_power_states, GetPowerStates, PowerStates);
|
||||
request_with_id!(reset_pmfw, ResetPmfw, u64);
|
||||
request_with_id!(dump_vbios, VbiosDump, Vec<u8>);
|
||||
|
||||
pub fn set_performance_level(
|
||||
&self,
|
||||
|
@ -28,7 +28,7 @@ use std::{
|
||||
str::FromStr,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{collections::BTreeMap, time::Instant};
|
||||
use std::{collections::BTreeMap, fs, time::Instant};
|
||||
use tokio::{
|
||||
select,
|
||||
sync::Notify,
|
||||
@ -623,6 +623,18 @@ impl GpuController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vbios_dump(&self) -> anyhow::Result<Vec<u8>> {
|
||||
let debugfs = self.debugfs_path().context("DebugFS not found")?;
|
||||
fs::read(debugfs.join("amdgpu_vbios")).context("Could not read VBIOS file")
|
||||
}
|
||||
|
||||
fn debugfs_path(&self) -> Option<PathBuf> {
|
||||
self.handle
|
||||
.get_pci_slot_name()
|
||||
.map(|slot_id| Path::new("/sys/kernel/debug/dri").join(slot_id))
|
||||
.filter(|path| path.exists())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub async fn apply_config(&self, config: &config::Gpu) -> anyhow::Result<()> {
|
||||
if let Some(cap) = config.power_cap {
|
||||
|
@ -463,6 +463,10 @@ impl<'a> Handler {
|
||||
.context("Failed to edit GPU config and set enabled power states")
|
||||
}
|
||||
|
||||
pub fn vbios_dump(&self, id: &str) -> anyhow::Result<Vec<u8>> {
|
||||
self.controller_by_id(id)?.vbios_dump()
|
||||
}
|
||||
|
||||
pub async fn generate_snapshot(&self) -> anyhow::Result<String> {
|
||||
let datetime = chrono::Local::now().format("%Y%m%d-%H%M%S");
|
||||
let out_path = format!("/tmp/LACT-sysfs-snapshot-{datetime}.tar.gz");
|
||||
|
@ -106,6 +106,7 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
|
||||
Request::SetEnabledPowerStates { id, kind, states } => {
|
||||
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
|
||||
}
|
||||
Request::VbiosDump { id } => ok_response(handler.vbios_dump(id)?),
|
||||
Request::EnableOverdrive => ok_response(system::enable_overdrive().await?),
|
||||
Request::DisableOverdrive => ok_response(system::disable_overdrive().await?),
|
||||
Request::GenerateSnapshot => ok_response(handler.generate_snapshot().await?),
|
||||
|
@ -26,6 +26,7 @@ impl Header {
|
||||
Some("Show historical charts"),
|
||||
Some("app.show-graphs-window"),
|
||||
);
|
||||
menu.append(Some("Dump VBIOS"), Some("app.dump-vbios"));
|
||||
menu.append(
|
||||
Some("Generate debug snapshot"),
|
||||
Some("app.generate-debug-snapshot"),
|
||||
|
@ -198,7 +198,14 @@ impl App {
|
||||
}))
|
||||
.build();
|
||||
|
||||
app.application.add_action_entries([snapshot_action, disable_overdive_action, show_graphs_window_action]);
|
||||
let dump_vbios_action = ActionEntry::builder("dump-vbios")
|
||||
.activate(clone!(@strong app, @strong current_gpu_id => move |_, _, _| {
|
||||
let gpu_id = current_gpu_id.borrow();
|
||||
app.dump_vbios(&gpu_id);
|
||||
}))
|
||||
.build();
|
||||
|
||||
app.application.add_action_entries([snapshot_action, disable_overdive_action, show_graphs_window_action, dump_vbios_action]);
|
||||
|
||||
app.start_stats_update_loop(current_gpu_id);
|
||||
|
||||
@ -645,6 +652,52 @@ impl App {
|
||||
}));
|
||||
}
|
||||
|
||||
fn dump_vbios(&self, gpu_id: &str) {
|
||||
match self
|
||||
.daemon_client
|
||||
.dump_vbios(gpu_id)
|
||||
.and_then(|response| response.inner())
|
||||
{
|
||||
Ok(vbios_data) => {
|
||||
let file_chooser = FileChooserDialog::new(
|
||||
Some("Save VBIOS file"),
|
||||
Some(&self.window),
|
||||
FileChooserAction::Save,
|
||||
&[
|
||||
("Save", ResponseType::Accept),
|
||||
("Cancel", ResponseType::Cancel),
|
||||
],
|
||||
);
|
||||
|
||||
let file_name_suffix = gpu_id
|
||||
.split_once('-')
|
||||
.map(|(id, _)| id.replace(':', "_"))
|
||||
.unwrap_or_default();
|
||||
file_chooser.set_current_name(&format!("{file_name_suffix}_vbios_dump.rom"));
|
||||
file_chooser.run_async(
|
||||
clone!(@strong self.window as window => move |diag, _| {
|
||||
diag.close();
|
||||
|
||||
if let Some(file) = diag.file() {
|
||||
match file.path() {
|
||||
Some(path) => {
|
||||
if let Err(err) = std::fs::write(path, vbios_data).context("Could not save vbios file") {
|
||||
show_error(&window, err);
|
||||
}
|
||||
}
|
||||
None => show_error(
|
||||
&window,
|
||||
anyhow!("Selected file has an invalid path"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
Err(err) => show_error(&self.window, err),
|
||||
}
|
||||
}
|
||||
|
||||
fn ask_confirmation(&self, gpu_id: String, mut delay: u64) {
|
||||
let text = confirmation_text(delay);
|
||||
let dialog = MessageDialog::builder()
|
||||
|
@ -52,6 +52,9 @@ pub enum Request<'a> {
|
||||
kind: PowerLevelKind,
|
||||
states: Vec<u8>,
|
||||
},
|
||||
VbiosDump {
|
||||
id: &'a str,
|
||||
},
|
||||
EnableOverdrive,
|
||||
DisableOverdrive,
|
||||
GenerateSnapshot,
|
||||
|
Loading…
Reference in New Issue
Block a user