[bazel] Build mask_rom with bazel

1. Add a bazel rule to build otbn programs.
2. Add bazel rules for all silicon_creator sources.
3. Add bazel rules for all silicon_creator tests.

Signed-off-by: Chris Frantz <cfrantz@google.com>
diff --git a/util/opentitantool_test_runner.sh b/util/opentitantool_test_runner.sh
index 1003a4a..2db363a 100755
--- a/util/opentitantool_test_runner.sh
+++ b/util/opentitantool_test_runner.sh
@@ -8,5 +8,6 @@
 
 set -e
 
+readonly REPO_TOP="$TEST_SRCDIR/$TEST_WORKSPACE"
 readonly OPENTITANTOOL="sw/host/opentitantool/opentitantool"
 RUST_BACKTRACE=1 ${OPENTITANTOOL} "$@"
diff --git a/util/otbn_build.py b/util/otbn_build.py
index ef1b54b..63b000d 100755
--- a/util/otbn_build.py
+++ b/util/otbn_build.py
@@ -20,6 +20,7 @@
   OTBN_LD            path to otbn-ld, the OTBN linker
   RV32_TOOL_LD       path to RV32 ld
   RV32_TOOL_AS       path to RV32 as
+  RV32_TOOL_AR       path to RV32 ar
   RV32_TOOL_OBJCOPY  path to RV32 objcopy
 
   The RV32* environment variables are used by both this script and the OTBN
@@ -120,8 +121,15 @@
     run_cmd([rv32_tool_objcopy] + args)
 
 
+def call_rv32_ar(args: List[str]):
+    rv32_tool_ar = os.environ.get('RV32_TOOL_AR',
+                                  'riscv32-unknown-elf-ar')
+    run_cmd([rv32_tool_ar] + args)
+
+
 def main() -> int:
-    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser = argparse.ArgumentParser(description=__doc__,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
     parser.add_argument(
         '--out-dir',
         '-o',
@@ -129,6 +137,11 @@
         default=".",
         help="Output directory (default: %(default)s)")
     parser.add_argument(
+        '--archive',
+        '-a',
+        action='store_true',
+        help='Archive the rv32embed.o file into a library.')
+    parser.add_argument(
         '--verbose',
         '-v',
         action='store_true',
@@ -152,7 +165,7 @@
     log.basicConfig(level=log_level, format="%(message)s")
 
     out_dir = Path(args.out_dir)
-    out_dir.mkdir(exist_ok=True)
+    out_dir.mkdir(parents=True, exist_ok=True)
 
     src_files = [Path(f) for f in args.src_files]
     for src_file in src_files:
@@ -162,6 +175,7 @@
     obj_files = [out_dir / f.with_suffix('.o').name for f in src_files]
 
     app_name = args.app_name or str(src_files[0].stem)
+    archive = args.archive
 
     try:
         for src_file, obj_file in zip(src_files, obj_files):
@@ -205,6 +219,10 @@
             emb_file.seek(0x10)
             emb_file.write(b'\1\0')
 
+        if archive:
+            out_embedded_a = out_dir / (app_name + '.rv32embed.a')
+            call_rv32_ar(['rcs', out_embedded_a, out_embedded_obj])
+
     except subprocess.CalledProcessError as e:
         # Show a nicer error message if any of the called programs fail.
         log.fatal("Command {!r} returned non-zero exit code {}".format(