Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add firmware updater #2455

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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