bootrom: include compiled dtb
authorWesley W. Terpstra <wesley@sifive.com>
Tue, 21 Mar 2017 23:06:49 +0000 (16:06 -0700)
committerWesley W. Terpstra <wesley@sifive.com>
Tue, 21 Mar 2017 23:08:22 +0000 (16:08 -0700)
riscv/sim.cc

index 49b0336f5182b9d5026a6cd53248930f0164f493..004ccaacd0c1c94e4b2ec89143d3df2811ca30b4 100644 (file)
@@ -10,6 +10,9 @@
 #include <cstdlib>
 #include <cassert>
 #include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
 
 volatile bool ctrlc_pressed = false;
 static void handle_signal(int sig)
@@ -150,6 +153,87 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
   return bus.store(addr, len, bytes);
 }
 
+static std::string dts_compile(const std::string& dts)
+{
+  // Convert the DTS to DTB
+  int dts_pipe[2];
+  pid_t dts_pid;
+
+  if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) {
+    std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  // Child process to output dts
+  if (dts_pid == 0) {
+    close(dts_pipe[0]);
+    int step, len = dts.length();
+    const char *buf = dts.c_str();
+    for (int done = 0; done < len; done += step) {
+      step = write(dts_pipe[1], buf+done, len-done);
+      if (step == -1) {
+        std::cerr << "Failed to write dts: " << strerror(errno) << std::endl;
+        exit(1);
+      }
+    }
+    close(dts_pipe[1]);
+    exit(0);
+  }
+
+  pid_t dtb_pid;
+  int dtb_pipe[2];
+  if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) {
+    std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  // Child process to output dtb
+  if (dtb_pid == 0) {
+    dup2(dts_pipe[0], 0);
+    dup2(dtb_pipe[1], 1);
+    close(dts_pipe[0]);
+    close(dts_pipe[1]);
+    close(dtb_pipe[0]);
+    close(dtb_pipe[1]);
+    execl(DTC, DTC, "-O", "dtb", 0);
+    std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  close(dts_pipe[1]);
+  close(dts_pipe[0]);
+  close(dtb_pipe[1]);
+
+  // Read-out dtb
+  std::stringstream dtb;
+
+  int got;
+  char buf[4096];
+  while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) {
+    dtb.write(buf, got);
+  }
+  if (got == -1) {
+    std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+  close(dtb_pipe[0]);
+
+  // Reap children
+  int status;
+  waitpid(dts_pid, &status, 0);
+  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+    std::cerr << "Child dts process failed" << std::endl;
+    exit(1);
+  }
+  waitpid(dtb_pid, &status, 0);
+  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+    std::cerr << "Child dtb process failed" << std::endl;
+    exit(1);
+  }
+
+  return dtb.str();
+}
+
 void sim_t::make_config_string()
 {
   reg_t rtc_addr = EXT_IO_BASE;
@@ -220,7 +304,9 @@ void sim_t::make_config_string()
          "};\n";
 
   config_string = s.str();
-  rom.insert(rom.end(), config_string.begin(), config_string.end());
+  std::string dtb = dts_compile(config_string);
+
+  rom.insert(rom.end(), dtb.begin(), dtb.end());
   rom.resize((rom.size() / align + 1) * align);
 
   boot_rom.reset(new rom_device_t(rom));