From 0be479255819c6d09449411181bd7999a25f0f4e Mon Sep 17 00:00:00 2001 From: Yiwei Lin Date: Sun, 5 Jan 2025 23:34:04 +0800 Subject: [PATCH] Allow to modify bootargs for system emulation --- .gitmodules | 4 ++++ Makefile | 3 ++- mk/system.mk | 6 ++++++ src/dtc | 1 + src/main.c | 9 +++++++- src/riscv.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/riscv.h | 1 + 7 files changed, 77 insertions(+), 6 deletions(-) create mode 160000 src/dtc diff --git a/.gitmodules b/.gitmodules index 24acaf307..f9ee9a194 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 86e2b95b4..faffdcfdf 100644 --- a/Makefile +++ b/Makefile @@ -269,10 +269,11 @@ $(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 $< -$(BIN): $(OBJS) $(DEV_OBJS) +$(BIN): $(FDT_OBJS) $(OBJS) $(DEV_OBJS) $(VECHO) " LD\t$@\n" $(Q)$(CC) -o $@ $(CFLAGS_emcc) $^ $(LDFLAGS) diff --git a/mk/system.mk b/mk/system.mk index 5080e2c7f..c82e99ac2 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 @@ -24,6 +26,10 @@ $(DEV_OUT)/%.o: $(DEV_SRC)/%.c $(deps_emcc) DEV_OBJS := $(patsubst $(DEV_SRC)/%.c, $(DEV_OUT)/%.o, $(wildcard $(DEV_SRC)/*.c)) deps := $(DEV_OBJS:%.o=%.o.d) +FDT_OBJS = $(addprefix build/dtc/libfdt/,fdt.o fdt_ro.o fdt_rw.o) +src/dtc/libfdt/%.c: + git submodule update --init src/dtc + OBJS_EXT += system.o # system target execution by using default dependencies diff --git a/src/dtc b/src/dtc new file mode 160000 index 000000000..18f4f305f --- /dev/null +++ b/src/dtc @@ -0,0 +1 @@ +Subproject commit 18f4f305fdd7e14c8941658a29c7b85c27d41de4 diff --git a/src/main.c b/src/main.c index 56734b632..80d3d5ee0 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 72a25ece1..fdc63b3fe 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 46aa75984..1ed7ba65d 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) */