[opentitantool] Add image manifest commands
Add the `digest`, `manifest show`, `manifest update`, and `manifest
verify` image subcommands.
Signed-off-by: Jon Flatley <jflat@google.com>
diff --git a/sw/host/opentitanlib/src/image/manifest_def.rs b/sw/host/opentitanlib/src/image/manifest_def.rs
index ef56a2e..42af264 100644
--- a/sw/host/opentitanlib/src/image/manifest_def.rs
+++ b/sw/host/opentitanlib/src/image/manifest_def.rs
@@ -11,6 +11,7 @@
use serde::Deserialize;
use std::convert::{TryFrom, TryInto};
use std::iter::IntoIterator;
+use std::path::Path;
use thiserror::Error;
use zerocopy::AsBytes;
@@ -85,6 +86,10 @@
}
impl ManifestDef {
+ pub fn read_from_file(path: &Path) -> Result<ManifestDef> {
+ Ok(deser_hjson::from_str(&std::fs::read_to_string(path)?)?)
+ }
+
pub fn overwrite_fields(&mut self, other: ManifestDef) {
self.overwrite(other)
}
diff --git a/sw/host/opentitantool/src/command/image.rs b/sw/host/opentitantool/src/command/image.rs
index e28919d..99e7145 100644
--- a/sw/host/opentitantool/src/command/image.rs
+++ b/sw/host/opentitantool/src/command/image.rs
@@ -11,7 +11,8 @@
use opentitanlib::app::command::CommandDispatch;
use opentitanlib::app::TransportWrapper;
-use opentitanlib::image::image::ImageAssembler;
+use opentitanlib::image::image::{self, ImageAssembler};
+use opentitanlib::image::manifest_def::ManifestDef;
use opentitanlib::util::parse_int::ParseInt;
/// Bootstrap the target device.
@@ -62,6 +63,110 @@
}
}
+/// Manifest show command.
+#[derive(Debug, StructOpt)]
+pub struct ManifestShowCommand {
+ #[structopt(name = "IMAGE", help = "Filename for the image to display")]
+ image: PathBuf,
+}
+
+impl CommandDispatch for ManifestShowCommand {
+ fn run(
+ &self,
+ _context: &dyn Any,
+ _transport: &TransportWrapper,
+ ) -> Result<Option<Box<dyn Serialize>>> {
+ Ok(None)
+ }
+}
+
+/// Manifest update command.
+#[derive(Debug, StructOpt)]
+pub struct ManifestUpdateCommand {
+ #[structopt(name = "IMAGE", help = "Filename for the image to update")]
+ image: PathBuf,
+ #[structopt(
+ short,
+ long,
+ help = "Filename for an HJSON configuration specifying manifest fields"
+ )]
+ hjson_file: Option<PathBuf>,
+ #[structopt(short, long, help = "Filename for a signature file")]
+ signature_file: Option<PathBuf>,
+ #[structopt(
+ short,
+ long,
+ help = "Filename to write the output to instead of updating the input file"
+ )]
+ output: Option<PathBuf>,
+}
+
+impl CommandDispatch for ManifestUpdateCommand {
+ fn run(
+ &self,
+ _context: &dyn Any,
+ _transport: &TransportWrapper,
+ ) -> Result<Option<Box<dyn Serialize>>> {
+ let mut image = image::Image::read_from_file(&self.image)?;
+
+ self.hjson_file.as_ref().map(|hjson| -> Result<()> {
+ let def = ManifestDef::read_from_file(&hjson)?;
+ image.overwrite_manifest(def)
+ });
+
+ // TODO: Add signature update.
+
+ image.write_to_file(&self.output.as_ref().unwrap_or(&self.image))?;
+
+ Ok(None)
+ }
+}
+
+/// Manifest verify command.
+#[derive(Debug, StructOpt)]
+pub struct ManifestVerifyCommand {
+ #[structopt(name = "IMAGE", help = "Filename for the image to verify")]
+ image: PathBuf,
+}
+
+impl CommandDispatch for ManifestVerifyCommand {
+ fn run(
+ &self,
+ _context: &dyn Any,
+ _transport: &TransportWrapper,
+ ) -> Result<Option<Box<dyn Serialize>>> {
+ Ok(None)
+ }
+}
+
+/// Compute digest command.
+#[derive(Debug, StructOpt)]
+pub struct DigestCommand {
+ #[structopt(
+ name = "IMAGE",
+ help = "Filename for the image to calculate the digest for"
+ )]
+ image: PathBuf,
+}
+
+impl CommandDispatch for DigestCommand {
+ fn run(
+ &self,
+ _context: &dyn Any,
+ _transport: &TransportWrapper,
+ ) -> Result<Option<Box<dyn Serialize>>> {
+ Ok(None)
+ }
+}
+
+#[derive(Debug, StructOpt, CommandDispatch)]
+/// Manifest manipulation commands.
+pub enum ManifestCommand {
+ Show(ManifestShowCommand),
+ Update(ManifestUpdateCommand),
+ Verify(ManifestVerifyCommand),
+}
+
#[derive(Debug, StructOpt, CommandDispatch)]
/// Image manipulation commands.
pub enum Image {