[signer] Add image type support

This change adds a new CLI argument for image type (`rom_ext` or
`owner`) and updates relevant `meson.build` files.

Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/rom_exts/meson.build b/sw/device/silicon_creator/rom_exts/meson.build
index 5200123..ab12156 100644
--- a/sw/device/silicon_creator/rom_exts/meson.build
+++ b/sw/device/silicon_creator/rom_exts/meson.build
@@ -156,6 +156,7 @@
         output: '@BASENAME@.@0@.signed.bin'.format(key_name),
         command: [
           rom_ext_signer_export.full_path(),
+          'rom_ext',
           '@INPUT@',
           key_info['path'],
           rom_ext_elf.full_path(),
diff --git a/sw/device/tests/meson.build b/sw/device/tests/meson.build
index 770328d..6d905e6 100644
--- a/sw/device/tests/meson.build
+++ b/sw/device/tests/meson.build
@@ -726,6 +726,7 @@
         output: '@BASENAME@.@0@.signed.bin'.format(key_name),
         command: [
           rom_ext_signer_export.full_path(),
+          'rom_ext',
           '@INPUT@',
           key_info['path'],
           sw_test_elf.full_path(),
diff --git a/sw/host/rom_ext_image_tools/signer/image/src/image.rs b/sw/host/rom_ext_image_tools/signer/image/src/image.rs
index a30e2fc..24e98d1 100644
--- a/sw/host/rom_ext_image_tools/signer/image/src/image.rs
+++ b/sw/host/rom_ext_image_tools/signer/image/src/image.rs
@@ -45,7 +45,8 @@
     }
 
     pub fn signed_bytes(&self) -> Vec<u8> {
-        self.bytes().split_off(self.manifest.signature.as_bytes().len())
+        self.bytes()
+            .split_off(self.manifest.signature.as_bytes().len())
     }
 }
 
diff --git a/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs b/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
index cdd2406..af7de91 100644
--- a/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
+++ b/sw/host/rom_ext_image_tools/signer/image/src/manifest.rs
@@ -25,11 +25,16 @@
 //      --no-doc-comments --no-layout-tests \
 //      sw/device/silicon_creator/lib/manifest.h \
 //      -- -I./ -Isw/device/lib/base/freestanding
+// TODO: Generate some constants as hex if possible, replacing manually for now.
 
 pub const MANIFEST_SIZE: u32 = 896;
-pub const MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL: u32 = 0xA5A5A5A5;
-pub const MANIFEST_LENGTH_FIELD_MIN: u32 = 896;
-pub const MANIFEST_LENGTH_FIELD_MAX: u32 = 65536;
+pub const MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL: u32 = 0xa5a5a5a5;
+pub const MANIFEST_IDENTIFIER_ROM_EXT: u32 = 0x4552544f;
+pub const MANIFEST_IDENTIFIER_OWNER_STAGE: u32 = 0x4f53544f;
+pub const MANIFEST_LENGTH_FIELD_ROM_EXT_MIN: u32 = 896;
+pub const MANIFEST_LENGTH_FIELD_ROM_EXT_MAX: u32 = 0x10000;
+pub const MANIFEST_LENGTH_FIELD_OWNER_STAGE_MIN: u32 = 896;
+pub const MANIFEST_LENGTH_FIELD_OWNER_STAGE_MAX: u32 = 0x70000;
 
 /// Manifest for boot stage images stored in flash.
 #[repr(C)]
