[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 {