diff options
Diffstat (limited to 'content/2021-12-02-toying-with-virtio')
-rw-r--r-- | content/2021-12-02-toying-with-virtio/Dockerfile | 44 | ||||
-rw-r--r-- | content/2021-12-02-toying-with-virtio/Makefile | 57 | ||||
-rwxr-xr-x | content/2021-12-02-toying-with-virtio/build_initramfs.sh | 90 | ||||
-rwxr-xr-x | content/2021-12-02-toying-with-virtio/build_kernel.sh | 67 |
4 files changed, 258 insertions, 0 deletions
diff --git a/content/2021-12-02-toying-with-virtio/Dockerfile b/content/2021-12-02-toying-with-virtio/Dockerfile new file mode 100644 index 0000000..f892fef --- /dev/null +++ b/content/2021-12-02-toying-with-virtio/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:20.04 +MAINTAINER Johannes Stoelp <johannes.stoelp@gmail.edu> + +ARG UID + +RUN apt update \ + && DEBIAN_FRONTEND=noninteractive \ + apt install \ + --yes \ + --no-install-recommends \ + # Download & unpack. + wget \ + ca-certificates \ + xz-utils \ + # Build tools & deps (kernel). + make \ + bc \ + gcc g++ \ + flex bison \ + libelf-dev \ + libncurses-dev \ + # Build tools & deps (initrd). + cpio \ + # Run & debug. + qemu-system-x86 \ + # Convenience. + sudo \ + telnet \ + ripgrep \ + fd-find \ + neovim \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Allow 'user' to use sudo without password. +# Convenience in case we want to install some packages in the container later. +RUN echo "user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/user + +# Create user with the UID passed during docker build. +RUN useradd --create-home --home-dir /home/user --uid $UID --shell /bin/bash user +# Start container with user. +USER user +# Change default working dir. +WORKDIR /develop diff --git a/content/2021-12-02-toying-with-virtio/Makefile b/content/2021-12-02-toying-with-virtio/Makefile new file mode 100644 index 0000000..4009862 --- /dev/null +++ b/content/2021-12-02-toying-with-virtio/Makefile @@ -0,0 +1,57 @@ +VER := 5.15.6 + +all: kernel init + +help: + @echo "Build targets:" + @echo "* init - Build busybox based initramfs." + @echo "* kernel - Build minimal linux kernel." + @echo " clean - Cleanup downloads & builds." + @echo "" + @echo "Run targets:" + @echo " run - Boot into the initramfs (qemu)." + @echo " vcon - Attach to guest virtio console." + @echo " This needs an already running guest VM and must be" + @echo " executed in the same domain as the 'run' target" + @echo " (docker or host)." + @echo " Login as 'root' user, no passwd required." + @echo "" + @echo "Docker targets:" + @echo " docker - Build and start the docker container." + @echo " attach - Start an additional bash in the container." + @echo " This needs an already running container." + +kernel: + ./build_kernel.sh + +init: + ./build_initramfs.sh + +run: + qemu-system-x86_64 \ + -nographic \ + -cpu host \ + -enable-kvm \ + -kernel ./linux-$(VER)/arch/x86/boot/bzImage \ + -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/ram0 ro" \ + -initrd ./initramfs.cpio.gz \ + -device virtio-serial-pci \ + -device virtconsole,chardev=vcon,name=console.0 \ + -chardev socket,id=vcon,ipv4=on,host=localhost,port=2222,server,telnet=on,wait=off \ + -drive format=raw,if=virtio,file=rootfs.ext2 \ + -nic user,model=virtio-net-pci + +vcon: + telnet -4 localhost 2222 + +clean: + $(RM) initramfs.cpio.gz + $(RM) -r busybox-* + $(RM) -r linux-$(VER)* + +docker: + DOCKER_BUILDKIT=1 docker build --build-arg UID=$(shell id -u) -t virtio-dev . + docker run --name virtio -it --rm -v $(PWD):/develop --device /dev/kvm virtio-dev + +attach: + docker exec -it virtio bash diff --git a/content/2021-12-02-toying-with-virtio/build_initramfs.sh b/content/2021-12-02-toying-with-virtio/build_initramfs.sh new file mode 100755 index 0000000..c30fa5e --- /dev/null +++ b/content/2021-12-02-toying-with-virtio/build_initramfs.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +set -e + +BUSYBOX=busybox-1.34.1 +INITRAMFS=$PWD/initramfs.cpio.gz + +## Build busybox (static). + +test -f $BUSYBOX.tar.bz2 || wget -nc https://busybox.net/downloads/$BUSYBOX.tar.bz2 +test -d $BUSYBOX || tar xf $BUSYBOX.tar.bz2 + +cd $BUSYBOX +make defconfig +sed -i 's/[# ]*CONFIG_STATIC[ =].*/CONFIG_STATIC=y/' .config +make -j$(nproc) busybox +make install + +## Create initramfs. + +cd _install + +# 1. Create initramfs folder structure. + +mkdir -p bin sbin etc/init.d proc sys usr/bin usr/sbin dev mnt + +# 2. Prepare init. + +# By default, initramfs executes /init. +# Optionally change with rdinit= kernel parameter. +ln -sfn sbin/init init + +cat <<EOF > etc/inittab +# Initialization after boot. +::sysinit:/etc/init.d/rcS + +# Shell on console after user presses key. +::askfirst:/bin/cttyhack /bin/sh -l + +# Spawn getty on first virtio console. +::respawn:/sbin/getty hvc0 9600 vt100 +EOF + +cat <<EOF > etc/init.d/rcS +#!/bin/sh + +# Mount devtmpfs, which automatically populates /dev with devices nodes. +# So no mknod for our experiments :} +mount -t devtmpfs none /dev + +# Mount procfs and sysfs. +mount -t proc none /proc +mount -t sysfs none /sys + +# Set hostname. +hostname virtio-box +EOF +chmod +x etc/init.d/rcS + +cat <<EOF > etc/profile +export PS1="\[\e[31m\e[1m\]\u@\h\[\e[0m\] \w # " +EOF + +# 3. Create minimal passwd db with 'root' user and password '1234'. +# Mainly used for login on virtual console in this experiments. +echo "root:x:0:0:root:/:/bin/sh" > etc/passwd +echo "root:$(openssl passwd -crypt 1234):0::::::" > etc/shadow + +# 4. Create minimal setup for basic networking. + +# Virtul DNS from qemu user network. +echo "nameserver 10.0.2.3" > etc/resolv.conf + +# Assign static IP address, bring-up interface and define default route. +cat <<EOF >> etc/init.d/rcS +# Assign static IP address to eth0 interface. +ip addr add 10.0.2.15/24 dev eth0 + +# Bring up eth0 interface. +ip link set dev eth0 up + +# Add default route via the host (qemu user networking exposes host at this +# address by default). +ip route add default via 10.0.2.2 +EOF + +# 5. Created cpio compressed initramfs. +find . -print0 \ + | cpio --null -ov --format=newc \ + | gzip -9 > $INITRAMFS diff --git a/content/2021-12-02-toying-with-virtio/build_kernel.sh b/content/2021-12-02-toying-with-virtio/build_kernel.sh new file mode 100755 index 0000000..b219b57 --- /dev/null +++ b/content/2021-12-02-toying-with-virtio/build_kernel.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -e + +LINUX=linux-5.15.6 + +test -f $LINUX.tar.xz || wget -nc https://cdn.kernel.org/pub/linux/kernel/v5.x/$LINUX.tar.xz +test -d $LINUX || tar xf $LINUX.tar.xz + +cd $LINUX + +cat <<EOF > kernel_fragment.config +# 64bit kernel. +CONFIG_64BIT=y +# Enable support for cpio compressed initramfs (gzip). +CONFIG_BLK_DEV_INITRD=y +CONFIG_RD_GZIP=y +# Support for ELF and #! binary format. +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_SCRIPT=y +# Enable devtmpfs (can automatically populate /dev). +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# Enable tty & console. +CONFIG_TTY=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# Enable proc & sys pseudo fs. +CONFIG_PROC_FS=y +CONFIG_SYSFS=y + +# Enable support for virtio pci. +CONFIG_PCI=y +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_PCI=y + +# Enable virtio console driver. +CONFIG_VIRTIO_CONSOLE=y + +# Enable support for block devices. +CONFIG_BLK_DEV=y + +# Enable virtio blk driver. +CONFIG_VIRTIO_BLK=y + +# Enable support for ext2 filesystems. +CONFIG_EXT2_FS=y + +# Enable general networking support. +CONFIG_NET=y + +# Enable support for TCP/IP. +CONFIG_INET=y + +# Enable support for network devices. +CONFIG_NETDEVICES=y + +# Enable networking core drivers. +CONFIG_NET_CORE=y + +# Enable virtio net driver. +CONFIG_VIRTIO_NET=y +EOF + +make tinyconfig +./scripts/kconfig/merge_config.sh -n ./kernel_fragment.config +make -j$(nproc) |