diff options
Diffstat (limited to 'riscv/dts.cc')
-rw-r--r-- | riscv/dts.cc | 156 |
1 files changed, 106 insertions, 50 deletions
diff --git a/riscv/dts.cc b/riscv/dts.cc index 8304171..9751ffe 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -13,14 +13,17 @@ #include <sys/types.h> std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, - reg_t initrd_start, reg_t initrd_end, - const char* bootargs, - size_t pmpregions, - size_t pmpgranularity, - std::vector<processor_t*> procs, + const cfg_t* cfg, std::vector<std::pair<reg_t, abstract_mem_t*>> mems, std::string device_nodes) { + reg_t initrd_start = cfg->initrd_bounds.first; + reg_t initrd_end = cfg->initrd_bounds.second; + const char* bootargs = cfg->bootargs; + reg_t pmpregions = cfg->pmpregions; + reg_t pmpgranularity = cfg->pmpgranularity; + isa_parser_t isa(cfg->isa, cfg->priv); + std::stringstream s; s << std::dec << "/dts-v1/;\n" @@ -54,14 +57,14 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, " #address-cells = <1>;\n" " #size-cells = <0>;\n" " timebase-frequency = <" << (cpu_hz/insns_per_rtc_tick) << ">;\n"; - for (size_t i = 0; i < procs.size(); i++) { + for (size_t i = 0; i < cfg->nprocs(); i++) { s << " CPU" << i << ": cpu@" << i << " {\n" " device_type = \"cpu\";\n" - " reg = <" << i << ">;\n" + " reg = <" << cfg->hartids[i] << ">;\n" " status = \"okay\";\n" " compatible = \"riscv\";\n" - " riscv,isa = \"" << procs[i]->get_isa().get_isa_string() << "\";\n" - " mmu-type = \"riscv," << (procs[i]->get_isa().get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" + " riscv,isa = \"" << isa.get_isa_string() << "\";\n" + " mmu-type = \"riscv," << (isa.get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" " riscv,pmpregions = <" << pmpregions << ">;\n" " riscv,pmpgranularity = <" << pmpgranularity << ">;\n" " clock-frequency = <" << cpu_hz << ">;\n" @@ -96,86 +99,98 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, return s.str(); } -std::string dts_compile(const std::string& dts) +static std::string dtc_compile(const std::string& dtc_input, bool compile) { - // Convert the DTS to DTB - int dts_pipe[2]; - pid_t dts_pid; + const char* input_type = compile ? "dts" : "dtb"; + const char* output_type = compile ? "dtb" : "dts"; + + int dtc_input_pipe[2]; + pid_t dtc_input_pid; fflush(NULL); // flush stdout/stderr before forking - if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) { - std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl; + if (pipe(dtc_input_pipe) != 0 || (dtc_input_pid = fork()) < 0) { + std::cerr << "Failed to fork dtc_input 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(); + // Child process to output dtc_input + if (dtc_input_pid == 0) { + close(dtc_input_pipe[0]); + int step, len = dtc_input.length(); + const char *buf = dtc_input.c_str(); for (int done = 0; done < len; done += step) { - step = write(dts_pipe[1], buf+done, len-done); + step = write(dtc_input_pipe[1], buf+done, len-done); if (step == -1) { - std::cerr << "Failed to write dts: " << strerror(errno) << std::endl; + std::cerr << "Failed to write dtc_input: " << strerror(errno) << std::endl; exit(1); } } - close(dts_pipe[1]); + close(dtc_input_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; + pid_t dtc_output_pid; + int dtc_output_pipe[2]; + if (pipe(dtc_output_pipe) != 0 || (dtc_output_pid = fork()) < 0) { + std::cerr << "Failed to fork dtc_output 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]); - execlp(DTC, DTC, "-O", "dtb", (char *)0); + // Child process to output dtc_output + if (dtc_output_pid == 0) { + dup2(dtc_input_pipe[0], 0); + dup2(dtc_output_pipe[1], 1); + close(dtc_input_pipe[0]); + close(dtc_input_pipe[1]); + close(dtc_output_pipe[0]); + close(dtc_output_pipe[1]); + execlp(DTC, DTC, "-O", output_type, "-I", input_type, nullptr); std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl; exit(1); } - close(dts_pipe[1]); - close(dts_pipe[0]); - close(dtb_pipe[1]); + close(dtc_input_pipe[1]); + close(dtc_input_pipe[0]); + close(dtc_output_pipe[1]); - // Read-out dtb - std::stringstream dtb; + // Read-out dtc_output + std::stringstream dtc_output; int got; char buf[4096]; - while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) { - dtb.write(buf, got); + while ((got = read(dtc_output_pipe[0], buf, sizeof(buf))) > 0) { + dtc_output.write(buf, got); } if (got == -1) { - std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl; + std::cerr << "Failed to read dtc_output: " << strerror(errno) << std::endl; exit(1); } - close(dtb_pipe[0]); + close(dtc_output_pipe[0]); // Reap children int status; - waitpid(dts_pid, &status, 0); + waitpid(dtc_input_pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - std::cerr << "Child dts process failed" << std::endl; + std::cerr << "Child dtc_input process failed" << std::endl; exit(1); } - waitpid(dtb_pid, &status, 0); + waitpid(dtc_output_pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - std::cerr << "Child dtb process failed" << std::endl; + std::cerr << "Child dtc_output process failed" << std::endl; exit(1); } - return dtb.str(); + return dtc_output.str(); +} + +std::string dtb_to_dts(const std::string& dtc_input) +{ + return dtc_compile(dtc_input, false); +} + +std::string dts_to_dtb(const std::string& dtc_input) +{ + return dtc_compile(dtc_input, true); } int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr, @@ -386,3 +401,44 @@ int fdt_parse_mmu_type(const void *fdt, int cpu_offset, const char **mmu_type) return 0; } + +int fdt_parse_isa(const void *fdt, int cpu_offset, const char **isa) +{ + assert(isa); + + int len, rc; + const void *prop; + + if ((rc = check_cpu_node(fdt, cpu_offset)) < 0) + return rc; + + prop = fdt_getprop(fdt, cpu_offset, "riscv,isa", &len); + if (!prop || !len) + return -EINVAL; + + *isa = (const char *)prop; + + return 0; +} + +int fdt_parse_hartid(const void *fdt, int cpu_offset, uint32_t *hartid) +{ + int len, rc; + const void *prop; + const fdt32_t *val; + + if ((rc = check_cpu_node(fdt, cpu_offset)) < 0) + return rc; + + val = (fdt32_t*) fdt_getprop(fdt, cpu_offset, "reg", &len); + if (!val || len < (int) sizeof(fdt32_t)) + return -EINVAL; + + if (len > (int) sizeof(fdt32_t)) + val++; + + if (hartid) + *hartid = fdt32_to_cpu(*val); + + return 0; +} |