[ottf] enable OTTF to be loaded in any slot at silicon_creator stage
This refactors the OTTF linker scripts to enable the OTTF to be loaded
in any slot (A, B, and virtual) at the silicon_creator (ROM_EXT) boot
stage.
Additionally this makes the "manifest" field of the
`opentitan_flash_binary` macro mandatory when the `signed` field is set
to `True`, and fixes existing signed tests that did not provide a
manifest.
This partially addresses #10712.
Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/rules/opentitan.bzl b/rules/opentitan.bzl
index eef2e03..b2cd1be 100644
--- a/rules/opentitan.bzl
+++ b/rules/opentitan.bzl
@@ -748,6 +748,7 @@
@param platform: The target platform for the artifacts.
@param signing_keys: The signing keys for to sign each BIN file with.
@param signed: Whether or not to emit signed binary/VMEM files.
+ @param manifest: Partially populated manifest to set boot stage/slot configs.
@param **kwargs: Arguments to forward to `opentitan_binary`.
Emits rules:
For each device in per_device_deps entry:
@@ -790,6 +791,8 @@
# Sign BIN (if required) and generate scrambled VMEM images.
if signed:
+ if manifest == None:
+ fail("A 'manifest' must be provided in order to sign flash images.")
for (key_name, key) in signing_keys.items():
# Sign the Binary.
signed_bin_name = "{}_bin_signed_{}".format(devname, key_name)
diff --git a/sw/device/examples/hello_usbdev/BUILD b/sw/device/examples/hello_usbdev/BUILD
index 4219613..558f636 100644
--- a/sw/device/examples/hello_usbdev/BUILD
+++ b/sw/device/examples/hello_usbdev/BUILD
@@ -41,7 +41,7 @@
"//sw/device/lib/testing:usb_testutils",
"//sw/device/lib/testing:usb_testutils_simpleserial",
"//sw/device/lib/testing/test_framework:check",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
"//sw/device/lib/testing/test_framework:ottf_test_config",
],
)
diff --git a/sw/device/examples/hello_world/BUILD b/sw/device/examples/hello_world/BUILD
index 677eac0..c1c81ec 100644
--- a/sw/device/examples/hello_world/BUILD
+++ b/sw/device/examples/hello_world/BUILD
@@ -41,7 +41,7 @@
"//sw/device/lib/runtime:print",
"//sw/device/lib/testing:pinmux_testutils",
"//sw/device/lib/testing/test_framework:check",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
"//sw/device/lib/testing/test_framework:ottf_test_config",
],
)
diff --git a/sw/device/lib/testing/test_framework/BUILD b/sw/device/lib/testing/test_framework/BUILD
index edb10ed..6ec57c4 100644
--- a/sw/device/lib/testing/test_framework/BUILD
+++ b/sw/device/lib/testing/test_framework/BUILD
@@ -56,51 +56,41 @@
)
ld_library(
- name = "linker_script",
- script = "ottf.ld",
+ name = "ottf_ld_common",
+ fragments = ["ottf_common.ld"],
+ deps = ["//sw/device:info_sections"],
+)
+
+ld_library(
+ name = "ottf_ld_silicon_creator_slot_a",
+ script = "ottf_silicon_creator_a.ld",
deps = [
+ ":ottf_ld_common",
"//hw/top_earlgrey/sw/autogen:top_earlgrey_memory",
- "//sw/device:info_sections",
],
)
-# This target provides start files without providing the full OTTF, and can be used
-# to bootstrap post-ROM execution without pulling in the full OTTF.
-#
-# The binary target must provide a `noreturn void _ottf_main(void)` function that
-# this library will call.
-cc_library(
- name = "ottf_start",
- srcs = [
- "ottf_isrs.S",
- "ottf_isrs.c",
- "ottf_start.S",
- ],
- hdrs = [
- "ottf_isrs.h",
- "ottf_macros.h",
- ],
- target_compatible_with = [OPENTITAN_CPU],
+ld_library(
+ name = "ottf_ld_silicon_creator_slot_b",
+ script = "ottf_silicon_creator_b.ld",
deps = [
- ":linker_script",
- "//sw/device/lib/base:csr",
- "//sw/device/lib/base:macros",
- "//sw/device/lib/crt",
- "//sw/device/lib/runtime:hart",
- "//sw/device/lib/runtime:log",
- "//sw/device/silicon_creator/lib:manifest_size",
+ ":ottf_ld_common",
+ "//hw/top_earlgrey/sw/autogen:top_earlgrey_memory",
],
)
-cc_library(
- name = "ottf_test_config",
- hdrs = [
- "ottf_test_config.h",
+ld_library(
+ name = "ottf_ld_silicon_creator_slot_virtual",
+ script = "ottf_silicon_creator_virtual.ld",
+ deps = [
+ ":ottf_ld_common",
+ "//hw/top_earlgrey/sw/autogen:top_earlgrey_memory",
],
)
-# TODO(#12905): Use a slightly hollowed out version of the silicon_creator manifest_def
-# implementation when building the test_framework for the english breakfast top level.
+# TODO(#12905): Use a slightly hollowed out version of the silicon_creator
+# manifest_def implementation when building the test_framework for the english
+# breakfast top level.
cc_library(
name = "english_breakfast_test_framework_manifest_def",
srcs = [
@@ -124,6 +114,71 @@
}),
)
+# This target provides start files without providing the full OTTF, and can be
+# used to bootstrap post-ROM execution without pulling in the full OTTF. This is
+# useful for programs in `sw/device/examples/` and `sw/device/sca/` that do not
+# make us of the full OTTF.
+#
+# The binary target must provide a `noreturn void _ottf_main(void)` function
+# that this library will call.
+cc_library(
+ name = "ottf_start",
+ srcs = [
+ "ottf_isrs.S",
+ "ottf_isrs.c",
+ "ottf_start.S",
+ ],
+ hdrs = [
+ "ottf_isrs.h",
+ "ottf_macros.h",
+ ],
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ "//sw/device/lib/base:csr",
+ "//sw/device/lib/base:macros",
+ "//sw/device/lib/crt",
+ "//sw/device/lib/runtime:hart",
+ "//sw/device/lib/runtime:log",
+ ],
+)
+
+cc_library(
+ name = "ottf_start_silicon_creator_slot_a",
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ ":ottf_ld_silicon_creator_slot_a",
+ ":ottf_start",
+ ":test_framework_manifest_def",
+ ],
+)
+
+cc_library(
+ name = "ottf_start_silicon_creator_slot_b",
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ ":ottf_ld_silicon_creator_slot_b",
+ ":ottf_start",
+ ":test_framework_manifest_def",
+ ],
+)
+
+cc_library(
+ name = "ottf_start_silicon_creator_slot_virtual",
+ target_compatible_with = [OPENTITAN_CPU],
+ deps = [
+ ":ottf_ld_silicon_creator_slot_virtual",
+ ":ottf_start",
+ ":test_framework_manifest_def",
+ ],
+)
+
+cc_library(
+ name = "ottf_test_config",
+ hdrs = [
+ "ottf_test_config.h",
+ ],
+)
+
cc_library(
name = "ottf_main",
srcs = ["ottf_main.c"],
@@ -133,10 +188,9 @@
":check",
":coverage",
":freertos_port",
- ":ottf_start",
+ ":ottf_start_silicon_creator_slot_a",
":ottf_test_config",
":status",
- ":test_framework_manifest_def",
"//sw/device/lib/arch:device",
"//sw/device/lib/base:macros",
"//sw/device/lib/dif:uart",
@@ -146,9 +200,9 @@
"//third_party/freertos",
"@manufacturer_test_hooks//:test_hooks",
],
- # `:ottf` depends on `:ottf_start`, but `:ottf_start` gets its main function from
- # `:ottf`. Thus we need to include all of the objects in `:ottf` unconditionally
- # so that the linker can find the symbol later.
+ # `:ottf` depends on `:ottf_start`, but `:ottf_start` gets its main function
+ # from `:ottf`. Thus we need to include all of the objects in `:ottf`
+ # unconditionally so that the linker can find the symbol later.
alwayslink = True,
)
diff --git a/sw/device/lib/testing/test_framework/ottf.ld b/sw/device/lib/testing/test_framework/ottf_common.ld
similarity index 69%
rename from sw/device/lib/testing/test_framework/ottf.ld
rename to sw/device/lib/testing/test_framework/ottf_common.ld
index 4609e80..a2a8a8f 100644
--- a/sw/device/lib/testing/test_framework/ottf.ld
+++ b/sw/device/lib/testing/test_framework/ottf_common.ld
@@ -3,43 +3,12 @@
/* SPDX-License-Identifier: Apache-2.0 */
/**
- * Linker script for OpenTitan OTTF-launched test binaries.
- *
- * Portions of this file are Ibex-specific.
+ * NOTE:
+ * This is an incomplete common portion of OTTF linker file, and should not
+ * be used directly. Instead it should be included by a top level OTTF slot
+ * linker file.
*/
-INCLUDE hw/top_earlgrey/sw/autogen/top_earlgrey_memory.ld
-
-/**
- * Reserving space at the top of the RAM for the stack.
- */
-_stack_size = 0x2000;
-_stack_end = ORIGIN(ram_main) + LENGTH(ram_main);
-_stack_start = _stack_end - _stack_size;
-
-/**
- * DV Log offset.
- * TODO: this will need to be different depending on the boot stage the OTTF is
- * launched at. See lowrisc/opentitan:#10712.
- */
-_dv_log_offset = 0x10000;
-
-/*
- * The start of the .text section relative to the beginning of the associated
- * slot for use in the manifest.
- */
-_manifest_code_start = _text_start - ORIGIN(eflash);
-/*
- * The end of the .text section relative to the beginning of the associated slot
- * for use in the manifest.
- */
-_manifest_code_end = _text_end - ORIGIN(eflash);
-/*
- * The location of the entry point relative to the beginning of the associated
- * slot for use in the manifest.
- */
-_manifest_entry_point = _ottf_start - ORIGIN(eflash);
-
OUTPUT_ARCH(riscv)
/**
@@ -48,6 +17,13 @@
__DYNAMIC = 0;
/**
+ * Reserving space at the top of the RAM for the stack.
+ */
+_stack_size = 0x2000;
+_stack_end = ORIGIN(ram_main) + LENGTH(ram_main);
+_stack_start = _stack_end - _stack_size;
+
+/**
* Marking the entry point correctly for the ELF file. The signer tool will
* transfer this value to the `entry_point` field of the manifest, which will
* then be used by `mask_rom_boot` or `rom_ext_boot` to handover execution to
@@ -56,13 +32,38 @@
ENTRY(_ottf_start);
/**
+ * DV Log offset.
+ * TODO: this will need to be different depending on the boot stage the OTTF is
+ * launched at. See lowrisc/opentitan:#10712.
+ */
+_dv_log_offset = 0x10000;
+
+/**
+ * The start of the .text section relative to the beginning of the associated
+ * slot for use in the manifest.
+ */
+_manifest_code_start = _text_start - _ottf_start_address;
+
+/**
+ * The end of the .text section relative to the beginning of the associated slot
+ * for use in the manifest.
+ */
+_manifest_code_end = _text_end - _ottf_start_address;
+
+/**
+ * The location of the entry point relative to the beginning of the associated
+ * slot for use in the manifest.
+ */
+_manifest_entry_point = _ottf_start - _ottf_start_address;
+
+/**
* NOTE: We have to align each section to word boundaries as our current
* s19->slm conversion scripts are not able to handle non-word aligned sections.
*/
SECTIONS {
- .manifest ORIGIN(eflash) : {
+ .manifest _ottf_start_address : {
KEEP(*(.manifest))
- } > eflash
+ } > ottf_flash
/**
* Non-volatile Scratch area in flash.
@@ -73,7 +74,7 @@
.non_volatile_scratch : ALIGN(2048){
_non_volatile_scratch_start = .;
KEEP(*(.non_volatile_scratch))
- } > eflash
+ } > ottf_flash
/**
* Ibex interrupt vector. See 'ottf_start.S' for more information.
@@ -84,14 +85,14 @@
.vectors : ALIGN (256){
_text_start = .;
*(.vectors)
- } > eflash
+ } > ottf_flash
/**
* C runtime (CRT) section, containing program initialization code.
*/
.crt : ALIGN(4) {
KEEP(*(.crt))
- } > eflash
+ } > ottf_flash
/**
* For LLVM profiling. This contains a pointer to the runtime initialization
@@ -105,7 +106,7 @@
*(.init_array.*)
. = ALIGN(4);
_init_array_end = .;
- } > eflash
+ } > ottf_flash
/**
* Standard text section, containing program code.
@@ -114,24 +115,33 @@
*(.text)
*(.text.*)
- /**
- * Some tests place functions into the .shutdown section.
- */
+ /* Ensure section end is word-aligned. */
+ . = ALIGN(4);
+ } > ottf_flash
+
+ /**
+ * Shutdown text section, containing shutdown function(s).
+ *
+ * This must be the last executable section in the OTTF flash image.
+ */
+ .shutdown : ALIGN(4) {
*(.shutdown)
*(.shutdown.*)
/* Ensure section end is word-aligned. */
. = ALIGN(4);
_text_end = .;
- } > eflash
+ } > ottf_flash
/**
* Read-only data section, containing all large compile-time constants, like
* strings.
*/
.rodata : ALIGN(4) {
- /* Small read-only data comes before regular read-only data for the same
- * reasons as in the data section. */
+ /**
+ * Small read-only data comes before regular read-only data for the same
+ * reasons as in the data section.
+ */
*(.srodata)
*(.srodata.*)
*(.rodata)
@@ -141,34 +151,38 @@
KEEP(*(__llvm_covfun))
KEEP(*(__llvm_covmap))
KEEP(*(__llvm_prf_names))
- } > eflash
-
- /**
- * "Intitial data" section, the initial values of the mutable data section
- * initialized at runtime.
- */
- .idata : ALIGN(4) {
- _data_init_start = .;
- } > eflash
+ } > ottf_flash
/**
* Standard mutable data section, at the bottom of RAM. This will be
* initialized from the .idata section at runtime by the CRT.
*/
- .data ORIGIN(ram_main): AT(_data_init_start) ALIGN(4) {
+ .data : ALIGN(4) {
_data_start = .;
+ _data_init_start = LOADADDR(.data);
+
+ /**
+ * This will get loaded into `gp`, and the linker will use that register for
+ * accessing data within [-2048,2047] of `__global_pointer$`.
+ *
+ * This is much cheaper (for small data) than materializing the
+ * address and loading from that (which will take one extra instruction).
+ */
__global_pointer$ = . + 2048;
/* SRAM programs embedded in functional tests must come first. */
*(.data.sram_program)
- /* Small data should come before larger data. This helps to ensure small
+ /**
+ * Small data should come before larger data. This helps to ensure small
* globals are within 2048 bytes of the value of `gp`, making their accesses
- * hopefully only take one instruction. */
+ * hopefully only take one instruction.
+ */
*(.sdata)
*(.sdata.*)
- /* Other data will likely need multiple instructions to load, so we're less
+ /**
+ * Other data will likely need multiple instructions to load, so we're less
* concerned about address materialisation taking more than one instruction.
*/
*(.data)
@@ -181,7 +195,17 @@
/* Ensure section end is word-aligned. */
. = ALIGN(4);
_data_end = .;
- } > ram_main
+ _data_init_end = LOADADDR(.data) + SIZEOF(.data);
+
+ /**
+ * This puts it in ram_main at runtime (for the VMA), but puts the section
+ * into flash for load time (for the LMA). This is why `_data_init_*` uses
+ * `LOADADDR`.
+ *
+ * Using `AT>` means we don't have to keep track of the next free part of
+ * flash, as we do in our other linker scripts.
+ */
+ } > ram_main AT> ottf_flash
/**
* Standard BSS section. This will be zeroed at runtime by the CRT.
@@ -189,8 +213,10 @@
.bss : ALIGN(4) {
_bss_start = .;
- /* Small BSS comes before regular BSS for the same reasons as in the data
- * section. */
+ /**
+ * Small BSS comes before regular BSS for the same reasons as in the data
+ * section.
+ */
*(.sbss)
*(.sbss.*)
*(.bss)
diff --git a/sw/device/lib/testing/test_framework/ottf_silicon_creator_a.ld b/sw/device/lib/testing/test_framework/ottf_silicon_creator_a.ld
new file mode 100644
index 0000000..604c01e
--- /dev/null
+++ b/sw/device/lib/testing/test_framework/ottf_silicon_creator_a.ld
@@ -0,0 +1,24 @@
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/**
+ * Linker script for OpenTitan OTTF-launched test binaries.
+ *
+ * Portions of this file are Ibex-specific.
+ *
+ * This linker script generates a binary to run mask_rom.
+ */
+
+INCLUDE hw/top_earlgrey/sw/autogen/top_earlgrey_memory.ld
+
+/**
+ * Symbols to be used in the setup of the address translation for the OTTF run
+ * at the Silicon Creator boot stage in slot A.
+ */
+_ottf_size = LENGTH(eflash) / 2;
+_ottf_start_address = ORIGIN(eflash);
+
+REGION_ALIAS("ottf_flash", eflash);
+
+INCLUDE sw/device/lib/testing/test_framework/ottf_common.ld
diff --git a/sw/device/lib/testing/test_framework/ottf_silicon_creator_b.ld b/sw/device/lib/testing/test_framework/ottf_silicon_creator_b.ld
new file mode 100644
index 0000000..dca2f66
--- /dev/null
+++ b/sw/device/lib/testing/test_framework/ottf_silicon_creator_b.ld
@@ -0,0 +1,24 @@
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/**
+ * Linker script for OpenTitan OTTF-launched test binaries.
+ *
+ * Portions of this file are Ibex-specific.
+ *
+ * This linker script generates a binary to run mask_rom.
+ */
+
+INCLUDE hw/top_earlgrey/sw/autogen/top_earlgrey_memory.ld
+
+/**
+ * Symbols to be used in the setup of the address translation for the OTTF run
+ * at the Silicon Creator boot stage in slot B.
+ */
+_ottf_size = LENGTH(eflash) / 2;
+_ottf_start_address = ORIGIN(eflash) + _ottf_size;
+
+REGION_ALIAS("ottf_flash", eflash);
+
+INCLUDE sw/device/lib/testing/test_framework/ottf_common.ld
diff --git a/sw/device/lib/testing/test_framework/ottf_silicon_creator_virtual.ld b/sw/device/lib/testing/test_framework/ottf_silicon_creator_virtual.ld
new file mode 100644
index 0000000..074e3bf
--- /dev/null
+++ b/sw/device/lib/testing/test_framework/ottf_silicon_creator_virtual.ld
@@ -0,0 +1,24 @@
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/**
+ * Linker script for OpenTitan OTTF-launched test binaries.
+ *
+ * Portions of this file are Ibex-specific.
+ *
+ * This linker script generates a binary to run mask_rom.
+ */
+
+INCLUDE hw/top_earlgrey/sw/autogen/top_earlgrey_memory.ld
+
+/**
+ * Symbols to be used in the setup of the address translation for the OTTF run
+ * at the Silicon Creator boot stage in the virtual slot.
+ */
+_ottf_start_address = ORIGIN(rom_ext_virtual);
+_ottf_size = LENGTH(rom_ext_virtual);
+
+REGION_ALIAS("ottf_flash", rom_ext_virtual);
+
+INCLUDE sw/device/lib/testing/test_framework/ottf_common.ld
diff --git a/sw/device/sca/BUILD b/sw/device/sca/BUILD
index 9dc2755..c42afd2 100644
--- a/sw/device/sca/BUILD
+++ b/sw/device/sca/BUILD
@@ -14,7 +14,7 @@
"//sw/device/lib/base:memory",
"//sw/device/lib/dif:aes",
"//sw/device/lib/runtime:log",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
"//sw/device/lib/testing/test_framework:ottf_test_config",
"//sw/device/sca/lib:prng",
"//sw/device/sca/lib:sca",
@@ -30,7 +30,7 @@
"//sw/device/lib/base:memory",
"//sw/device/lib/dif:kmac",
"//sw/device/lib/runtime:log",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
"//sw/device/lib/testing/test_framework:ottf_test_config",
"//sw/device/sca/lib:prng",
"//sw/device/sca/lib:sca",
diff --git a/sw/device/sca/lib/BUILD b/sw/device/sca/lib/BUILD
index 7b92928..2a818b0 100644
--- a/sw/device/sca/lib/BUILD
+++ b/sw/device/sca/lib/BUILD
@@ -56,6 +56,6 @@
"//sw/device/lib/runtime:hart",
"//sw/device/lib/runtime:print",
"//sw/device/lib/testing:pinmux_testutils",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
],
)
diff --git a/sw/device/silicon_creator/mask_rom/e2e/BUILD b/sw/device/silicon_creator/mask_rom/e2e/BUILD
index 8b6573a..1c2b0a7 100644
--- a/sw/device/silicon_creator/mask_rom/e2e/BUILD
+++ b/sw/device/silicon_creator/mask_rom/e2e/BUILD
@@ -2,7 +2,6 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
-load("//rules:opentitan.bzl", "OPENTITAN_CPU", "opentitan_flash_binary")
load(
"//rules:opentitan_test.bzl",
"cw310_params",
@@ -93,6 +92,7 @@
],
bitstream = "//hw/bitstream:mask_rom",
),
+ manifest = "//sw/device/silicon_creator/rom_ext:manifest_standard",
signed = True,
targets = ["cw310"],
test_harness = "//sw/host/tests/mask_rom/e2e_bootup_bad_rom_ext_signature",
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index cba75fd..2118da9 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -478,7 +478,7 @@
"//sw/device/lib/runtime:log",
"//sw/device/lib/runtime:print",
"//sw/device/lib/testing/test_framework:check",
- "//sw/device/lib/testing/test_framework:ottf_start",
+ "//sw/device/lib/testing/test_framework:ottf_start_silicon_creator_slot_a",
"//sw/device/lib/testing/test_framework:ottf_test_config",
"//sw/device/lib/testing/test_framework:status",
"//sw/device/silicon_creator/lib:manifest_def",
@@ -1347,6 +1347,7 @@
opentitan_functest(
name = "uart_smoketest",
srcs = ["uart_smoketest.c"],
+ manifest = "//sw/device/silicon_creator/rom_ext:manifest_standard",
signed = True,
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",