diff --git a/.gitmodules b/.gitmodules index 24acaf30..f9ee9a19 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,7 @@ path = tests/quake url = https://github.com/sysprog21/quake-embedded shallow = true +[submodule "src/dtc"] + path = src/dtc + url = https://git.kernel.org/pub/scm/utils/dtc/dtc.git + shallow = true diff --git a/Makefile b/Makefile index 86e2b95b..9669b0c4 100644 --- a/Makefile +++ b/Makefile @@ -269,6 +269,7 @@ $(OBJS): $(GDBSTUB_LIB) endif $(OUT)/%.o: src/%.c $(deps_emcc) + $(Q)mkdir -p $(shell dirname $@) $(VECHO) " CC\t$@\n" $(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $< diff --git a/mk/system.mk b/mk/system.mk index 5080e2c7..907450be 100644 --- a/mk/system.mk +++ b/mk/system.mk @@ -1,6 +1,8 @@ # Peripherals for system emulation ifeq ($(call has, SYSTEM), 1) +CFLAGS += -Isrc/dtc/libfdt + DEV_SRC := src/devices DTC ?= dtc @@ -25,6 +27,11 @@ DEV_OBJS := $(patsubst $(DEV_SRC)/%.c, $(DEV_OUT)/%.o, $(wildcard $(DEV_SRC)/*.c deps := $(DEV_OBJS:%.o=%.o.d) OBJS_EXT += system.o +FDT_OBJS := fdt.o fdt_ro.o fdt_rw.o +OBJS_EXT +=$(addprefix dtc/libfdt/,$(FDT_OBJS)) + +src/dtc/libfdt/fdt.c: + git submodule update --init src/dtc # system target execution by using default dependencies LINUX_IMAGE_DIR := linux-image diff --git a/src/dtc b/src/dtc new file mode 160000 index 00000000..18f4f305 --- /dev/null +++ b/src/dtc @@ -0,0 +1 @@ +Subproject commit 18f4f305fdd7e14c8941658a29c7b85c27d41de4 diff --git a/src/main.c b/src/main.c index 56734b63..80d3d5ee 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,7 @@ static char *opt_prog_name; /* target argc and argv */ static int prog_argc; static char **prog_args; -static const char *optstr = "tgqmhpd:a:k:i:"; +static const char *optstr = "tgqmhpd:a:k:i:b:"; /* enable misaligned memory access */ static bool opt_misaligned = false; @@ -55,6 +55,7 @@ static char *prof_out_file; /* Linux kernel data */ static char *opt_kernel_img; static char *opt_rootfs_img; +static char *opt_bootargs; #endif static void print_usage(const char *filename) @@ -72,6 +73,7 @@ static void print_usage(const char *filename) #if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) " -k : use as kernel image\n" " -i : use as rootfs\n" + " -b : use customized for the kernel\n" #endif " -d [filename]: dump registers as JSON to the " "given file or `-` (STDOUT)\n" @@ -112,6 +114,10 @@ static bool parse_args(int argc, char **args) opt_rootfs_img = optarg; emu_argc++; break; + case 'b': + opt_bootargs = optarg; + emu_argc++; + break; #endif case 'q': opt_quiet_outputs = true; @@ -257,6 +263,7 @@ int main(int argc, char **args) #if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) attr.data.system.kernel = opt_kernel_img; attr.data.system.initrd = opt_rootfs_img; + attr.data.system.bootargs = opt_bootargs; #else attr.data.user.elf_program = opt_prog_name; #endif diff --git a/src/riscv.c b/src/riscv.c index 72a25ece..fdc63b3f 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -14,6 +14,7 @@ #if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) #include +#include "dtc/libfdt/libfdt.h" #endif #if !defined(_WIN32) && !defined(_WIN64) @@ -259,11 +260,61 @@ static void map_file(char **ram_loc, const char *name) exit(EXIT_FAILURE); } -static void load_dtb(char **ram_loc) +#define ALIGN_FDT(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) +static char *realloc_property(char *fdt, + int nodeoffset, + const char *name, + int newlen) +{ + int delta = 0; + int oldlen = 0; + + if (!fdt_get_property(fdt, nodeoffset, name, &oldlen)) + /* strings + property header */ + delta = sizeof(struct fdt_property) + strlen(name) + 1; + + if (newlen > oldlen) + /* actual value in off_struct */ + delta += ALIGN_FDT(newlen) - ALIGN_FDT(oldlen); + + int new_sz = fdt_totalsize(fdt) + delta; + /* Assume the pre-allocated RAM is enough here, so we + * don't realloc any memory for fdt */ + fdt_open_into(fdt, fdt, new_sz); + return fdt; +} + +static void load_dtb(char **ram_loc, char *bootargs) { #include "minimal_dtb.h" - memcpy(*ram_loc, minimal, sizeof(minimal)); - *ram_loc += sizeof(minimal); + char *blob = *ram_loc; + char *buf; + size_t len; + int node, err; + int totalsize; + + memcpy(blob, minimal, sizeof(minimal)); + + if (bootargs) { + node = fdt_path_offset(blob, "/chosen"); + assert(node > 0); + + len = strlen(bootargs) + 1; + buf = malloc(len); + assert(buf); + memcpy(buf, bootargs, len - 1); + buf[len] = 0; + err = fdt_setprop(blob, node, "bootargs", buf, len + 1); + if (err == -FDT_ERR_NOSPACE) { + blob = realloc_property(blob, node, "bootargs", len); + err = fdt_setprop(blob, node, "bootargs", buf, len); + } + free(buf); + assert(!err); + } + + totalsize = fdt_totalsize(blob); + *ram_loc += totalsize; return; } @@ -418,7 +469,7 @@ riscv_t *rv_create(riscv_user_t rv_attr) uint32_t dtb_addr = attr->mem->mem_size - (1 * 1024 * 1024); ram_loc = ((char *) attr->mem->mem_base) + dtb_addr; - load_dtb(&ram_loc); + load_dtb(&ram_loc, attr->data.system.bootargs); /* * Load optional initrd image at last 8 MiB before the dtb region to * prevent kernel from overwritting it diff --git a/src/riscv.h b/src/riscv.h index 46aa7598..1ed7ba65 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -551,6 +551,7 @@ typedef struct { typedef struct { char *kernel; char *initrd; + char *bootargs; } vm_system_t; #endif /* RV32_HAS(SYSTEM) */