[sw] Create a temporary location for a rewrite of boot_rom
The current boot_rom currently cannot provide many of the features the
OpenTitan mask ROM will eventually need. Rather than attempting to
refactor the current ROM and risk breaking everyone, we'll do a complete
rewrite (which isn't too bad, since the current boot_rom is tiny).
The code in the new location is everything necessary to get to a
hello-world at boot.
Signed-off-by: Miguel Young de la Sota <mcyoung@google.com>
diff --git a/sw/device/boot_rom2/README.md b/sw/device/boot_rom2/README.md
new file mode 100644
index 0000000..e8a57f5
--- /dev/null
+++ b/sw/device/boot_rom2/README.md
@@ -0,0 +1,3 @@
+# OpenTitan Boot ROM v2
+
+This subtree is a temporary location for a rewrite of the Boot ROM, which will eventually be moved to `sw/device/boot_rom` once it is able to replace the code currently there.
diff --git a/sw/device/boot_rom2/boot_rom.c b/sw/device/boot_rom2/boot_rom.c
new file mode 100644
index 0000000..d71cd11
--- /dev/null
+++ b/sw/device/boot_rom2/boot_rom.c
@@ -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`
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "sw/device/boot_rom2/uart_log.h"
+#include "sw/device/lib/base/log.h"
+
+// Non-DIF drivers. These should eventually be removed.
+#include "sw/device/lib/pinmux.h"
+
+/**
+ * First non-assembly function, called by the ROM CRT file.
+ *
+ * Returning from this function is equivalent to aborting.
+ */
+void _boot_start(void) {
+ pinmux_init();
+ uart_log_init();
+
+ LOG_INFO("Hello, world!");
+}
diff --git a/sw/device/boot_rom2/meson.build b/sw/device/boot_rom2/meson.build
new file mode 100644
index 0000000..33c6645
--- /dev/null
+++ b/sw/device/boot_rom2/meson.build
@@ -0,0 +1,66 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+# We re-use a bunch of variables from boot_rom/meson.build for now.
+# These are:
+# - chip_info_h
+# - rom_link_args
+# - rom_link_deps
+
+sw_br2_crt_files = [
+ '../boot_rom/rom_crt.S',
+ '../boot_rom/irq_vector.S',
+]
+
+sw_br2_log = declare_dependency(
+ link_with: static_library(
+ 'sw_br2_log',
+ sources: ['uart_log.c'],
+ dependencies: [
+ dif_uart,
+ sw_lib_mem,
+ sw_lib_base_print,
+ sw_lib_runtime_hart,
+ ],
+ ),
+)
+
+foreach device_name, device_lib : sw_lib_arch_core_devices
+ sw_br2_elf = executable(
+ 'br2_' + device_name,
+ sources: [
+ 'boot_rom.c',
+ sw_br2_crt_files,
+ ],
+ name_suffix: 'elf',
+ link_args: rom_link_args,
+ link_depends: rom_link_deps,
+ dependencies: [
+ chip_info_h,
+ device_lib,
+ sw_br2_log,
+ sw_lib_base_log,
+
+ # Non-DIF drivers. These should eventally be removed.
+ sw_lib_pinmux,
+ ],
+ )
+
+ sw_br2_embedded = custom_target(
+ 'br2_' + device_name,
+ command: make_embedded_target,
+ input: sw_br2_elf,
+ output: make_embedded_target_outputs,
+ build_by_default: true,
+ )
+
+ custom_target(
+ 'br2_export_' + device_name,
+ command: export_embedded_target,
+ input: [sw_br2_elf, sw_br2_embedded],
+ output: 'br2_export_' + device_name,
+ build_always_stale: true,
+ build_by_default: true,
+ )
+endforeach
diff --git a/sw/device/boot_rom2/uart_log.c b/sw/device/boot_rom2/uart_log.c
new file mode 100644
index 0000000..a453091
--- /dev/null
+++ b/sw/device/boot_rom2/uart_log.c
@@ -0,0 +1,62 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0`
+
+#include "sw/device/boot_rom2/uart_log.h"
+
+#include "sw/device/lib/arch/device.h"
+#include "sw/device/lib/base/print.h"
+#include "sw/device/lib/runtime/hart.h"
+
+/**
+ * Handle for the 0th UART port.
+ */
+static dif_uart_t uart0;
+
+dif_uart_t *uart_log_handle(void) { return &uart0; }
+
+/**
+ * Tries to write a buffer to the 0th UART. This function only exists to
+ * drive logging, and should otherwise not be called directly.
+ *
+ * This function is called by error-handling code, and as such a failure
+ * within it is treated asa double-fault.
+ *
+ * @param ignored a data pointer required by buf_sink_t, which is ignored.
+ * @param buf a buffer to write to UART.
+ * @param len the length of the buffer.
+ * @return the number of bytes written, that is, the value of len.
+ */
+static size_t uart0_send_buf(void *ignored, const char *buf, size_t len) {
+ size_t total_len = len;
+ while (len > 0) {
+ size_t bytes_written;
+ bool success =
+ dif_uart_bytes_send(&uart0, (const uint8_t *)buf, len, &bytes_written);
+ if (!success) {
+ // We have no way of logging this failure for now, since we're in the
+ // middle of the UART stdout... which is used for logging. Oops.
+ abort();
+ }
+
+ len -= bytes_written;
+ buf += bytes_written;
+ }
+ return total_len;
+}
+
+void uart_log_init(void) {
+ dif_uart_config_t config = {
+ .baudrate = kUartBaudrate,
+ .clk_freq_hz = kClockFreqHz,
+ .parity_enable = kDifUartDisable,
+ .parity = kDifUartParityEven,
+ };
+
+ mmio_region_t addr = mmio_region_from_addr(0x40000000);
+ dif_uart_init(addr, &config, &uart0);
+
+ base_set_stdout((buffer_sink_t){
+ .sink = &uart0_send_buf,
+ });
+}
diff --git a/sw/device/boot_rom2/uart_log.h b/sw/device/boot_rom2/uart_log.h
new file mode 100644
index 0000000..ea04a13
--- /dev/null
+++ b/sw/device/boot_rom2/uart_log.h
@@ -0,0 +1,34 @@
+// 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_BOOT_ROM2_UART_LOG_H_
+#define OPENTITAN_SW_DEVICE_BOOT_ROM2_UART_LOG_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "sw/device/lib/dif/dif_uart.h"
+
+/**
+ * UART logging setup, as well as macros built on top of those.
+ */
+
+/**
+ * Returns a handle to the 0th UART port, for performing low-level UART
+ * operations.
+ *
+ * Prefer to use the LOG_* macros, instead.
+ *
+ * @return a pointer to a UART handle.
+ */
+dif_uart_t *uart_log_handle(void);
+
+/**
+ * Initialize UART, including logging setup.
+ *
+ * Should only be called once.
+ */
+void uart_log_init(void);
+
+#endif // OPENTITAN_SW_DEVICE_BOOT_ROM2_UART_LOG_H_
diff --git a/sw/device/meson.build b/sw/device/meson.build
index 6db9389..9b472c0 100644
--- a/sw/device/meson.build
+++ b/sw/device/meson.build
@@ -31,6 +31,7 @@
]
subdir('boot_rom')
+subdir('boot_rom2')
subdir('examples')
subdir('tests')
subdir('benchmarks')