Skip to content

Commit

Permalink
add firmware updater
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-bonez committed Oct 13, 2023
1 parent 8549b9b commit a5536f3
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 47 deletions.
83 changes: 46 additions & 37 deletions backend/src/bins/start_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::context::{DiagnosticContext, InstallContext, SetupContext};
use crate::disk::fsck::RepairStrategy;
use crate::disk::main::DEFAULT_PASSWORD;
use crate::disk::REPAIR_DISK_PATH;
use crate::firmware::update_firmware;
use crate::init::STANDBY_MODE_PATH;
use crate::net::web_server::WebServer;
use crate::shutdown::Shutdown;
Expand All @@ -19,7 +20,14 @@ use crate::util::Invoke;
use crate::{Error, ErrorKind, ResultExt, OS_ARCH};

#[instrument(skip_all)]
async fn setup_or_init(cfg_path: Option<PathBuf>) -> Result<(), Error> {
async fn setup_or_init(cfg_path: Option<PathBuf>) -> Result<Option<Shutdown>, Error> {
if update_firmware().await?.0 {
return Ok(Some(Shutdown {
export_args: None,
restart: true,
}));
}

Command::new("ln")
.arg("-sf")
.arg("/usr/lib/embassy/scripts/fake-apt")
Expand Down Expand Up @@ -146,7 +154,7 @@ async fn setup_or_init(cfg_path: Option<PathBuf>) -> Result<(), Error> {
crate::init::init(&cfg).await?;
}

Ok(())
Ok(None)
}

async fn run_script_if_exists<P: AsRef<Path>>(path: P) {
Expand Down Expand Up @@ -180,46 +188,47 @@ async fn inner_main(cfg_path: Option<PathBuf>) -> Result<Option<Shutdown>, Error

run_script_if_exists("/media/embassy/config/preinit.sh").await;

let res = if let Err(e) = setup_or_init(cfg_path.clone()).await {
async move {
tracing::error!("{}", e.source);
tracing::debug!("{}", e.source);
crate::sound::BEETHOVEN.play().await?;

let ctx = DiagnosticContext::init(
cfg_path,
if tokio::fs::metadata("/media/embassy/config/disk.guid")
.await
.is_ok()
{
Some(Arc::new(
tokio::fs::read_to_string("/media/embassy/config/disk.guid") // unique identifier for volume group - keeps track of the disk that goes with your embassy
.await?
.trim()
.to_owned(),
))
} else {
None
},
e,
)
.await?;
let res = match setup_or_init(cfg_path.clone()).await {
Err(e) => {
async move {
tracing::error!("{}", e.source);
tracing::debug!("{}", e.source);
crate::sound::BEETHOVEN.play().await?;

let server = WebServer::diagnostic(
SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 80),
ctx.clone(),
)
.await?;
let ctx = DiagnosticContext::init(
cfg_path,
if tokio::fs::metadata("/media/embassy/config/disk.guid")
.await
.is_ok()
{
Some(Arc::new(
tokio::fs::read_to_string("/media/embassy/config/disk.guid") // unique identifier for volume group - keeps track of the disk that goes with your embassy
.await?
.trim()
.to_owned(),
))
} else {
None
},
e,
)
.await?;

let shutdown = ctx.shutdown.subscribe().recv().await.unwrap();
let server = WebServer::diagnostic(
SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 80),
ctx.clone(),
)
.await?;

let shutdown = ctx.shutdown.subscribe().recv().await.unwrap();

server.shutdown().await;
server.shutdown().await;

Ok(shutdown)
Ok(shutdown)
}
.await
}
.await
} else {
Ok(None)
Ok(s) => Ok(s),
};

run_script_if_exists("/media/embassy/config/postinit.sh").await;
Expand Down
6 changes: 4 additions & 2 deletions backend/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ pub fn exit(#[context] ctx: DiagnosticContext) -> Result<(), Error> {
pub fn restart(#[context] ctx: DiagnosticContext) -> Result<(), Error> {
ctx.shutdown
.send(Some(Shutdown {
datadir: ctx.datadir.clone(),
disk_guid: ctx.disk_guid.clone(),
export_args: ctx
.disk_guid
.clone()
.map(|guid| (guid, ctx.datadir.clone())),
restart: true,
}))
.expect("receiver dropped");
Expand Down
82 changes: 82 additions & 0 deletions backend/src/firmware.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use std::path::Path;
use std::process::Stdio;

use async_compression::tokio::bufread::GzipDecoder;
use tokio::fs::File;
use tokio::io::{AsyncRead, AsyncWriteExt, BufReader};
use tokio::process::Command;

use crate::disk::fsck::RequiresReboot;
use crate::prelude::*;
use crate::util::Invoke;

pub async fn update_firmware() -> Result<RequiresReboot, Error> {
let product_name = String::from_utf8(
Command::new("dmidecode")
.arg("-s")
.arg("system-product-name")
.invoke(ErrorKind::Firmware)
.await?,
)?
.trim()
.to_owned();
if product_name.is_empty() {
return Ok(RequiresReboot(false));
}
let firmware_dir = Path::new("/usr/lib/embassy/firmware").join(&product_name);
if tokio::fs::metadata(&firmware_dir).await.is_ok() {
let current_firmware = String::from_utf8(
Command::new("dmidecode")
.arg("-s")
.arg("bios-version")
.invoke(ErrorKind::Firmware)
.await?,
)?
.trim()
.to_owned();
if tokio::fs::metadata(firmware_dir.join(format!("{current_firmware}.rom.gz")))
.await
.is_err()
&& tokio::fs::metadata(firmware_dir.join(format!("{current_firmware}.rom")))
.await
.is_err()
{
let mut firmware_read_dir = tokio::fs::read_dir(&firmware_dir).await?;
while let Some(entry) = firmware_read_dir.next_entry().await? {
let filename = entry.file_name().to_string_lossy().into_owned();
let rdr: Option<Box<dyn AsyncRead + Unpin>> = if filename.ends_with(".rom.gz") {
Some(Box::new(GzipDecoder::new(BufReader::new(
File::open(entry.path()).await?,
))))
} else if filename.ends_with(".rom") {
Some(Box::new(File::open(entry.path()).await?))
} else {
None
};
if let Some(mut rdr) = rdr {
let mut flashrom = Command::new("flashrom")
.arg("-p")
.arg("internal")
.arg("-w-")
.stdin(Stdio::piped())
.spawn()?;
let mut rom_dest = flashrom.stdin.take().or_not_found("stdin")?;
tokio::io::copy(&mut rdr, &mut rom_dest).await?;
rom_dest.flush().await?;
rom_dest.shutdown().await?;
drop(rom_dest);
let o = flashrom.wait_with_output().await?;
if !o.status.success() {
return Err(Error::new(
eyre!("{}", std::str::from_utf8(&o.stderr)?),
ErrorKind::Firmware,
));
} else {
return Ok(RequiresReboot(true));
}
}
}
}
}
Ok(RequiresReboot(false))
}
1 change: 1 addition & 0 deletions backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod developer;
pub mod diagnostic;
pub mod disk;
pub mod error;
pub mod firmware;
pub mod hostname;
pub mod init;
pub mod inspect;
Expand Down
13 changes: 5 additions & 8 deletions backend/src/shutdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use crate::{Error, OS_ARCH};

#[derive(Debug, Clone)]
pub struct Shutdown {
pub datadir: PathBuf,
pub disk_guid: Option<Arc<String>>,
pub export_args: Option<(Arc<String>, PathBuf)>,
pub restart: bool,
}
impl Shutdown {
Expand Down Expand Up @@ -55,8 +54,8 @@ impl Shutdown {
tracing::debug!("{:?}", e);
}
}
if let Some(guid) = &self.disk_guid {
if let Err(e) = export(guid, &self.datadir).await {
if let Some((guid, datadir)) = &self.export_args {
if let Err(e) = export(guid, datadir).await {
tracing::error!("Error Exporting Volume Group: {}", e);
tracing::debug!("{:?}", e);
}
Expand Down Expand Up @@ -93,8 +92,7 @@ impl Shutdown {
pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> {
ctx.shutdown
.send(Some(Shutdown {
datadir: ctx.datadir.clone(),
disk_guid: Some(ctx.disk_guid.clone()),
export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())),
restart: false,
}))
.map_err(|_| ())
Expand All @@ -106,8 +104,7 @@ pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> {
pub async fn restart(#[context] ctx: RpcContext) -> Result<(), Error> {
ctx.shutdown
.send(Some(Shutdown {
datadir: ctx.datadir.clone(),
disk_guid: Some(ctx.disk_guid.clone()),
export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())),
restart: true,
}))
.map_err(|_| ())
Expand Down
2 changes: 2 additions & 0 deletions build/lib/depends
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ cifs-utils
containerd.io
cryptsetup
curl
dmidecode
docker-ce
docker-ce-cli
docker-compose-plugin
dosfstools
e2fsprogs
ecryptfs-utils
exfatprogs
flashrom
grub-common
htop
httpdirfs
Expand Down
Binary file not shown.
2 changes: 2 additions & 0 deletions libs/models/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub enum ErrorKind {
Zram = 67,
Lshw = 68,
CpuSettings = 69,
Firmware = 70,
}
impl ErrorKind {
pub fn as_str(&self) -> &'static str {
Expand Down Expand Up @@ -153,6 +154,7 @@ impl ErrorKind {
Zram => "Zram Error",
Lshw => "LSHW Error",
CpuSettings => "CPU Settings Error",
Firmware => "Firmware Error",
}
}
}
Expand Down

0 comments on commit a5536f3

Please sign in to comment.