From cad75f7bf0e268aff47466fad06b6cf6343feb0d Mon Sep 17 00:00:00 2001 From: Tim Crawford Date: Mon, 14 Apr 2025 11:10:49 -0600 Subject: [PATCH] Use model-specific scripts if found Prioritize model-specific scripts over embedded flash logic. Allows using scripts and external drivers/apps for flashing systems with coreboot and 76ec. Signed-off-by: Tim Crawford --- src/app/bios.rs | 45 ++++++++++++++++++++++-- src/app/ec.rs | 92 +++++++++++++++++++++++++++++-------------------- src/app/mod.rs | 4 +++ 3 files changed, 100 insertions(+), 41 deletions(-) diff --git a/src/app/bios.rs b/src/app/bios.rs index bfc61f6..1f9f411 100644 --- a/src/app/bios.rs +++ b/src/app/bios.rs @@ -15,8 +15,8 @@ use std::uefi::reset::ResetType; use std::vars::{get_boot_item, get_boot_order, set_boot_item, set_boot_order}; use super::{ - Component, FIRMWARECAP, FIRMWAREDIR, FIRMWARENSH, FIRMWAREROM, H2OFFT, IFLASHV, UEFIFLASH, - UefiMapper, cmos, pci_mcfg, shell, + Component, FIRMWARECAP, FIRMWAREDIR, FIRMWARENSH, FIRMWAREROM, H2OFFT, IFLASHV, + MODEL_FIRMWARE_NSH, UEFIFLASH, UefiMapper, cmos, pci_mcfg, shell, }; fn copy_region( @@ -245,7 +245,46 @@ impl Component for BiosComponent { } fn flash(&self) -> Result<()> { - if let Some((mut spi, _hsfsts_ctl)) = self.spi() { + if find(MODEL_FIRMWARE_NSH).is_ok() { + find(FIRMWARENSH)?; + + let mut boot_options: Vec<(u16, Vec)> = vec![]; + + let order = get_boot_order(); + if order.is_ok() { + println!("Preserving boot order"); + for num in order.clone().unwrap() { + if let Ok(item) = get_boot_item(num) { + boot_options.push((num, item)); + } else { + println!("Failed to read Boot{:>04X}", num); + } + } + } else { + println!("Failed to preserve boot order"); + } + + let cmd = format!("{} {} bios flash", FIRMWARENSH, FIRMWAREDIR); + let status = shell(&cmd)?; + + if let Ok(order) = order { + if set_boot_order(&order).is_ok() { + for (num, data) in boot_options { + if set_boot_item(num, &data).is_err() { + println!("Failed to write Boot{:>04X}", num); + } + } + println!("Restored boot order"); + } else { + println!("Failed to restore boot order"); + } + } + + if status != 0 { + println!("{} Flash Error: {}", self.name(), status); + return Err(Status::DEVICE_ERROR); + } + } else if let Some((mut spi, _hsfsts_ctl)) = self.spi() { // Read new data let mut new; { diff --git a/src/app/ec.rs b/src/app/ec.rs index 16bdacd..73889ce 100644 --- a/src/app/ec.rs +++ b/src/app/ec.rs @@ -16,7 +16,8 @@ use std::{ }; use super::{ - Component, EC2ROM, ECROM, ECTAG, FIRMWAREDIR, FIRMWARENSH, pci_read, shell, sideband::Sideband, + Component, EC2ROM, ECROM, ECTAG, FIRMWAREDIR, FIRMWARENSH, MODEL_EC_NSH, pci_read, shell, + sideband::Sideband, }; pub struct UefiTimeout { @@ -767,49 +768,64 @@ impl Component for EcComponent { println!("file version: {:?}", str::from_utf8(firmware.version)); } - let result = match &self.ec { - EcKind::Pang(_pmc, _system_version) => { - find(FIRMWARENSH)?; - let command = if self.master { "ec" } else { "ec2" }; - let status = shell(&format!( - "{} {} {} flash", - FIRMWARENSH, FIRMWAREDIR, command - ))?; - if status == 0 { - Ok(()) - } else { - println!("{} Flash Error: {}", self.name(), status); - Err(Status::DEVICE_ERROR) - } + let result = if find(MODEL_EC_NSH).is_ok() { + find(FIRMWARENSH)?; + let command = if self.master { "ec" } else { "ec2" }; + let status = shell(&format!( + "{} {} {} flash", + FIRMWARENSH, FIRMWAREDIR, command + ))?; + if status == 0 { + Ok(()) + } else { + println!("{} Flash Error: {}", self.name(), status); + Err(Status::DEVICE_ERROR) } - EcKind::System76(_ec, _pmc) => { - // System76 EC requires reset to load new firmware - requires_reset = true; - - // Flash main ROM - match unsafe { flash(&firmware_data, SpiTarget::Main) } { - Ok(()) => Ok(()), - Err(err) => { - println!("{} Flash Error: {:X?}", self.name(), err); + } else { + match &self.ec { + EcKind::Pang(_pmc, _system_version) => { + find(FIRMWARENSH)?; + let command = if self.master { "ec" } else { "ec2" }; + let status = shell(&format!( + "{} {} {} flash", + FIRMWARENSH, FIRMWAREDIR, command + ))?; + if status == 0 { + Ok(()) + } else { + println!("{} Flash Error: {}", self.name(), status); Err(Status::DEVICE_ERROR) } } - } - EcKind::Legacy(_ec) => { - requires_reset = true; - - // Use open source flashing code - match unsafe { flash_legacy(&firmware_data) } { - Ok(()) => Ok(()), - Err(err) => { - println!("{} Flash Error: {:X?}", self.name(), err); - Err(Status::DEVICE_ERROR) + EcKind::System76(_ec, _pmc) => { + // System76 EC requires reset to load new firmware + requires_reset = true; + + // Flash main ROM + match unsafe { flash(&firmware_data, SpiTarget::Main) } { + Ok(()) => Ok(()), + Err(err) => { + println!("{} Flash Error: {:X?}", self.name(), err); + Err(Status::DEVICE_ERROR) + } } } - } - EcKind::Unknown => { - println!("{} Failed to flash EcKind::Unknown", self.name()); - Err(Status::DEVICE_ERROR) + EcKind::Legacy(_ec) => { + requires_reset = true; + + // Use open source flashing code + match unsafe { flash_legacy(&firmware_data) } { + Ok(()) => Ok(()), + Err(err) => { + println!("{} Flash Error: {:X?}", self.name(), err); + Err(Status::DEVICE_ERROR) + } + } + } + EcKind::Unknown => { + println!("{} Failed to flash EcKind::Unknown", self.name()); + Err(Status::DEVICE_ERROR) + } } }; diff --git a/src/app/mod.rs b/src/app/mod.rs index b9a8924..7a2cc5b 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -49,6 +49,10 @@ static SPLASHBMP: &str = concat!("\\", env!("BASEDIR"), "\\res\\splash.bmp"); static UEFIFLASH: &str = concat!("\\", env!("BASEDIR"), "\\firmware\\uefiflash.efi"); static UEFIFLASHTAG: &str = concat!("\\", env!("BASEDIR"), "\\firmware\\uefiflash.tag"); +// Model-specific flash scripts +static MODEL_FIRMWARE_NSH: &str = concat!("\\", env!("BASEDIR"), "\\firmware\\firmware.nsh"); +static MODEL_EC_NSH: &str = concat!("\\", env!("BASEDIR"), "\\firmware\\ec.nsh"); + fn shell(cmd: &str) -> Result { exec_path( SHELLEFI,