@@ -88,7 +93,8 @@
         Self {
             selector_bits: 0,
             device_id: LifecycleDeviceId {
-                device_id: [MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL; 8usize],
+                device_id: [MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL;
+                    8usize],
             },
             manuf_state_creator: MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL,
             manuf_state_owner: MANIFEST_USAGE_CONSTRAINT_UNSELECTED_WORD_VAL,
diff --git a/sw/host/rom_ext_image_tools/signer/src/main.rs b/sw/host/rom_ext_image_tools/signer/src/main.rs
index af44b04..ef0d57a 100644
--- a/sw/host/rom_ext_image_tools/signer/src/main.rs
+++ b/sw/host/rom_ext_image_tools/signer/src/main.rs
@@ -11,6 +11,7 @@
 use std::fs;
 use std::mem::size_of;
 use std::path::PathBuf;
+use std::str::FromStr;
 
 use mundane::hash::Sha256;
 use mundane::public::rsa::RsaPkcs1v15;
@@ -39,8 +40,27 @@
     mundane::public::rsa::RsaSignature<B3072, RsaPkcs1v15, Sha256>;
 type PrivateKey = mundane::public::rsa::RsaPrivKey<B3072>;
 
+#[derive(Copy, Clone)]
+enum ImageType {
+    RomExt,
+    OwnerStage,
+}
+
+impl FromStr for ImageType {
+    type Err = anyhow::Error;
+
+    fn from_str(s: &str) -> Result<Self> {
+        match s {
+            "rom_ext" => Ok(ImageType::RomExt),
+            "owner" => Ok(ImageType::OwnerStage),
+            _ => bail!("Unexpected image type: {}", s),
+        }
+    }
+}
+
 // TODO: Remove this struct when this functionality is integrated into `opentitantool`.
 struct Args {
+    image_type: ImageType,
     input_image: PathBuf,
     priv_key: PathBuf,
     elf_file: PathBuf,
@@ -51,13 +71,16 @@
     pub fn new(args: env::ArgsOs) -> Result<Args> {
         let args = args.skip(1).collect::<Vec<_>>();
         match args.as_slice() {
-            [input_image, priv_key, elf_file, output_image] => Ok(Args {
+            [image_type, input_image, priv_key, elf_file, output_image] => Ok(Args {
+                    image_type: ImageType::from_str(&image_type.to_string_lossy())?,
                     input_image: PathBuf::from(input_image),
                     priv_key: PathBuf::from(priv_key),
                     elf_file: PathBuf::from(elf_file),
                     output_image: PathBuf::from(output_image),
                 }),
-            args => bail!("Expected exactly 4 positional arguments: input image, private key, elf file, and output image, got: {}.", args.len()),
+            args => bail!("Expected exactly 5 positional arguments: \
+                          image type, input image, private key, elf file, and output image, \
+                          got: {}.", args.len()),
         }
     }
 }
@@ -84,6 +107,7 @@
 // TODO: This function must use a public key.
 fn update_image_manifest(
     image: &mut Image,
+    image_type: ImageType,
     key: &PrivateKey,
     elf: &ElfFile32,
 ) -> Result<()> {
@@ -93,8 +117,21 @@
             .address(),
     )?;
 
+    let (identifier, allowed_lengths) = match image_type {
+        ImageType::RomExt => (
+            manifest::MANIFEST_IDENTIFIER_ROM_EXT,
+            manifest::MANIFEST_LENGTH_FIELD_ROM_EXT_MIN
+                ..=manifest::MANIFEST_LENGTH_FIELD_ROM_EXT_MAX,
+        ),
+        ImageType::OwnerStage => (
+            manifest::MANIFEST_IDENTIFIER_OWNER_STAGE,
+            manifest::MANIFEST_LENGTH_FIELD_OWNER_STAGE_MIN
+                ..=manifest::MANIFEST_LENGTH_FIELD_OWNER_STAGE_MAX,
+        ),
+    };
+
     *image.manifest = Manifest {
-        identifier: 0x4552544f,
+        identifier,
         length: u32::try_from(image.bytes().len())?,
         code_start: {
             let addr = u32::try_from(
@@ -176,9 +213,7 @@
         "`entry_point` is outside the code region."
     );
     ensure!(
-        (manifest::MANIFEST_LENGTH_FIELD_MIN
-            ..=manifest::MANIFEST_LENGTH_FIELD_MAX)
-            .contains(&image.manifest.length),
+        allowed_lengths.contains(&image.manifest.length),
         "`length` is outside the allowed range."
     );
 
@@ -232,7 +267,7 @@
     let elf = fs::read(&args.elf_file)?;
     let elf = ElfFile32::parse(elf.as_slice())?;
 
-    update_image_manifest(&mut image, &key, &elf)?;
+    update_image_manifest(&mut image, args.image_type, &key, &elf)?;
     let sig = calculate_image_signature(&image, &key)?;
     update_image_signature(&mut image, sig)?;