[sw/silicon_creator] Introduce romextimage module
Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/silicon_creator/lib/error.h b/sw/device/silicon_creator/lib/error.h
index 90750d6..4c5ec89 100644
--- a/sw/device/silicon_creator/lib/error.h
+++ b/sw/device/silicon_creator/lib/error.h
@@ -21,12 +21,13 @@
*/
enum module_ {
kModuleUnknown = 0,
- kModuleUart = 0x4155, // ASCII "UA".
- kModuleHmac = 0x4d48, // ASCII "HM".
- kModuleSigverify = 0x5653, // ASCII "SV".
- kModuleOtp = 0x504f, // ASCII "OP".
- kModuleKeymgr = 0x4d4b, // ASCII "KM".
- kModuleManifest = 0x414d, // ASCII "MA".
+ kModuleUart = 0x4155, // ASCII "UA".
+ kModuleHmac = 0x4d48, // ASCII "HM".
+ kModuleSigverify = 0x5653, // ASCII "SV".
+ kModuleOtp = 0x504f, // ASCII "OP".
+ kModuleKeymgr = 0x4d4b, // ASCII "KM".
+ kModuleManifest = 0x414d, // ASCII "MA".
+ kModuleRomextimage = 0x4552, // ASCII "RE".
};
/**
@@ -46,14 +47,16 @@
// after the ROM is frozen.
#define DEFINE_ERRORS(X) \
X(kErrorOk, 0x739), \
- X(kErrorUartInvalidArgument, ERROR_(1, kModuleUart, kInvalidArgument)), \
- X(kErrorUartBadBaudRate, ERROR_(2, kModuleUart, kInvalidArgument)), \
- X(kErrorHmacInvalidArgument, ERROR_(1, kModuleHmac, kInvalidArgument)), \
- X(kErrorSigverifyInvalidArgument, ERROR_(1, kModuleSigverify, kInvalidArgument)), \
- X(kErrorOtpBusy, ERROR_(1, kModuleOtp, kUnavailable)), \
- X(kErrorOtpUnknown, ERROR_(2, kModuleOtp, kUnknown)), \
- X(kErrorKeymgrInternal, ERROR_(1, kModuleKeymgr, kInternal)), \
- X(kErrorManifestInternal, ERROR_(1, kModuleManifest, kInternal)), \
+ X(kErrorUartInvalidArgument, ERROR_(1, kModuleUart, kInvalidArgument)), \
+ X(kErrorUartBadBaudRate, ERROR_(2, kModuleUart, kInvalidArgument)), \
+ X(kErrorHmacInvalidArgument, ERROR_(1, kModuleHmac, kInvalidArgument)), \
+ X(kErrorSigverifyInvalidArgument, ERROR_(1, kModuleSigverify, kInvalidArgument)), \
+ X(kErrorOtpBusy, ERROR_(1, kModuleOtp, kUnavailable)), \
+ X(kErrorOtpUnknown, ERROR_(2, kModuleOtp, kUnknown)), \
+ X(kErrorKeymgrInternal, ERROR_(1, kModuleKeymgr, kInternal)), \
+ X(kErrorManifestInternal, ERROR_(1, kModuleManifest, kInternal)), \
+ X(kErrorRomextimageInvalidArgument, ERROR_(1, kModuleRomextimage, kInvalidArgument)), \
+ X(kErrorRomextimageInternal, ERROR_(2, kModuleRomextimage, kInternal)), \
X(kErrorUnknown, 0xFFFFFFFF)
// clang-format on
diff --git a/sw/device/silicon_creator/mask_rom/mask_rom.c b/sw/device/silicon_creator/mask_rom/mask_rom.c
index 4a77c7b..0b76c46 100644
--- a/sw/device/silicon_creator/mask_rom/mask_rom.c
+++ b/sw/device/silicon_creator/mask_rom/mask_rom.c
@@ -16,13 +16,11 @@
#include "sw/device/lib/runtime/print.h"
#include "sw/device/silicon_creator/lib/drivers/keymgr.h"
#include "sw/device/silicon_creator/lib/drivers/uart.h"
+#include "sw/device/silicon_creator/mask_rom/romextimage.h"
#include "sw/device/silicon_creator/mask_rom/sig_verify.h"
-#include "sw/device/silicon_creator/rom_exts/rom_ext_manifest_parser.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
-typedef void(boot_fn)(void);
-
void mask_rom_exception_handler(void) { wait_for_interrupt(); }
void mask_rom_nmi_handler(void) { wait_for_interrupt(); }
@@ -91,25 +89,17 @@
// break
//}
- // TODO: Range checks for manifest fields used before signature
- // verification.
- rom_ext_manifest_t rom_ext = rom_ext_get_parameters(kRomExtManifestSlotA);
- rom_ext_signature_key_modulus_t key_modulus;
- if (!rom_ext_get_signature_key_modulus(rom_ext, &key_modulus)) {
+ const manifest_t *manifest;
+ manifest_signed_region_t signed_region;
+ if (romextimage_manifest_get(kFlashSlotA, &manifest) != kErrorOk) {
break;
}
- rom_ext_signature_t rom_ext_signature;
- if (!rom_ext_get_signature(rom_ext, &rom_ext_signature)) {
+ if (manifest_signed_region_get(manifest, &signed_region) != kErrorOk) {
break;
}
- sigverify_rsa_buffer_t signature;
- memcpy(signature.data, rom_ext_signature.data, sizeof(signature.data));
- rom_ext_ranges_t ranges = rom_ext_get_ranges(rom_ext);
-
if (sigverify_rom_ext_signature_verify(
- (void *)ranges.signed_area_start,
- ranges.image_end - ranges.signed_area_start, &signature,
- key_modulus.data[0]) != kErrorOk) {
+ signed_region.start, signed_region.length, &manifest->signature,
+ manifest->modulus.data[0]) != kErrorOk) {
break;
}
@@ -171,14 +161,11 @@
// if (!final_jump_to_rom_ext(current_rom_ext_manifest)) { // Hardened Jump
// Module
if (true) {
- // Set mtvec for ROM_EXT.
- uintptr_t interrupt_vector = rom_ext_get_interrupt_vector(rom_ext);
- CSR_WRITE(CSR_REG_MTVEC, (uint32_t)interrupt_vector);
-
// Jump to ROM_EXT entry point.
- boot_fn *rom_ext_entry = (boot_fn *)rom_ext_get_entry(rom_ext);
- base_printf("rom_ext_entry: %p\r\n", rom_ext_entry);
- rom_ext_entry();
+ romextimage_entry_point *entry_point =
+ (romextimage_entry_point *)manifest_entry_point_address_get(manifest);
+ base_printf("rom_ext_entry: %p\r\n", entry_point);
+ entry_point();
// NOTE: never expecting a return, but if something were to go wrong
// in the real `jump` implementation, we need to enter a failure case.
diff --git a/sw/device/silicon_creator/mask_rom/meson.build b/sw/device/silicon_creator/mask_rom/meson.build
index f6039c2..fd267fe 100644
--- a/sw/device/silicon_creator/mask_rom/meson.build
+++ b/sw/device/silicon_creator/mask_rom/meson.build
@@ -28,6 +28,16 @@
),
)
+# ROM_EXT image.
+sw_silicon_creator_mask_rom_romextimage = declare_dependency(
+ link_with: static_library(
+ 'sw_silicon_creator_mask_rom_romextimage',
+ sources: [
+ 'romextimage.c',
+ ],
+ ),
+)
+
# MaskROM library.
mask_rom_lib = declare_dependency(
sources: [
@@ -46,6 +56,7 @@
sw_silicon_creator_lib_manifest,
sw_silicon_creator_mask_rom_sigverify,
rom_ext_manifest_parser,
+ sw_silicon_creator_mask_rom_romextimage,
sw_lib_crt,
sw_lib_pinmux,
sw_lib_runtime_print,
@@ -157,3 +168,19 @@
),
suite: 'mask_rom',
)
+
+test('sw_silicon_creator_mask_rom_romextimage_unittest', executable(
+ 'sw_silicon_creator_mask_rom_romextimage_unittest',
+ sources: [
+ 'romextimage_unittest.cc',
+ 'romextimage.c',
+ ],
+ dependencies: [
+ sw_vendor_gtest,
+ ],
+ native: true,
+ c_args: ['-DOT_OFF_TARGET_TEST'],
+ cpp_args: ['-DOT_OFF_TARGET_TEST'],
+ ),
+ suite: 'mask_rom',
+)
diff --git a/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h b/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h
new file mode 100644
index 0000000..0616427
--- /dev/null
+++ b/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h
@@ -0,0 +1,43 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_MOCK_ROMEXTIMAGE_PTRS_H_
+#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_MOCK_ROMEXTIMAGE_PTRS_H_
+
+#include "sw/device/lib/testing/mask_rom_test.h"
+#include "sw/device/silicon_creator/mask_rom/romextimage_ptrs.h"
+
+namespace mask_rom_test {
+namespace internal {
+
+/**
+ * Mock class for romextimage_ptrs.h
+ */
+class MockRomextimagePtrs {
+ public:
+ MOCK_METHOD(const manifest_t *, slot_a_manifest_ptr_get, ());
+ MOCK_METHOD(const manifest_t *, slot_b_manifest_ptr_get, ());
+
+ virtual ~MockRomextimagePtrs() {}
+};
+
+} // namespace internal
+
+using MockRomextimagePtrs =
+ GlobalMock<testing::StrictMock<internal::MockRomextimagePtrs>>;
+
+extern "C" {
+
+const manifest_t *romextimage_slot_a_manifest_ptr_get() {
+ return MockRomextimagePtrs::Instance().slot_a_manifest_ptr_get();
+}
+
+const manifest_t *romextimage_slot_b_manifest_ptr_get() {
+ return MockRomextimagePtrs::Instance().slot_b_manifest_ptr_get();
+}
+
+} // extern "C"
+} // namespace mask_rom_test
+
+#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_MOCK_ROMEXTIMAGE_PTRS_H_
diff --git a/sw/device/silicon_creator/mask_rom/romextimage.c b/sw/device/silicon_creator/mask_rom/romextimage.c
new file mode 100644
index 0000000..5ab9a63
--- /dev/null
+++ b/sw/device/silicon_creator/mask_rom/romextimage.c
@@ -0,0 +1,31 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/silicon_creator/mask_rom/romextimage.h"
+
+#include "sw/device/silicon_creator/lib/error.h"
+#include "sw/device/silicon_creator/mask_rom/romextimage_ptrs.h"
+
+rom_error_t romextimage_manifest_get(flash_slot_t slot,
+ const manifest_t **manifest) {
+ const manifest_t *ptr;
+ switch (slot) {
+ case kFlashSlotA:
+ ptr = romextimage_slot_a_manifest_ptr_get();
+ break;
+ case kFlashSlotB:
+ ptr = romextimage_slot_b_manifest_ptr_get();
+ break;
+ default:
+ return kErrorRomextimageInvalidArgument;
+ }
+ if (ptr->identifier != kRomextimageManifestIdentifier) {
+ return kErrorRomextimageInternal;
+ }
+ *manifest = ptr;
+ return kErrorOk;
+}
+
+extern const manifest_t *romextimage_slot_a_manifest_ptr_get(void);
+extern const manifest_t *romextimage_slot_b_manifest_ptr_get(void);
diff --git a/sw/device/silicon_creator/mask_rom/romextimage.h b/sw/device/silicon_creator/mask_rom/romextimage.h
new file mode 100644
index 0000000..b5f0578
--- /dev/null
+++ b/sw/device/silicon_creator/mask_rom/romextimage.h
@@ -0,0 +1,47 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_H_
+#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_H_
+
+#include "sw/device/silicon_creator/lib/error.h"
+#include "sw/device/silicon_creator/lib/manifest.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Type alias for the ROM_EXT entry point.
+ *
+ * The entry point address obtained from the ROM_EXT manifest must be cast to a
+ * pointer to this type before being called.
+ */
+typedef void romextimage_entry_point(void);
+
+enum {
+ /**
+ * ROM_EXT manifest identifier (ASCII "OTRE").
+ */
+ kRomextimageManifestIdentifier = 0x4552544f,
+};
+
+/**
+ * Gets the manifest of the ROM_EXT image in the given slot.
+ *
+ * This function also checks that the manifest's identifier field has the
+ * expected value.
+ *
+ * @param slot A flash slot.
+ * @param[out] The manifest of the ROM_EXT image in the given slot.
+ * @return The result of the operation.
+ */
+rom_error_t romextimage_manifest_get(flash_slot_t slot,
+ const manifest_t **manifest);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_H_
diff --git a/sw/device/silicon_creator/mask_rom/romextimage_ptrs.h b/sw/device/silicon_creator/mask_rom/romextimage_ptrs.h
new file mode 100644
index 0000000..7360ed6
--- /dev/null
+++ b/sw/device/silicon_creator/mask_rom/romextimage_ptrs.h
@@ -0,0 +1,52 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_PTRS_H_
+#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_PTRS_H_
+
+#include "sw/device/silicon_creator/lib/manifest.h"
+
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+static_assert((TOP_EARLGREY_EFLASH_SIZE_BYTES % 2) == 0,
+ "Flash size is not divisible by 2");
+
+#ifndef OT_OFF_TARGET_TEST
+/**
+ * Returns a pointer to the manifest of the ROM_EXT image stored in flash
+ * slot A.
+ *
+ * @return Pointer to the manifest of the ROM_EXT image in slot A.
+ */
+inline const manifest_t *romextimage_slot_a_manifest_ptr_get(void) {
+ return (const manifest_t *)TOP_EARLGREY_EFLASH_BASE_ADDR;
+}
+
+/**
+ * Returns a pointer to the manifest of the ROM_EXT image stored in flash
+ * slot B.
+ *
+ * @return Pointer to the manifest of the ROM_EXT image in slot B.
+ */
+inline const manifest_t *romextimage_slot_b_manifest_ptr_get(void) {
+ return (const manifest_t *)(TOP_EARLGREY_EFLASH_BASE_ADDR +
+ (TOP_EARLGREY_EFLASH_SIZE_BYTES / 2));
+}
+#else
+/**
+ * Declarations for the functions above that should be defined in tests.
+ */
+const manifest_t *romextimage_slot_a_manifest_ptr_get(void);
+const manifest_t *romextimage_slot_b_manifest_ptr_get(void);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_MASK_ROM_ROMEXTIMAGE_PTRS_H_
diff --git a/sw/device/silicon_creator/mask_rom/romextimage_unittest.cc b/sw/device/silicon_creator/mask_rom/romextimage_unittest.cc
new file mode 100644
index 0000000..82c41b7
--- /dev/null
+++ b/sw/device/silicon_creator/mask_rom/romextimage_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/silicon_creator/mask_rom/romextimage.h"
+
+#include "gtest/gtest.h"
+#include "sw/device/lib/testing/mask_rom_test.h"
+#include "sw/device/silicon_creator/lib/error.h"
+#include "sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h"
+
+namespace manifest_unittest {
+namespace {
+using ::testing::Return;
+
+class RomExtImage : public mask_rom_test::MaskRomTest {
+ protected:
+ mask_rom_test::MockRomextimagePtrs romextimage_ptrs_;
+ manifest_t manifest_;
+};
+
+TEST_F(RomExtImage, ManifestGet) {
+ const manifest_t *act_manifest;
+ manifest_.identifier = kRomextimageManifestIdentifier;
+
+ EXPECT_CALL(romextimage_ptrs_, slot_a_manifest_ptr_get)
+ .WillOnce(Return(&manifest_));
+ EXPECT_EQ(romextimage_manifest_get(kFlashSlotA, &act_manifest), kErrorOk);
+ EXPECT_EQ(act_manifest, &manifest_);
+
+ act_manifest = nullptr;
+ EXPECT_CALL(romextimage_ptrs_, slot_b_manifest_ptr_get)
+ .WillOnce(Return(&manifest_));
+ EXPECT_EQ(romextimage_manifest_get(kFlashSlotB, &act_manifest), kErrorOk);
+ EXPECT_EQ(act_manifest, &manifest_);
+}
+
+TEST_F(RomExtImage, ManifestGetBadIdentifier) {
+ const manifest_t *act_manifest;
+
+ EXPECT_CALL(romextimage_ptrs_, slot_a_manifest_ptr_get)
+ .WillOnce(Return(&manifest_));
+ EXPECT_EQ(romextimage_manifest_get(kFlashSlotA, &act_manifest),
+ kErrorRomextimageInternal);
+
+ EXPECT_CALL(romextimage_ptrs_, slot_b_manifest_ptr_get)
+ .WillOnce(Return(&manifest_));
+ EXPECT_EQ(romextimage_manifest_get(kFlashSlotB, &act_manifest),
+ kErrorRomextimageInternal);
+}
+
+TEST_F(RomExtImage, ManifestGetBadSlot) {
+ const manifest_t *act_manifest;
+
+ EXPECT_EQ(romextimage_manifest_get(static_cast<flash_slot_t>(kFlashSlotB + 1),
+ &act_manifest),
+ kErrorRomextimageInvalidArgument);
+}
+
+} // namespace
+} // namespace manifest_unittest