Skip to content

Customize bootargs for system emulation #534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ build/linux-x86-softfp/
build/riscv32/
build/sail_cSim/
build/sha1sum-*
build/bin2c
build/minimal.dtb
*.a
*.o
*.o.d
Expand All @@ -29,3 +31,4 @@ tests/arch-test-target/sail_cSim/riscv_sim_RV32
tests/scimark2/
__pycache__/
src/rv32_jit.c
src/minimal_dtb.h
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2020-2024 National Cheng Kung University, Taiwan
Copyright (c) 2020-2025 National Cheng Kung University, Taiwan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ include mk/artifact.mk
include mk/wasm.mk
include mk/system.mk

all: config $(BUILD_DTB) $(BIN)
all: config $(BUILD_DTB) $(BUILD_DTB2C) $(BIN)

OBJS := \
map.o \
Expand Down Expand Up @@ -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 $<

Expand Down Expand Up @@ -369,7 +370,7 @@ endif
endif

clean:
$(RM) $(BIN) $(OBJS) $(DEV_OBJS) $(BUILD_DTB) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c
$(RM) $(BIN) $(OBJS) $(DEV_OBJS) $(BUILD_DTB) $(BUILD_DTB2C) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c
distclean: clean
-$(RM) $(DOOM_DATA) $(QUAKE_DATA) $(BUILDROOT_DATA) $(LINUX_DATA)
$(RM) -r $(OUT)/linux-image
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ $ make ENABLE_SYSTEM=1 system
Build using run using specified images:
```shell
$ make ENABLE_SYSTEM=1
$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> -b <dtb_path>
$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path>
```

#### Build Linux image
Expand Down
20 changes: 16 additions & 4 deletions mk/system.mk
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
# Peripherals for system emulation
ifeq ($(call has, SYSTEM), 1)

CFLAGS += -Isrc/dtc/libfdt
LIBFDT_HACK := $(shell git submodule update --init src/dtc)

DEV_SRC := src/devices

DTC ?= dtc
$(OUT)/minimal.dtb: $(DEV_SRC)/minimal.dts
BUILD_DTB := $(OUT)/minimal.dtb
$(BUILD_DTB): $(DEV_SRC)/minimal.dts
$(VECHO) " DTC\t$@\n"
$(Q)$(DTC) $^ -o $@
BUILD_DTB := $(OUT)/minimal.dtb

BIN_TO_C := $(OUT)/bin2c
$(BIN_TO_C): tools/bin2c.c
$(Q)$(CC) -Wall -o $@ $^

BUILD_DTB2C := src/minimal_dtb.h
$(BUILD_DTB2C): $(BIN_TO_C) $(BUILD_DTB)
$(BIN_TO_C) $(BUILD_DTB) > $(BUILD_DTB2C)

$(DEV_OUT)/%.o: $(DEV_SRC)/%.c $(deps_emcc)
$(Q)mkdir -p $(DEV_OUT)
Expand All @@ -17,11 +28,12 @@ DEV_OBJS := $(patsubst $(DEV_SRC)/%.c, $(DEV_OUT)/%.o, $(wildcard $(DEV_SRC)/*.c
deps := $(DEV_OBJS:%.o=%.o.d)

OBJS_EXT += system.o
OBJS_EXT += dtc/libfdt/fdt.o dtc/libfdt/fdt_ro.o dtc/libfdt/fdt_rw.o

# system target execution by using default dependencies
LINUX_IMAGE_DIR := linux-image
system_action := ($(BIN) -k $(OUT)/$(LINUX_IMAGE_DIR)/Image -i $(OUT)/$(LINUX_IMAGE_DIR)/rootfs.cpio -b $(OUT)/minimal.dtb)
system_deps += artifact $(BUILD_DTB) $(BIN)
system_action := ($(BIN) -k $(OUT)/$(LINUX_IMAGE_DIR)/Image -i $(OUT)/$(LINUX_IMAGE_DIR)/rootfs.cpio)
system_deps += artifact $(BUILD_DTB) $(BUILD_DTB2C) $(BIN)
system: $(system_deps)
$(system_action)

Expand Down
1 change: 1 addition & 0 deletions src/dtc
Submodule dtc added at 18f4f3
8 changes: 4 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static char *prof_out_file;
/* Linux kernel data */
static char *opt_kernel_img;
static char *opt_rootfs_img;
static char *opt_dtb;
static char *opt_bootargs;
#endif

static void print_usage(const char *filename)
Expand All @@ -73,7 +73,7 @@ static void print_usage(const char *filename)
#if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER)
" -k <image> : use <image> as kernel image\n"
" -i <image> : use <image> as rootfs\n"
" -b <dtb> : use <dtb> as device tree blob\n"
" -b <bootargs> : use customized <bootargs> for the kernel\n"
#endif
" -d [filename]: dump registers as JSON to the "
"given file or `-` (STDOUT)\n"
Expand Down Expand Up @@ -115,7 +115,7 @@ static bool parse_args(int argc, char **args)
emu_argc++;
break;
case 'b':
opt_dtb = optarg;
opt_bootargs = optarg;
emu_argc++;
break;
#endif
Expand Down Expand Up @@ -263,7 +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.dtb = opt_dtb;
attr.data.system.bootargs = opt_bootargs;
#else
attr.data.user.elf_program = opt_prog_name;
#endif
Expand Down
65 changes: 62 additions & 3 deletions src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER)
#include <termios.h>
#include "dtc/libfdt/libfdt.h"
#endif

#if !defined(_WIN32) && !defined(_WIN64)
Expand Down Expand Up @@ -259,6 +260,64 @@ static void map_file(char **ram_loc, const char *name)
exit(EXIT_FAILURE);
}

#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"
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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include an assertion or verify the return value of malloc, as it may fail.

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;
}

/*
* The control mode flag for keyboard.
*
Expand Down Expand Up @@ -294,6 +353,7 @@ static void capture_keyboard_input()
term.c_lflag &= ~TERMIOS_C_CFLAG;
tcsetattr(0, TCSANOW, &term);
}

#endif

/*
Expand Down Expand Up @@ -409,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;
map_file(&ram_loc, attr->data.system.dtb);
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
Expand Down Expand Up @@ -517,8 +577,7 @@ void rv_run(riscv_t *rv)
vm_attr_t *attr = PRIV(rv);
assert(attr &&
#if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER)
attr->data.system.kernel && attr->data.system.initrd &&
attr->data.system.dtb
attr->data.system.kernel && attr->data.system.initrd
#else
attr->data.user.elf_program
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ typedef struct {
typedef struct {
char *kernel;
char *initrd;
char *dtb;
char *bootargs;
} vm_system_t;
#endif /* RV32_HAS(SYSTEM) */

Expand Down
Loading
Loading