diff --git a/.ci/boot-linux-prepare.sh b/.ci/boot-linux-prepare.sh index 0e801dbb..15a591b2 100755 --- a/.ci/boot-linux-prepare.sh +++ b/.ci/boot-linux-prepare.sh @@ -6,7 +6,15 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" check_platform -VBLK_IMG=build/disk.img +VBLK_IMGS=( + build/disk_ext4.img +) +# FIXME: mkfs.simplefs is not compilable on macOS, thus running the +# simplefs cases on Linux runner for now +if [[ "${OS_TYPE}" == "Linux" ]]; then + VBLK_IMGS+=(build/disk_simplefs.img) +fi + which dd > /dev/null 2>&1 || { echo "Error: dd not found" exit 1 @@ -25,48 +33,77 @@ ACTION=$1 case "$ACTION" in setup) - # Setup a disk image - dd if=/dev/zero of=${VBLK_IMG} bs=4M count=32 + # Clone simplefs to use mkfs.simplefs util and create simplefs disk image + git clone https://github.com/sysprog21/simplefs.git -b rel2025.0 --depth 1 - # Setup a /dev/ block device with ${VBLK_IMG} to test guestOS access to hostOS /dev/ block device - case "${OS_TYPE}" in - Linux) - mkfs.ext4 ${VBLK_IMG} - BLK_DEV=$(losetup -f) - losetup ${BLK_DEV} ${VBLK_IMG} - ;; - Darwin) - $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 ${VBLK_IMG} - BLK_DEV=$(hdiutil attach -nomount ${VBLK_IMG}) - ;; - esac + # Setup disk images + for disk_img in "${VBLK_IMGS[@]}"; do + case "${OS_TYPE}" in + Linux) + # Setup a /dev/ block device with ext4 fs to test guestOS access to hostOS /dev/ block device + if [[ "${disk_img}" =~ ext4 ]]; then + dd if=/dev/zero of=${disk_img} bs=4M count=32 + mkfs.ext4 ${disk_img} + else + mkdir -p simplefs/build + make IMAGE=${disk_img} ${disk_img} -C simplefs + mv simplefs/${disk_img} ./build + fi + BLK_DEV=$(losetup -f) + losetup ${BLK_DEV} ${disk_img} + ;; + Darwin) + # Setup a /dev/ block device with ext4 fs to test guestOS access to hostOS /dev/ block device + dd if=/dev/zero of=${disk_img} bs=4M count=32 + $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 ${disk_img} + BLK_DEV=$(hdiutil attach -nomount ${disk_img}) + ;; + esac - # On Linux, ${VBLK_IMG} will be created by root and owned by root:root. - # Even if "others" have read and write (rw) permissions, accessing the file for certain operations may - # still require elevated privileges (e.g., setuid). - # To simplify this, we change the ownership to a non-root user. - # Use this with caution—changing ownership to runner:runner is specific to the GitHub CI environment. - chown runner: ${VBLK_IMG} - # Add other's rw permission to the disk image and device, so non-superuser can rw them - chmod o+r,o+w ${VBLK_IMG} - chmod o+r,o+w ${BLK_DEV} + # On Linux, ${disk_img} will be created by root and owned by root:root. + # Even if "others" have read and write (rw) permissions, accessing the file for certain operations may + # still require elevated privileges (e.g., setuid). + # To simplify this, we change the ownership to a non-root user. + # Use this with caution—changing ownership to runner:runner is specific to the GitHub CI environment. + chown runner: ${disk_img} + # Add other's rw permission to the disk image and device, so non-superuser can rw them + chmod o+r,o+w ${disk_img} + chmod o+r,o+w ${BLK_DEV} - # Export ${BLK_DEV} to a tmp file. Then, source to "$GITHUB_ENV" in job step. - echo "export BLK_DEV=${BLK_DEV}" > "${TMP_FILE}" + # Export ${BLK_DEV} to a tmp file. Then, source to "$GITHUB_ENV" in job step. + if [[ "${disk_img}" =~ ext4 ]]; then + echo "export BLK_DEV_EXT4=${BLK_DEV}" >> "${TMP_FILE}" + else + echo "export BLK_DEV_SIMPLEFS=${BLK_DEV}" >> "${TMP_FILE}" + fi + done + + # Put simplefs.ko into ext4 fs + mkdir -p mnt + mount ${VBLK_IMGS[0]} mnt + cp build/linux-image/simplefs.ko mnt + umount mnt + rm -rf mnt ;; cleanup) + # Remove simplefs repo + rm -rf simplefs + # Detach the /dev/loopx(Linux) or /dev/diskx(Darwin) case "${OS_TYPE}" in Linux) - losetup -d ${BLK_DEV} + losetup -d ${BLK_DEV_EXT4} + losetup -d ${BLK_DEV_SIMPLEFS} ;; Darwin) - hdiutil detach ${BLK_DEV} + hdiutil detach ${BLK_DEV_EXT4} ;; esac - # delete disk image - rm -f ${VBLK_IMG} + # delete disk images + for disk_img in "${VBLK_IMGS[@]}"; do + rm -f ${disk_img} + done # delete tmp file rm "${TMP_FILE}" diff --git a/.ci/boot-linux.sh b/.ci/boot-linux.sh index c2aafc20..48a396f2 100755 --- a/.ci/boot-linux.sh +++ b/.ci/boot-linux.sh @@ -66,8 +66,22 @@ ASSERT() cleanup ENABLE_VBLK=1 -VBLK_IMG=build/disk.img -[ -f "${VBLK_IMG}" ] || ENABLE_VBLK=0 +VBLK_IMGS=( + build/disk_ext4.img +) +# FIXME: mkfs.simplefs is not compilable on macOS, thus running the +# simplefs cases on Linux runner for now +if [[ "${OS_TYPE}" == "Linux" ]]; then + VBLK_IMGS+=(build/disk_simplefs.img) +fi +SIMPLEFS_KO_SRC="${VBLK_IMGS[0]}" + +# If any disk image is not found in the VBLK_IMGS, skip the VBLK tests +for disk_img in "${VBLK_IMGS[@]}"; do + if [ ! -f "${disk_img}" ]; then + ENABLE_VBLK=0 + fi +done TIMEOUT=50 OPTS_BASE=" -k build/linux-image/Image" @@ -85,28 +99,64 @@ COLOR_R='\e[31;01m' # Red COLOR_Y='\e[33;01m' # Yellow COLOR_N='\e[0m' # No color -MESSAGES=("${COLOR_G}OK!" - "${COLOR_R}Fail to boot" - "${COLOR_R}Fail to login" - "${COLOR_R}Fail to run commands" - "${COLOR_R}Fail to find emu.txt in ${VBLK_IMG}" -) +for disk_img in "${VBLK_IMGS[@]}"; do + TEST_OPTIONS=() + EXPECT_CMDS=() + + MESSAGES=("${COLOR_G}OK!" + "${COLOR_R}Fail to boot" + "${COLOR_R}Fail to login" + "${COLOR_R}Fail to run commands" + "${COLOR_R}Fail to find emu.txt in ${disk_img}" + ) -if [ "${ENABLE_VBLK}" -eq "1" ]; then - # Read-only - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG},readonly") - EXPECT_CMDS+=(' + if [ "${ENABLE_VBLK}" -eq "1" ]; then + # Read-only + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTION="${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:${disk_img},readonly" + EXPECT_CMD=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir simplefs_ko_src && mount /dev/vdb simplefs_ko_src && \ + insmod simplefs_ko_src/simplefs.ko\n" } timeout { exit 3 } + expect "simplefs: module loaded" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect -ex "-sh: can'\''t create mnt/emu.txt: Read-only file system" {} timeout { exit 3 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + else + TEST_OPTION="${OPTS_BASE} -x vblk:${disk_img},readonly" + EXPECT_CMD=' expect "buildroot login:" { send "root\n" } timeout { exit 1 } expect "# " { send "uname -a\n" } timeout { exit 2 } expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } expect -ex "-sh: can'\''t create mnt/emu.txt: Read-only file system" {} timeout { exit 3 } expect "# " { send "\x01"; send "x" } timeout { exit 3 } - ') + ' + fi + TEST_OPTIONS+=("${TEST_OPTION}") + EXPECT_CMDS+=("${EXPECT_CMD}") - # multiple blocks, Read-only, one disk image, one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin)) - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG},readonly -x vblk:${BLK_DEV},readonly") - EXPECT_CMDS+=(' + # multiple blocks, Read-only, one disk image, one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin)) + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTION=("${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:${disk_img},readonly -x vblk:${BLK_DEV_SIMPLEFS},readonly") + EXPECT_CMD=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir simplefs_ko_src && mount /dev/vdc simplefs_ko_src && \ + insmod simplefs_ko_src/simplefs.ko\n" } timeout { exit 3 } + expect "simplefs: module loaded" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect -ex "-sh: can'\''t create mnt/emu.txt: Read-only file system" {} timeout { exit 3 } + expect "# " { send "mkdir mnt2 && mount /dev/vdb mnt2\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt2/emu.txt\n" } timeout { exit 3 } + expect -ex "-sh: can'\''t create mnt2/emu.txt: Read-only file system" {} timeout { exit 3 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + else + TEST_OPTION=("${OPTS_BASE} -x vblk:${disk_img},readonly -x vblk:${BLK_DEV_EXT4},readonly") + EXPECT_CMD=' expect "buildroot login:" { send "root\n" } timeout { exit 1 } expect "# " { send "uname -a\n" } timeout { exit 2 } expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } @@ -116,11 +166,29 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then expect "# " { send "echo rv32emu > mnt2/emu.txt\n" } timeout { exit 3 } expect -ex "-sh: can'\''t create mnt2/emu.txt: Read-only file system" {} timeout { exit 3 } expect "# " { send "\x01"; send "x" } timeout { exit 3 } - ') + ' + fi + TEST_OPTIONS+=("${TEST_OPTION}") + EXPECT_CMDS+=("${EXPECT_CMD}") - # Read-write using disk image with ~ home directory symbol - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:~$(pwd | sed "s|$HOME||")/${VBLK_IMG}") - VBLK_EXPECT_CMDS=' + # Read-write using disk image with ~ home directory symbol + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTION=("${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:~$(pwd | sed "s|$HOME||")/${disk_img}") + EXPECT_CMD=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir simplefs_ko_src && mount /dev/vdb simplefs_ko_src && \ + insmod simplefs_ko_src/simplefs.ko\n" } timeout { exit 3 } + expect "simplefs: module loaded" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect "# " { send "sync\n" } timeout { exit 3 } + expect "# " { send "cat mnt/emu.txt\n" } timeout { exit 3 } + expect "rv32emu" { send "umount mnt\n" } timeout { exit 4 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + else + TEST_OPTION=("${OPTS_BASE} -x vblk:~$(pwd | sed "s|$HOME||")/${disk_img}") + EXPECT_CMD=' expect "buildroot login:" { send "root\n" } timeout { exit 1 } expect "# " { send "uname -a\n" } timeout { exit 2 } expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } @@ -129,11 +197,29 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then expect "# " { send "umount mnt\n" } timeout { exit 3 } expect "# " { send "\x01"; send "x" } timeout { exit 3 } ' - EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") + fi + TEST_OPTIONS+=("${TEST_OPTION}") + EXPECT_CMDS+=("${EXPECT_CMD}") - # Read-write using disk image - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG}") - VBLK_EXPECT_CMDS=' + # Read-write using disk image + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTION=("${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:${disk_img}") + VBLK_EXPECT_CMDS=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir simplefs_ko_src && mount /dev/vdb simplefs_ko_src && \ + insmod simplefs_ko_src/simplefs.ko\n" } timeout { exit 3 } + expect "simplefs: module loaded" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect "# " { send "sync\n" } timeout { exit 3 } + expect "# " { send "cat mnt/emu.txt\n" } timeout { exit 3 } + expect "rv32emu" { send "umount mnt\n" } timeout { exit 4 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + EXPECT_CMD=("${VBLK_EXPECT_CMDS}") + else + TEST_OPTION=("${OPTS_BASE} -x vblk:${disk_img}") + VBLK_EXPECT_CMDS=' expect "buildroot login:" { send "root\n" } timeout { exit 1 } expect "# " { send "uname -a\n" } timeout { exit 2 } expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } @@ -142,15 +228,42 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then expect "# " { send "umount mnt\n" } timeout { exit 3 } expect "# " { send "\x01"; send "x" } timeout { exit 3 } ' - EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") + EXPECT_CMD=("${VBLK_EXPECT_CMDS}") + fi + TEST_OPTIONS+=("${TEST_OPTION}") + EXPECT_CMDS+=("${EXPECT_CMD}") - # Read-write using /dev/loopx(Linux) or /dev/diskx(Darwin) block device - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${BLK_DEV}") - EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") + # Read-write using /dev/loopx(Linux) or /dev/diskx(Darwin) block device + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:${BLK_DEV_SIMPLEFS}") + EXPECT_CMDS+=("${EXPECT_CMD}") + else + TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${BLK_DEV_EXT4}") + EXPECT_CMDS+=("${EXPECT_CMD}") + fi - # multiple blocks, Read-write, one disk image and one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin)) - TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG} -x vblk:${BLK_DEV}") - VBLK_EXPECT_CMDS=' + # multiple blocks, Read-write, one disk image and one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin)) + if [[ ${disk_img} =~ simplefs ]]; then + TEST_OPTION=("${OPTS_BASE} -x vblk:${SIMPLEFS_KO_SRC} -x vblk:${disk_img} -x vblk:${BLK_DEV_SIMPLEFS}") + EXPECT_CMD=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir simplefs_ko_src && mount /dev/vdc simplefs_ko_src && \ + insmod simplefs_ko_src/simplefs.ko\n" } timeout { exit 3 } + expect "simplefs: module loaded" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect "# " { send "sync\n" } timeout { exit 3 } + expect "# " { send "umount mnt\n" } timeout { exit 3 } + expect "# " { send "mkdir mnt2 && mount /dev/vdb mnt2\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt2/emu.txt\n" } timeout { exit 3 } + expect "# " { send "sync\n" } timeout { exit 3 } + expect "# " { send "cat mnt2/emu.txt\n" } timeout { exit 3 } + expect "rv32emu" { send "umount mnt2\n" } timeout { exit 4 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + else + TEST_OPTION=("${OPTS_BASE} -x vblk:${disk_img} -x vblk:${BLK_DEV_EXT4}") + EXPECT_CMD=' expect "buildroot login:" { send "root\n" } timeout { exit 1 } expect "# " { send "uname -a\n" } timeout { exit 2 } expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } @@ -163,46 +276,45 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then expect "# " { send "umount mnt2\n" } timeout { exit 3 } expect "# " { send "\x01"; send "x" } timeout { exit 3 } ' - EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") -fi + fi + TEST_OPTIONS+=("${TEST_OPTION}") + EXPECT_CMDS+=("${EXPECT_CMD}") + fi -for i in "${!TEST_OPTIONS[@]}"; do - printf "${COLOR_Y}===== Test option: ${TEST_OPTIONS[$i]} =====${COLOR_N}\n" + for i in "${!TEST_OPTIONS[@]}"; do + printf "${COLOR_Y}===== Test option: ${TEST_OPTIONS[$i]} =====${COLOR_N}\n" - OPTS="${OPTS_BASE}" - # No need to add option when running base test - case "${TEST_OPTIONS[$i]}" in - *base*) ;; - *) + OPTS="${OPTS_BASE}" + # No need to add option when running base test + if [[ ! "${TEST_OPTIONS[$i]}" =~ "base" ]]; then OPTS+="${TEST_OPTIONS[$i]}" - ;; - esac - RUN_LINUX="build/rv32emu ${OPTS}" + fi + RUN_LINUX="build/rv32emu ${OPTS}" - ASSERT expect <<- DONE + ASSERT expect <<- DONE set timeout ${TIMEOUT} spawn ${RUN_LINUX} ${EXPECT_CMDS[$i]} DONE - ret=$? - cleanup + ret=$? + cleanup - printf "\nBoot Linux Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" - case "${TEST_OPTIONS[$i]}" in - *vblk*) + printf "\nBoot Linux Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" + if [[ "${TEST_OPTIONS[$i]}" =~ vblk ]]; then # read-only test first, so the emu.txt definitely does not exist, skipping the check - case "${TEST_OPTIONS[$i]}" in - *readonly*) ;; - *) - if ! check_image_for_file "${VBLK_IMG}" emu.txt; then - ret=4 - fi - ;; - esac + if [[ ! "${TEST_OPTIONS[$i]}" =~ readonly ]]; then + if [[ ${disk_img} =~ simplefs ]]; then + # Does not verify the written file on hostOS since 7z does not recognize the format. + # But, the written file is printed out and verified in EXPECT_CMD in guestOS + : + else + 7z l ${disk_img} | grep emu.txt > /dev/null 2>&1 || ret=4 + fi + fi printf "Virtio-blk Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" - ;; - esac + fi + done done exit ${ret} diff --git a/.github/workflows/build-linux-artifacts.yml b/.github/workflows/build-linux-artifacts.yml index 6647f4cb..cf4043da 100644 --- a/.github/workflows/build-linux-artifacts.yml +++ b/.github/workflows/build-linux-artifacts.yml @@ -55,10 +55,6 @@ jobs: run: | make build-linux-image make artifact ENABLE_PREBUILT=0 ENABLE_SYSTEM=1 - mkdir -p /tmp/rv32emu-linux-image-prebuilt/linux-image - mv build/linux-image/Image /tmp/rv32emu-linux-image-prebuilt/linux-image - mv build/linux-image/rootfs.cpio /tmp/rv32emu-linux-image-prebuilt/linux-image - mv build/sha1sum-linux-image /tmp - name: Create tarball run: | cd /tmp diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e491a842..b700ecdc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -72,7 +72,8 @@ jobs: . \${TMP_FILE}; \ .ci/boot-linux.sh; \ EXIT_CODE=\$?; \ - sudo env TMP_FILE=\${TMP_FILE} BLK_DEV=\${BLK_DEV} .ci/boot-linux-prepare.sh cleanup; \ + sudo env TMP_FILE=\${TMP_FILE} BLK_DEV_EXT4=\${BLK_DEV_EXT4} \ + BLK_DEV_SIMPLEFS=\${BLK_DEV_SIMPLEFS} .ci/boot-linux-prepare.sh cleanup; \ exit \${EXIT_CODE};" >> "$GITHUB_ENV" - name: fetch artifact first to reduce HTTP requests env: @@ -375,7 +376,7 @@ jobs: . \${TMP_FILE}; \ .ci/boot-linux.sh; \ EXIT_CODE=\$?; \ - sudo env TMP_FILE=\${TMP_FILE} BLK_DEV=\${BLK_DEV} .ci/boot-linux-prepare.sh cleanup; \ + sudo env TMP_FILE=\${TMP_FILE} BLK_DEV_EXT4=\${BLK_DEV_EXT4} .ci/boot-linux-prepare.sh cleanup; \ exit \${EXIT_CODE};" >> "$GITHUB_ENV" - name: Symlink gcc-15 due to the default /usr/local/bin/gcc links to system's clang run: | diff --git a/README.md b/README.md index 5efe1fe3..1d6fe130 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,19 @@ $ build/rv32emu -k -i -x vblk:disk.img -x vb ``` Note that the /dev/vdx device order in guestOS is assigned in reverse: the first `-x vblk` argument corresponds to the device with the highest letter, while subsequent arguments receive lower-lettered device names. +In addition to the built-in ext4 filesystem support, other out-of-tree filesystems such as [simplefs](https://github.com/sysprog21/simplefs) are also supported. To use simplefs, first follow the instructions [here](https://github.com/sysprog21/simplefs?tab=readme-ov-file#build-and-run) to generate the simplefs disk image, and then attach it to the guestOS via the virtio block device. An additional ext4 image containing `simplefs.ko` must also be attached to the guestOS, since `simplefs.ko` is out-of-tree kernel module. The pre-built `simplefs.ko` can be found at `build/linux-image/` (run `make artifact ENABLE_SYSTEM=1` to get the artifacts). +```shell +$ build/rv32emu -k -i -x vblk: -x vblk: +``` +Once the guestOS is booted, insert the `simplefs.ko` kernel module. After loading the kernel module, the simplefs disk will be recognized by the Linux kernel and can be mounted and used as a regular filesystem. +```shell +# mkdir -p mnt && mount /dev/vdb mnt # mount the ext4 disk that contains simplefs.ko + +# insmod mnt/simplefs.ko # insert simplefs.ko + +# mkdir -p simplefs && mount -t simplefs /dev/vda simplefs # mount the simplefs disk +``` + #### Customize bootargs Build and run with customized bootargs to boot the guestOS. Otherwise, the default bootargs defined in `src/devices/minimal.dts` will be used. ```shell diff --git a/mk/artifact.mk b/mk/artifact.mk index db4936e1..41e374b9 100644 --- a/mk/artifact.mk +++ b/mk/artifact.mk @@ -135,8 +135,14 @@ else endif else ifeq ($(call has, SYSTEM), 1) + $(Q)(mkdir -p /tmp/rv32emu-linux-image-prebuilt/linux-image) $(Q)(cd $(BIN_DIR) && $(SHA1SUM) linux-image/Image >> sha1sum-linux-image) $(Q)(cd $(BIN_DIR) && $(SHA1SUM) linux-image/rootfs.cpio >> sha1sum-linux-image) + $(Q)(cd $(BIN_DIR) && $(SHA1SUM) linux-image/simplefs.ko >> sha1sum-linux-image) + $(Q)(mv $(BIN_DIR)/sha1sum-linux-image /tmp) + $(Q)(mv $(BIN_DIR)/linux-image/Image /tmp/rv32emu-linux-image-prebuilt/linux-image) + $(Q)(mv $(BIN_DIR)/linux-image/rootfs.cpio /tmp/rv32emu-linux-image-prebuilt/linux-image) + $(Q)(mv $(BIN_DIR)/linux-image/simplefs.ko /tmp/rv32emu-linux-image-prebuilt/linux-image) else git submodule update --init $(addprefix ./tests/,$(foreach tb,$(TEST_SUITES),$(tb))) $(Q)for tb in $(TEST_SUITES); do \ diff --git a/mk/external.mk b/mk/external.mk index b4d7f68e..4924f403 100644 --- a/mk/external.mk +++ b/mk/external.mk @@ -137,6 +137,13 @@ LINUX_DATA_SHA = $(shell wget -q -O- $(LINUX_CDN_VERSION_URL)/sha256sums.asc | \ grep $(LINUX_DATA) | awk '{print $$1}') LINUX_DATA_SHA_CMD = $(SHA256SUM) +# simplefs +SIMPLEFS_VERSION = rel2025.0 +SIMPLEFS_DATA = /tmp/simplefs +SIMPLEFS_DATA_URL = git clone https://github.com/sysprog21/simplefs $(SIMPLEFS_DATA) -b $(SIMPLEFS_VERSION) --depth=1 +SIMPLEFS_DATA_SHA = 863936f72e0781b240c5ec4574510c57f0394b99 +SIMPLEFS_DATA_SHA_CMD = $(SHA1SUM) + define download-extract-verify $($(T)_DATA): $(Q)$$(call prologue,$$@) @@ -146,5 +153,5 @@ $($(T)_DATA): $(Q)$$(call epilogue,$(notdir $($(T)_DATA_URL)),$(SHA_FILE1),$(SHA_FILE2)) endef -EXTERNAL_DATA = DOOM QUAKE TIMIDITY BUILDROOT LINUX +EXTERNAL_DATA = DOOM QUAKE TIMIDITY BUILDROOT LINUX SIMPLEFS $(foreach T,$(EXTERNAL_DATA),$(eval $(download-extract-verify))) diff --git a/mk/tools.mk b/mk/tools.mk index fbef691f..c0527ed8 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -35,7 +35,7 @@ $(HIST_BIN): $(HIST_OBJS) TOOLS_BIN += $(HIST_BIN) # Build Linux image -LINUX_IMAGE_SRC = $(BUILDROOT_DATA) $(LINUX_DATA) +LINUX_IMAGE_SRC = $(BUILDROOT_DATA) $(LINUX_DATA) $(SIMPLEFS_DATA) build-linux-image: $(LINUX_IMAGE_SRC) $(Q)./tools/build-linux-image.sh $(Q)$(PRINTF) "Build done.\n" diff --git a/tools/build-linux-image.sh b/tools/build-linux-image.sh index b6ee4e20..fd42ae9c 100755 --- a/tools/build-linux-image.sh +++ b/tools/build-linux-image.sh @@ -51,5 +51,14 @@ function do_linux cp -f $SRC_DIR/linux/arch/riscv/boot/Image $OUTPUT_DIR } +function do_simplefs +{ + pushd $SRC_DIR/simplefs + ASSERT make KDIR=$SRC_DIR/linux $PARALLEL + popd + cp -f $SRC_DIR/simplefs/simplefs.ko $OUTPUT_DIR +} + do_buildroot && OK do_linux && OK +do_simplefs && OK