blob: 82374c0a4abac7fb58a24fe87b7da120653c9d7b [file] [log] [blame]
Chris Frantzd2585452021-11-05 12:18:41 -07001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::{ensure, Result};
6use erased_serde::Serialize;
7use std::any::Any;
8use std::path::PathBuf;
9use structopt::StructOpt;
10
11use opentitanlib::app::command::CommandDispatch;
12use opentitanlib::app::TransportWrapper;
13
14use opentitanlib::util::image::ImageAssembler;
15use opentitanlib::util::parse_int::ParseInt;
16
17/// Bootstrap the target device.
18#[derive(Debug, StructOpt)]
19pub struct AssembleCommand {
20 #[structopt(
21 short,
22 long,
23 parse(try_from_str=usize::from_str),
24 default_value="1048576",
25 help="The size of the image to assemble"
26 )]
27 size: usize,
28 #[structopt(
29 short,
30 long,
31 parse(try_from_str),
32 default_value = "true",
33 help = "Whether or not the assembled image is mirrored"
34 )]
35 mirror: bool,
36 #[structopt(short, long, help = "Filename to write the assembled image to")]
37 output: PathBuf,
38 #[structopt(
39 name = "FILE",
40 min_values(1),
41 help = "One or more filename@offset specifiers to assemble into an image"
42 )]
43 filename: Vec<String>,
44}
45
46impl CommandDispatch for AssembleCommand {
47 fn run(
48 &self,
49 _context: &dyn Any,
50 _transport: &TransportWrapper,
51 ) -> Result<Option<Box<dyn Serialize>>> {
52 // The `min_values` structopt attribute should take care of this, but it doesn't.
53 ensure!(
54 !self.filename.is_empty(),
55 "You must supply at least one filename"
56 );
57 let mut image = ImageAssembler::with_params(self.size, self.mirror);
58 image.parse(&self.filename)?;
59 let content = image.assemble()?;
60 std::fs::write(&self.output, &content)?;
61 Ok(None)
62 }
63}
64
65#[derive(Debug, StructOpt, CommandDispatch)]
66/// Image manipulation commands.
67pub enum Image {
68 Assemble(AssembleCommand),
69}