Site logo
Stories around the Genode Operating System RSS feed
Sebastian Sumpf avatar

Building a Linux VM image for ARMv8


This brief article summarizes the steps necessary to build a runnable Linux kernel and initrd disk image that can be executed on top of Genode's custom VMM for i.MX8 platforms.

Prerequisites

Building the Linux kernel

  1. Get and extract the sources

     wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.53.tar.xz
    
     tar -xJF linux-4.19.53.tar.xz
     cd linux-4.19.53
    
  2. Configure the kernel

     make O=../build-linux-aarch64 ARCH=arm64 CROSS_COMPILE=/usr/local/genode-gcc/bin/genode-aarch64- defconfig
    
  3. Build the kernel

     make O=../build-linux-aarch64 ARCH=arm64 CROSS_COMPILE=/usr/local/genode-gcc/bin/genode-aarch64-
    
  4. The kernel image can is located at build-linux-aarch64/arch/arm64/boot/Image

Building an initrd using BusyBox

  1. Download and extract BusyBox

     wget https://busybox.net/downloads/busybox-1.29.3.tar.bz2
    
     tar xjf busybox-1.29.3.tar.bz2
     mkdir build-busybox-aarch64
     cd busybox-1.29.3
    
  2. Configure BusyBox

     make O=../build-busybox-aarch64 defconfig
     make O=../build-busybox-aarch64 menuconfig
    
     # check this setting in the menu
     [*] Setting ->  Build static binary (no shared libs)
    
  3. Compile BusyBox with the installed cross-compile tool chain

     cd ../build-busybox-aarch64
     make CROSS_COMPILE=<path-to-tool-chain>/aarch64--uclibc--stable-2018.11-1/bin/aarch64-linux- install -j6
    
  4. Useful setups for the ram disk

     cd <busbox-build-dir>/_install
    
    
    • create fstab

     <editor> etc/fstab
     none /proc  proc   defaults 0 0
     none /sys   sysfs  defaults 0 0
    
    • DNS resolution

     echo "nameserver 8.8.8.8" > etc/resolv.conf
    
    • Run level script using mdev

     <editor> etc/init.d/rcS
    
     #/bin/sh
    
     mkdir -p /proc
     mkdir -p /sys
     mkdir -p /var/shm
     mkdir -p /var/run
     mkdir -p /var/tmp
     mkdir -p /tmp
     mkdir -p /home/tc
     mkdir -p /root
     mkdir -p /dev
    
     /bin/mount -t tmpfs mdev /dev
     mkdir /dev/pts
     /bin/mount -t devpts devpts /dev/pts
    
     echo "Mount everything ${1}"
     /bin/mount -a
    
     echo /sbin/mdev > /proc/sys/kernel/hotplug
     /sbin/mdev -s
     echo "Finished"
     /bin/sh
    
  5. Create the initial ram disk using cpio

     find . | cpio -H newc -o | gzip > ../initrd
    
  6. Adjust the device tree information of Genode's VMM

     <editor> genode/repos/os/src/server/vmm/spec/arm_v8/virt.dts
    
  7. Look for the chosen entry

    chosen {
      bootargs = "rdinit=/bin/sh";
      linux,initrd-start = <0x42000000>;
      linux,initrd-end   = <0x42113b86>;
      stdout-path = "/pl011@9000000";
    };
    
  8. Adjust bootargs to use init

     bootargs = "init=/sbin/init";
    
  9. Adjust the size of the ram disk

     ls -l initrd
    
     -rw-r--r-- 1 user user 697657 Jan 29 17:03 initrd
    
    
  10. Convert size to Hex (0xaa539) and adjust initrd-end accordingly

     linux,initrd-end = <0x420aa539>;
    
  11. Compile the device tree

     dtc <Genode-src>/repos/os/src/server/vmm/spec/arm_v8/virt.dts > <Genode-build-directory>/arm_v8a/bin/dtc
    

Have fun!