diff --git a/.gitignore b/.gitignore index b56a9aa8..ebed6c9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ -*.o -*.o.d -*.sw* -semu +build/ # Linux-specific -*.dtb Image ext4.img rootfs.cpio diff --git a/.gitmodules b/.gitmodules index eb01e2ac..e54f640f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,12 @@ -[submodule "mini-gdbstub"] - path = mini-gdbstub - url = https://github.com/RinHizakura/mini-gdbstub - shallow = true -[submodule "minislirp"] - path = minislirp +[submodule "3rdparty/mini-gdbstub"] + path = 3rdparty/mini-gdbstub + url = https://github.com/RinHizakura/mini-gdbstub + shallow = true +[submodule "3rdparty/minislirp"] + path = 3rdparty/minislirp url = https://github.com/edubart/minislirp - shallow = true -[submodule "portaudio"] - path = portaudio - url = https://github.com/PortAudio/portaudio - shallow = true + shallow = true +[submodule "3rdparty/portaudio"] + path = 3rdparty/portaudio + url = https://github.com/PortAudio/portaudio + shallow = true diff --git a/3rdparty/mini-gdbstub b/3rdparty/mini-gdbstub new file mode 160000 index 00000000..39020f21 --- /dev/null +++ b/3rdparty/mini-gdbstub @@ -0,0 +1 @@ +Subproject commit 39020f212aa2aec4c7b9d1686a78a11b64db0535 diff --git a/minislirp b/3rdparty/minislirp similarity index 100% rename from minislirp rename to 3rdparty/minislirp diff --git a/3rdparty/portaudio b/3rdparty/portaudio new file mode 160000 index 00000000..c3f922fa --- /dev/null +++ b/3rdparty/portaudio @@ -0,0 +1 @@ +Subproject commit c3f922fa19712b00961a54f21365803239ec834d diff --git a/Makefile b/Makefile index 96030288..4101ea2f 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,14 @@ include mk/common.mk include mk/check-libs.mk +THIRDPARTY_DIR := 3rdparty +INCLUDE_DIR := include +BUILD_DIR := build +SRC_DIR := src + CC ?= gcc CFLAGS := -O2 -g -Wall -Wextra -CFLAGS += -include common.h +CFLAGS += -I$(INCLUDE_DIR) -I$(THIRDPARTY_DIR) -include $(INCLUDE_DIR)/common.h # clock frequency CLOCK_FREQ ?= 65000000 @@ -11,11 +16,15 @@ DT_CFLAGS := -D CLOCK_FREQ=$(CLOCK_FREQ) CFLAGS += $(DT_CFLAGS) OBJS_EXTRA := +LIBS_EXTRA := + # command line option OPTS := LDFLAGS := +SHELL_HACK := $(shell mkdir -p $(BUILD_DIR)) + # virtio-blk ENABLE_VIRTIOBLK ?= 1 $(call set-feature, VIRTIOBLK) @@ -24,7 +33,7 @@ MKFS_EXT4 ?= mkfs.ext4 ifeq ($(call has, VIRTIOBLK), 1) OBJS_EXTRA += virtio-blk.o DISKIMG_FILE := ext4.img - OPTS += -d $(DISKIMG_FILE) + OPTS += -d $(BUILD_DIR)/$(DISKIMG_FILE) MKFS_EXT4 := $(shell which $(MKFS_EXT4)) ifndef MKFS_EXT4 MKFS_EXT4 := $(shell which $$(brew --prefix e2fsprogs)/sbin/mkfs.ext4) @@ -77,8 +86,9 @@ $(call set-feature, VIRTIOSND) ifeq ($(call has, VIRTIOSND), 1) OBJS_EXTRA += virtio-snd.o - PA_LIB := portaudio/lib/.libs/libportaudio.a - PA_CFLAGS := -Iportaudio/include + PORTAUDIO_DIR := $(THIRDPARTY_DIR)/portaudio + PA_LIB := $(PORTAUDIO_DIR)/lib/.libs/libportaudio.a + PA_CFLAGS := -I$(PORTAUDIO_DIR)/include PA_CONFIG_PARAMS := LDFLAGS += $(PA_LIB) CFLAGS += $(PA_CFLAGS) @@ -105,9 +115,10 @@ ifeq ($(call has, VIRTIOSND), 1) # -lm separately. LDFLAGS += -lpthread -portaudio/Makefile: - git submodule update --init portaudio -$(PA_LIB): portaudio/Makefile +$(PORTAUDIO_DIR)/Makefile: + git submodule update --init $(PORTAUDIO_DIR) + +$(PA_LIB): $(PORTAUDIO_DIR)/Makefile cd $(dir $<) && git clean -fdx && git reset --hard HEAD cd $(dir $<) && ./configure \ --enable-static \ @@ -119,10 +130,10 @@ $(PA_LIB): portaudio/Makefile --disable-dependency-tracking \ $(PA_CONFIG_PARAMS) $(MAKE) -C $(dir $<) -main.o: $(PA_LIB) -virtio-snd.o: $(PA_LIB) +$(BUILD_DIR)/main.o: $(PA_LIB) +$(BUILD_DIR)/virtio-snd.o: $(PA_LIB) # suppress warning when compiling PortAudio -virtio-snd.o: CFLAGS += -Wno-unused-parameter +$(BUILD_DIR)/virtio-snd.o: CFLAGS += -Wno-unused-parameter endif # Set libm as the last dependency so that no need to set -lm seperately. @@ -132,8 +143,9 @@ LDFLAGS += -lm # after git submodule. .DEFAULT_GOAL := all -BIN = semu -all: $(BIN) minimal.dtb +BIN = $(BUILD_DIR)/semu + +all: $(BIN) $(BUILD_DIR)/minimal.dtb OBJS := \ riscv.o \ @@ -145,34 +157,36 @@ OBJS := \ aclint.o \ $(OBJS_EXTRA) -deps := $(OBJS:%.o=.%.o.d) +objs := $(foreach obj,$(OBJS),$(BUILD_DIR)/$(obj)) +deps := $(patsubst %.o,$(BUILD_DIR)/%.o.d,$(OBJS)) -GDBSTUB_LIB := mini-gdbstub/build/libgdbstub.a -LDFLAGS += $(GDBSTUB_LIB) -mini-gdbstub/Makefile: +MINI_GDBSTUB_DIR := $(THIRDPARTY_DIR)/mini-gdbstub +MINI_GDBSTUB_LIB := $(MINI_GDBSTUB_DIR)/build/libgdbstub.a +LDFLAGS += $(MINI_GDBSTUB_LIB) +$(THIRDPARTY_DIR)/mini-gdbstub/Makefile: git submodule update --init $(dir $@) -$(GDBSTUB_LIB): mini-gdbstub/Makefile +$(MINI_GDBSTUB_LIB): $(MINI_GDBSTUB_DIR)/Makefile $(MAKE) -C $(dir $<) -$(OBJS): $(GDBSTUB_LIB) +LIBS_EXTRA += $(MINI_GDBSTUB_LIB) ifeq ($(call has, VIRTIONET), 1) -MINISLIRP_DIR := minislirp -MINISLIRP_LIB := minislirp/src/libslirp.a +MINISLIRP_DIR := $(THIRDPARTY_DIR)/minislirp +MINISLIRP_LIB := $(MINISLIRP_DIR)/src/libslirp.a LDFLAGS += $(MINISLIRP_LIB) $(MINISLIRP_DIR)/src/Makefile: git submodule update --init $(MINISLIRP_DIR) $(MINISLIRP_LIB): $(MINISLIRP_DIR)/src/Makefile $(MAKE) -C $(dir $<) -$(OBJS): $(MINISLIRP_LIB) +LIBS_EXTRA += $(MINISLIRP_LIB) endif -$(BIN): $(OBJS) +$(BIN): $(objs) $(VECHO) " LD\t$@\n" $(Q)$(CC) -o $@ $^ $(LDFLAGS) -%.o: %.c +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(LIBS_EXTRA) $(VECHO) " CC\t$@\n" - $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF .$@.d $< + $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $< DTC ?= dtc @@ -196,40 +210,42 @@ S := $E $E CFLAGS += -D SEMU_BOOT_TARGET_TIME=10 SMP ?= 1 -.PHONY: riscv-harts.dtsi -riscv-harts.dtsi: +.PHONY: $(INCLUDE_DIR)/riscv-harts.dtsi +$(INCLUDE_DIR)/riscv-harts.dtsi: $(Q)python3 scripts/gen-hart-dts.py $@ $(SMP) $(CLOCK_FREQ) -minimal.dtb: minimal.dts riscv-harts.dtsi +$(BUILD_DIR)/minimal.dtb: $(SRC_DIR)/minimal.dts $(INCLUDE_DIR)/riscv-harts.dtsi $(VECHO) " DTC\t$@\n" $(Q)$(CC) -nostdinc -E -P -x assembler-with-cpp -undef \ + -I$(INCLUDE_DIR) \ $(DT_CFLAGS) \ $(subst ^,$S,$(filter -D^SEMU_FEATURE_%, $(subst -D$(S)SEMU_FEATURE,-D^SEMU_FEATURE,$(CFLAGS)))) $< \ | $(DTC) - > $@ -# Rules for downloading prebuilt Linux kernel image -include mk/external.mk - -ext4.img: +$(BUILD_DIR)/$(DISKIMG_FILE): $(Q)dd if=/dev/zero of=$@ bs=4k count=600 $(Q)$(MKFS_EXT4) -F $@ -check: $(BIN) minimal.dtb $(KERNEL_DATA) $(INITRD_DATA) $(DISKIMG_FILE) +.PHONY: download-artifacts +download-artifacts: + $(Q)scripts/download-artifacts.sh Image $(BUILD_DIR) + $(Q)scripts/download-artifacts.sh rootfs $(BUILD_DIR) + +check: $(BIN) $(BUILD_DIR)/minimal.dtb $(BUILD_DIR)/$(DISKIMG_FILE) download-artifacts @$(call notice, Ready to launch Linux kernel. Please be patient.) - $(Q)./$(BIN) -k $(KERNEL_DATA) -c $(SMP) -b minimal.dtb -i $(INITRD_DATA) -n $(NETDEV) $(OPTS) + $(Q)$(BIN) -k $(BUILD_DIR)/Image -c $(SMP) -b $(BUILD_DIR)/minimal.dtb -i $(BUILD_DIR)/rootfs.cpio -n $(NETDEV) $(OPTS) build-image: scripts/build-image.sh clean: - $(Q)$(RM) $(BIN) $(OBJS) $(deps) - $(Q)$(MAKE) -C mini-gdbstub clean - $(Q)$(MAKE) -C minislirp/src clean + $(Q)$(RM) $(BIN) $(objs) $(deps) + $(Q)$(MAKE) -C $(THIRDPARTY_DIR)/mini-gdbstub clean + $(Q)$(MAKE) -C $(THIRDPARTY_DIR)/minislirp/src clean + $(Q)$(MAKE) -C $(THIRDPARTY_DIR)/portaudio clean distclean: clean - $(Q)$(RM) riscv-harts.dtsi - $(Q)$(RM) minimal.dtb - $(Q)$(RM) Image rootfs.cpio - $(Q)$(RM) ext4.img + $(Q)$(RM) $(INCLUDE_DIR)/riscv-harts.dtsi + $(Q)$(RM) $(BUILD_DIR)/* -include $(deps) diff --git a/common.h b/include/common.h similarity index 100% rename from common.h rename to include/common.h diff --git a/device.h b/include/device.h similarity index 100% rename from device.h rename to include/device.h diff --git a/feature.h b/include/feature.h similarity index 100% rename from feature.h rename to include/feature.h diff --git a/netdev.h b/include/netdev.h similarity index 100% rename from netdev.h rename to include/netdev.h diff --git a/riscv.h b/include/riscv.h similarity index 100% rename from riscv.h rename to include/riscv.h diff --git a/riscv_private.h b/include/riscv_private.h similarity index 100% rename from riscv_private.h rename to include/riscv_private.h diff --git a/utils.h b/include/utils.h similarity index 100% rename from utils.h rename to include/utils.h diff --git a/virtio.h b/include/virtio.h similarity index 100% rename from virtio.h rename to include/virtio.h diff --git a/mini-gdbstub b/mini-gdbstub deleted file mode 160000 index 18a3746f..00000000 --- a/mini-gdbstub +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 18a3746fda1a03d82b31bc6b8f15c47e5808cee1 diff --git a/mk/external.mk b/mk/external.mk deleted file mode 100644 index dceeef78..00000000 --- a/mk/external.mk +++ /dev/null @@ -1,27 +0,0 @@ -# For each external target, the following must be defined in advance: -# _DATA_URL : the hyperlink which points to archive. -# _DATA : the file to be read by specific executable. -# _DATA_SHA1 : the checksum of the content in _DATA - -COMMON_URL = https://github.com/sysprog21/semu/raw/blob - -# kernel -KERNEL_DATA_URL = $(COMMON_URL)/Image.bz2 -KERNEL_DATA = Image -KERNEL_DATA_SHA1 = 72a8454575508d09210f067b25239cd51b929d27 - -# initrd -INITRD_DATA_URL = $(COMMON_URL)/rootfs.cpio.bz2 -INITRD_DATA = rootfs.cpio -INITRD_DATA_SHA1 = 18bd639c17fc299c317f8fed1c845e7dda296748 - -define download -$($(T)_DATA): - $(VECHO) " GET\t$$@\n" - $(Q)curl --progress-bar -O -L -C - "$(strip $($(T)_DATA_URL))" - $(Q)echo "$(strip $$($(T)_DATA_SHA1)) $$@.bz2" | $(SHA1SUM) -c - - $(Q)bunzip2 $$@.bz2 -endef - -EXTERNAL_DATA = KERNEL INITRD -$(foreach T,$(EXTERNAL_DATA),$(eval $(download))) diff --git a/portaudio b/portaudio deleted file mode 160000 index e97effb2..00000000 --- a/portaudio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e97effb2b910e579efe8c5af40b43adf19fd8c33 diff --git a/scripts/download-artifacts.sh b/scripts/download-artifacts.sh new file mode 100755 index 00000000..c9423e0f --- /dev/null +++ b/scripts/download-artifacts.sh @@ -0,0 +1,88 @@ +#!/bin/sh + +BASE_URL="https://github.com/sysprog21/semu/raw/blob" + +IMAGE_SHA1="72a8454575508d09210f067b25239cd51b929d27" +ROOTFS_SHA1="18bd639c17fc299c317f8fed1c845e7dda296748" + +DEST_DIR="./build" + +if [ -z "$1" ]; then + echo "No file name provided. Please provide a target as the first argument." + exit 1 +fi + +case "$1" in + "Image") + FULL_URL="${BASE_URL}/Image.bz2" + LOCAL_FILE_PATH="${DEST_DIR}/Image" + FILE_SHA1="${IMAGE_SHA1}" + ;; + "rootfs") + FULL_URL="${BASE_URL}/rootfs.cpio.bz2" + LOCAL_FILE_PATH="${DEST_DIR}/rootfs.cpio" + FILE_SHA1="${ROOTFS_SHA1}" + ;; + *) + echo "Invalid target: \"$1\"" + echo "Available keywords are: Image, rootfs" + exit 1 + ;; +esac + +if [ ! -z "$2" ]; then + DEST_DIR="$2" +else + echo "No destination directory provided. Using the default one: \"$DEST_DIR\"" +fi + +if [ ! -d "$DEST_DIR" ]; then + mkdir -p "$DEST_DIR" +fi + +if [ ! -f "${LOCAL_FILE_PATH}.bz2" ]; then + NEED_REDOWNLOAD="1" + + echo "The file \"${LOCAL_FILE_PATH}.bz2\" was not found. Downloading..." +else + SHA1_CHECK_RES=$(echo "${FILE_SHA1} ${LOCAL_FILE_PATH}.bz2" | sha1sum -c - >/dev/null 2>&1 || echo "failed") + + if [ "$SHA1_CHECK_RES" = "failed" ]; then + NEED_REDOWNLOAD="1" + + echo "Local file \"${LOCAL_FILE_PATH}.bz2\" already exists. Checking SHA1... Failed" + + # if the existing file is larger, the extra part would be ignored by "curl -C". + rm "${LOCAL_FILE_PATH}.bz2" + + echo "Re-downloading file..." + else + echo "Local file \"${LOCAL_FILE_PATH}.bz2\" already exists. Checking SHA1... Passed" + echo "File is up-to-date. Skipping download." + fi +fi + +if [ ! -z "$NEED_REDOWNLOAD" ]; then + curl --progress-bar -L -C - "$FULL_URL" -o "${LOCAL_FILE_PATH}.bz2" + + SHA1_CHECK_RES=$(echo "${FILE_SHA1} ${LOCAL_FILE_PATH}.bz2" | sha1sum -c - >/dev/null 2>&1 || echo "failed") + + if [ "$SHA1_CHECK_RES" = "failed" ]; then + echo "Checking SHA1... Failed" + echo "Error: The SHA1 might be outdated. Please update your local copy and try again." + exit 1 + else + echo "Checking SHA1... Passed" + fi +fi + +echo "Extracting from \"${LOCAL_FILE_PATH}.bz2\"" + +bunzip2 --keep "${LOCAL_FILE_PATH}.bz2" >/dev/null 2>&1 + +if [ ! -f "$LOCAL_FILE_PATH" ]; then + echo "Something went wrong! The file \"$LOCAL_FILE_PATH\" was not found." + exit 1 +else + echo "Completed!" +fi diff --git a/aclint.c b/src/aclint.c similarity index 100% rename from aclint.c rename to src/aclint.c diff --git a/main.c b/src/main.c similarity index 100% rename from main.c rename to src/main.c diff --git a/minimal.dts b/src/minimal.dts similarity index 100% rename from minimal.dts rename to src/minimal.dts diff --git a/netdev.c b/src/netdev.c similarity index 100% rename from netdev.c rename to src/netdev.c diff --git a/plic.c b/src/plic.c similarity index 100% rename from plic.c rename to src/plic.c diff --git a/ram.c b/src/ram.c similarity index 100% rename from ram.c rename to src/ram.c diff --git a/riscv.c b/src/riscv.c similarity index 99% rename from riscv.c rename to src/riscv.c index bd92f1f0..59acc2fa 100644 --- a/riscv.c +++ b/src/riscv.c @@ -1,6 +1,5 @@ #include -#include "common.h" #include "device.h" #include "riscv.h" #include "riscv_private.h" diff --git a/slirp.c b/src/slirp.c similarity index 100% rename from slirp.c rename to src/slirp.c diff --git a/uart.c b/src/uart.c similarity index 100% rename from uart.c rename to src/uart.c diff --git a/utils.c b/src/utils.c similarity index 100% rename from utils.c rename to src/utils.c diff --git a/virtio-blk.c b/src/virtio-blk.c similarity index 99% rename from virtio-blk.c rename to src/virtio-blk.c index c64cda78..6f214d4f 100644 --- a/virtio-blk.c +++ b/src/virtio-blk.c @@ -9,7 +9,6 @@ #include #include -#include "common.h" #include "device.h" #include "riscv.h" #include "riscv_private.h" diff --git a/virtio-net.c b/src/virtio-net.c similarity index 99% rename from virtio-net.c rename to src/virtio-net.c index 9fb9baaf..6f0683bf 100644 --- a/virtio-net.c +++ b/src/virtio-net.c @@ -11,7 +11,6 @@ #include #include -#include "common.h" #include "device.h" #include "riscv.h" #include "riscv_private.h" diff --git a/virtio-rng.c b/src/virtio-rng.c similarity index 99% rename from virtio-rng.c rename to src/virtio-rng.c index 2876fe09..7a3aad4d 100644 --- a/virtio-rng.c +++ b/src/virtio-rng.c @@ -4,7 +4,6 @@ #include #include -#include "common.h" #include "device.h" #include "riscv.h" #include "riscv_private.h" diff --git a/virtio-snd.c b/src/virtio-snd.c similarity index 100% rename from virtio-snd.c rename to src/virtio-snd.c