[rom_ext] ROM_EXT Parser: Image Ranges

This change adds an accessor for the image ranges, which computes
useful offsets within the image:
- The Image Start
- The Start of the Signed Area
- The End of the Image (which is the End of the Signed Area)

The latter one of these is the complex issue, because it is calculated
from the image length, which is stored in the image and user-provided.
This code does no checking of the calculated value, a caller must check
this value has not overflowed, and is within the expected extents of the
slot.

Signed-off-by: Sam Elliott <selliott@lowrisc.org>
diff --git a/sw/device/rom_exts/rom_ext_manifest_parser.c b/sw/device/rom_exts/rom_ext_manifest_parser.c
index 9a4e014..9224c6f 100644
--- a/sw/device/rom_exts/rom_ext_manifest_parser.c
+++ b/sw/device/rom_exts/rom_ext_manifest_parser.c
@@ -52,8 +52,17 @@
   return true;
 }
 
-uint32_t rom_ext_get_image_len(rom_ext_manifest_t params) {
-  return mmio_region_read32(params.base_addr, ROM_EXT_IMAGE_LENGTH_OFFSET);
+rom_ext_ranges_t rom_ext_get_ranges(rom_ext_manifest_t params) {
+  uintptr_t image_length =
+      mmio_region_read32(params.base_addr, ROM_EXT_IMAGE_LENGTH_OFFSET);
+
+  rom_ext_ranges_t ranges = {
+      .image_start = params.slot,
+      .signed_area_start = params.slot + ROM_EXT_SIGNED_AREA_START_OFFSET,
+      .image_end = params.slot + image_length,
+  };
+
+  return ranges;
 }
 
 uint32_t rom_ext_get_version(rom_ext_manifest_t params) {
diff --git a/sw/device/rom_exts/rom_ext_manifest_parser.h b/sw/device/rom_exts/rom_ext_manifest_parser.h
index cb7c901..0841151 100644
--- a/sw/device/rom_exts/rom_ext_manifest_parser.h
+++ b/sw/device/rom_exts/rom_ext_manifest_parser.h
@@ -11,6 +11,19 @@
 #include "sw/device/lib/base/mmio.h"
 #include "sw/device/rom_exts/manifest.h"
 
+/**
+ * @file
+ * @brief Parser for the ROM_EXT Image Format
+ *
+ * This parser is intended to parse in-memory ROM_EXT images, from either Slot A
+ * or Slot B. The fields it is parsing are defined in
+ * `sw/device/rom_exts/manifest.md` and `sw/device_rom_exts/manifes.hjson`.
+ *
+ * This parser does minimal validity checking of the returned values, which must
+ * always be checked by the caller to ensure do not contain incorrect or
+ * insecure values.
+ */
+
 #ifdef __cplusplus
 extern "C" {
 #endif  // __cplusplus
@@ -41,6 +54,35 @@
 } rom_ext_manifest_t;
 
 /**
+ * ROM Extension Memory Extents.
+ *
+ * This information is needed for calculating the signature of the entire
+ * ROM_EXT.
+ */
+typedef struct rom_ext_ranges {
+  /**
+   * Image Start Address
+   */
+  uintptr_t image_start;
+  /**
+   * Signed Area Start Address
+   *
+   * Not all of a ROM_EXT is signed. This is the address of the first signed
+   * byte of the ROM_EXT, in memory.
+   */
+  uintptr_t signed_area_start;
+  /**
+   * Image End Address
+   *
+   * This is also the Signed Area End Address.
+   *
+   * This is parsed from user-provided data, and must be checked to ensure it
+   * the value is within the expected range, and has not overflowed.
+   */
+  uintptr_t image_end;
+} rom_ext_ranges_t;
+
+/**
  * ROM Extension image signature.
  */
 typedef struct rom_ext_signature {
@@ -132,14 +174,19 @@
 bool rom_ext_get_signature(rom_ext_manifest_t params, rom_ext_signature_t *dst);
 
 /**
- * Retrieves the ROM_EXT image length.
+ * Retrieves the ROM_EXT image address ranges.
  *
- * The memory address where ROM_EXT image length field resides, is relative.
+ * This uses the ROM_EXT image length field, and the offset of the signed area.
  *
- * @param params Parameters required for manifest parsing.
- * @return ROM_EXT image length.
+ * The results provided are absolute addresses, not relative.
+ *
+ * This assumes that the slot identified by `params` is a valid ROM_EXT, and
+ * does not check the ROM_EXT image identifier.
+ *
+ * @param params Parameters required to identify the ROM_EXT.
+ * @return The address ranges of the specific ROM_EXT.
  */
-uint32_t rom_ext_get_image_len(rom_ext_manifest_t params);
+rom_ext_ranges_t rom_ext_get_ranges(rom_ext_manifest_t params);
 
 /**
  * Retrieves the ROM_EXT image version.
diff --git a/sw/device/tests/rom_ext/rom_ext_parser_unittest.cc b/sw/device/tests/rom_ext/rom_ext_parser_unittest.cc
index e8d66f5..e8349de 100644
--- a/sw/device/tests/rom_ext/rom_ext_parser_unittest.cc
+++ b/sw/device/tests/rom_ext/rom_ext_parser_unittest.cc
@@ -66,11 +66,31 @@
   EXPECT_THAT(src_.data, ElementsAreArray(dst.data));
 }
 
-class ImageLengthGetTest : public ParserTest {};
+class RangesGetTest : public ParserTest {
+ protected:
+  testing::Matcher<rom_ext_ranges_t> EqualsRanges(const rom_ext_ranges_t &rhs) {
+    return testing::AllOf(
+        testing::Field("image_start", &rom_ext_ranges_t::image_start,
+                       rhs.image_start),
+        testing::Field("signed_area_start",
+                       &rom_ext_ranges_t::signed_area_start,
+                       rhs.signed_area_start),
+        testing::Field("image_end", &rom_ext_ranges_t::image_end,
+                       rhs.image_end));
+  }
+};
 
-TEST_F(ImageLengthGetTest, Success) {
+TEST_F(RangesGetTest, Success) {
   EXPECT_READ32(ROM_EXT_IMAGE_LENGTH_OFFSET, 0xa5a5a5a5);
-  EXPECT_EQ(rom_ext_get_image_len(params_), 0xa5a5a5a5);
+
+  rom_ext_ranges_t expected = {
+      .image_start = kRomExtManifestSlotA,
+      .signed_area_start =
+          kRomExtManifestSlotA + ROM_EXT_SIGNED_AREA_START_OFFSET,
+      .image_end = kRomExtManifestSlotA + 0xa5a5a5a5,
+  };
+
+  EXPECT_THAT(rom_ext_get_ranges(params_), EqualsRanges(expected));
 }
 
 class ImageVersionGetTest : public ParserTest {};