diff --git a/.gitignore b/.gitignore index 30f20ed..58e9e7e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ semu *.dtb Image ext4.img +rootfs.cpio diff --git a/Makefile b/Makefile index c940bc5..171f7fc 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ ext4.img: check: $(BIN) minimal.dtb $(KERNEL_DATA) $(DISKIMG_FILE) @$(call notice, Ready to launch Linux kernel. Please be patient.) - $(Q)./$(BIN) -k $(KERNEL_DATA) -b minimal.dtb $(OPTS) + $(Q)./$(BIN) -k $(KERNEL_DATA) -b minimal.dtb -i rootfs.cpio $(OPTS) build-image: scripts/build-image.sh diff --git a/README.md b/README.md index 9b78d00..1cff54e 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,12 @@ $ make build-image ## Usage ``` -./semu -k linux-image [-b dtb-file] [-d disk-image] +./semu -k linux-image [-b dtb-file] [-i initrd-image] [-d disk-image] ``` * `linux-image` is the path to the Linux kernel `Image`. * `dtb-file` is optional, as it specifies the user-specified device tree blob. +* `initrd-image` is optional, as it specifies the user-specified init RAM disk image. * `disk-image` is optional, as it specifies the path of a disk image in ext4 file system for the virtio-blk device. ## License diff --git a/configs/linux.config b/configs/linux.config index 844ed9c..d079efb 100644 --- a/configs/linux.config +++ b/configs/linux.config @@ -123,9 +123,7 @@ CONFIG_CC_NO_ARRAY_BOUNDS=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="../buildroot/output/images/rootfs.cpio" -CONFIG_INITRAMFS_ROOT_UID=0 -CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_INITRAMFS_SOURCE="" # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set @@ -133,8 +131,6 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_LZO is not set # CONFIG_RD_LZ4 is not set CONFIG_RD_ZSTD=y -CONFIG_INITRAMFS_COMPRESSION_ZSTD=y -# CONFIG_INITRAMFS_COMPRESSION_NONE is not set # CONFIG_BOOT_CONFIG is not set CONFIG_INITRAMFS_PRESERVE_MTIME=y # CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set diff --git a/device.h b/device.h index 55d05b3..fd7f07b 100644 --- a/device.h +++ b/device.h @@ -6,6 +6,8 @@ /* RAM */ #define RAM_SIZE (512 * 1024 * 1024) +#define DTB_SIZE (1 * 1024 * 1024) +#define INITRD_SIZE (8 * 1024 * 1024) void ram_read(vm_t *core, uint32_t *mem, diff --git a/main.c b/main.c index 86cdb33..fa94e23 100644 --- a/main.c +++ b/main.c @@ -291,28 +291,30 @@ static void map_file(char **ram_loc, const char *name) static void usage(const char *execpath) { - fprintf(stderr, "Usage: %s -k linux-image [-b dtb] [-d disk-image]\n", - execpath); + fprintf( + stderr, + "Usage: %s -k linux-image [-b dtb] [-i initrd-image] [-d disk-image]\n", + execpath); } static void handle_options(int argc, char **argv, char **kernel_file, char **dtb_file, + char **initrd_file, char **disk_file) { - *kernel_file = *dtb_file = *disk_file = NULL; + *kernel_file = *dtb_file = *initrd_file = *disk_file = NULL; int optidx = 0; struct option opts[] = { - {"kernel", 1, NULL, 'k'}, - {"dtb", 1, NULL, 'b'}, - {"disk", 1, NULL, 'd'}, + {"kernel", 1, NULL, 'k'}, {"dtb", 1, NULL, 'b'}, + {"initrd", 1, NULL, 'i'}, {"disk", 1, NULL, 'd'}, {"help", 0, NULL, 'h'}, }; int c; - while ((c = getopt_long(argc, argv, "k:b:d:h", opts, &optidx)) != -1) { + while ((c = getopt_long(argc, argv, "k:b:i:d:h", opts, &optidx)) != -1) { switch (c) { case 'k': *kernel_file = optarg; @@ -320,6 +322,9 @@ static void handle_options(int argc, case 'b': *dtb_file = optarg; break; + case 'i': + *initrd_file = optarg; + break; case 'd': *disk_file = optarg; break; @@ -347,8 +352,10 @@ static int semu_start(int argc, char **argv) { char *kernel_file; char *dtb_file; + char *initrd_file; char *disk_file; - handle_options(argc, argv, &kernel_file, &dtb_file, &disk_file); + handle_options(argc, argv, &kernel_file, &dtb_file, &initrd_file, + &disk_file); /* Initialize the emulator */ emu_state_t emu; @@ -371,13 +378,27 @@ static int semu_start(int argc, char **argv) } assert(!(((uintptr_t) emu.ram) & 0b11)); + /* *-----------------------------------------* + * | Memory layout | + * *----------------*----------------*-------* + * | kernel image | initrd image | dtb | + * *----------------*----------------*-------* + */ char *ram_loc = (char *) emu.ram; /* Load Linux kernel image */ map_file(&ram_loc, kernel_file); - /* Load at last 1 MiB to prevent kernel / initrd from overwriting it */ - uint32_t dtb_addr = RAM_SIZE - 1024 * 1024; /* Device tree */ + /* Load at last 1 MiB to prevent kernel from overwriting it */ + uint32_t dtb_addr = RAM_SIZE - DTB_SIZE; /* Device tree */ ram_loc = ((char *) emu.ram) + dtb_addr; map_file(&ram_loc, dtb_file); + /* Load optional initrd image at last 8 MiB before the dtb region to + * prevent kernel from overwritting it + */ + if (initrd_file) { + uint32_t initrd_addr = dtb_addr - INITRD_SIZE; /* Init RAM disk */ + ram_loc = ((char *) emu.ram) + initrd_addr; + map_file(&ram_loc, initrd_file); + } /* Hook for unmapping files */ atexit(unmap_files); diff --git a/minimal.dts b/minimal.dts index cb7822c..f6126f1 100644 --- a/minimal.dts +++ b/minimal.dts @@ -12,6 +12,8 @@ chosen { bootargs = "earlycon console=ttyS0"; stdout-path = "serial0"; + linux,initrd-start = <0x1f700000>; /* @403 MiB (503 * 1024 * 1024) */ + linux,initrd-end = <0x1fefffff>; /* @511 MiB (511 * 1024 * 1024 - 1) */ }; cpus { diff --git a/scripts/build-image.sh b/scripts/build-image.sh index 044f39b..3d0cdd5 100755 --- a/scripts/build-image.sh +++ b/scripts/build-image.sh @@ -32,6 +32,7 @@ function do_buildroot ASSERT make olddefconfig ASSERT make $PARALLEL popd + cp -f buildroot/output/images/rootfs.cpio ./ } function do_linux