[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')