diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc78feb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +rootfs.cpio diff --git a/boot-qemu-help.txt b/boot-qemu-help.txt new file mode 100644 index 0000000..11b13d9 --- /dev/null +++ b/boot-qemu-help.txt @@ -0,0 +1,43 @@ +Usage: ./boot-qemu.sh + +Script description: Boots a Linux kernel in QEMU. + +Required parameters: + -a | --arch | --architecture: + The architecture to boot. Possible values are: + * arm32_v5 + * arm32_v6 + * arm32_v7 + * arm64 + * mips + * mipsel + * ppc32 + * ppc64 + * ppc64le + * x86_64 + + -k | --kbuild-folder: + The kernel build folder, as an absolute path or relative path + from wherever the script is being run. This is wherever the + compiled vmlinux image lives, not the architecture's boot folder. + +Optional parameters: + -d | --debug: + Invokes 'set -x' for debugging the script. + + -h | --help: + Prints this message then exits. + + -i | --interactive | --shell: + By default, the rootfs images in this repo just boots the kernel, + print the version string, then exit. If you would like to actually + interact with the machine, this option passes 'rdinit=/bin/sh' to + the kernel command line so that you are thrown into an interactive + shell. When this is set, there is no timeout so any value supplied + via the script's -t option is ignored. + + -t | --timeout: + By default, the timeout command waits 3 minutes before killing the + QEMU machine. Depending on the power of the host machine, this might + not be long enough for a kernel to boot so this allows that timeout + to be configured. Takes the value passed to timeout (e.g. 30s or 4m). diff --git a/boot-qemu.sh b/boot-qemu.sh new file mode 100755 index 0000000..e75056f --- /dev/null +++ b/boot-qemu.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash + +# Root of the repo +BASE=$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd) + + +# Prints an error message in bold red then exits +function die() { + printf "\n\033[01;31m%s\033[0m\n" "${1}" + exit 1 +} + + +# Check that a binary is found +function checkbin() { + command -v "${1}" &>/dev/null || die "${1} could not be found, please install it!" +} + + +# Parse inputs to the script +function parse_parameters() { + while (( ${#} )); do + case ${1} in + -a|--arch|--architecture) + shift + case ${1} in + arm32_v5|arm32_v6|arm32_v7|arm64|mips|mipsel|ppc32|ppc64|ppc64le|x86_64) ARCH=${1} ;; + *) die "Invalid --arch value '${1}'" ;; + esac ;; + + -d|--debug) + set -x ;; + + -h|--help) + echo + cat "${BASE}"/boot-qemu-help.txt + echo + exit 0 ;; + + -i|--interactive|--shell) + INTERACTIVE=true ;; + + -k|--kbuild-folder) + shift && KBUILD_DIR=${1} ;; + + -t|--timeout) + shift && TIMEOUT=${1} ;; + + *) + die "Invalid parameter '${1}'" ;; + esac + shift + done +} + + +# Sanity check parameters and required tools +function sanity_check() { + # Kernel build folder and architecture are required paramters + [[ -z ${ARCH} ]] && die "Architecture ('-a') is required but not specified!" + [[ -z ${KBUILD_DIR} ]] && die "Kernel build folder ('-k') is required but not specified!" + + # KBUILD_DIR could be a relative path; turn it into an absolute one with readlink + KBUILD_DIR=$(readlink -f "${KBUILD_DIR}") + + # Let the user know if the kernel build folder does not exist + [[ -d ${KBUILD_DIR} ]] || die "${KBUILD_DIR} does not exist!" + + # Make sure zstd is install + checkbin zstd +} + + +# Decompress rootfs images +function decomp_rootfs() { + # All arm32_* options share the same rootfs, under images/arm + [[ ${ARCH} =~ arm32 ]] && ARCH_RTFS_DIR=arm + + IMAGES_DIR=${BASE}/images/${ARCH_RTFS_DIR:-${ARCH}} + ROOTFS=${IMAGES_DIR}/rootfs.cpio + + rm -rf "${ROOTFS}" + zstd -d "${ROOTFS}".zst -o "${ROOTFS}" +} + + +# Boot QEMU +function setup_qemu_args() { + if ${INTERACTIVE:=false}; then + RDINIT=" rdinit=/bin/sh" + APPEND_RDINIT=( -append "${RDINIT}" ) + fi + + case ${ARCH} in + arm32_v5) + ARCH=arm + QEMU_ARCH_ARGS=( "${APPEND_RDINIT[@]}" + -dtb "${KBUILD_DIR}"/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dtb + -machine palmetto-bmc + -no-reboot ) + QEMU=( qemu-system-arm ) ;; + + arm32_v6) + ARCH=arm + QEMU_ARCH_ARGS=( "${APPEND_RDINIT[@]}" + -dtb "${KBUILD_DIR}"/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dtb + -machine romulus-bmc + -no-reboot ) + QEMU=( qemu-system-arm ) ;; + + arm32_v7) + ARCH=arm + QEMU_ARCH_ARGS=( -append "console=ttyAMA0${RDINIT}" + -machine virt + -no-reboot ) + QEMU=( qemu-system-arm ) ;; + + arm64) + KIMAGE=Image.gz + QEMU_ARCH_ARGS=( -append "console=ttyAMA0${RDINIT}" + -cpu cortex-a57 + -machine virt ) + QEMU=( qemu-system-aarch64 ) ;; + + mips|mipsel) + KIMAGE=vmlinux + QEMU_ARCH_ARGS=( "${APPEND_RDINIT[@]}" + -cpu 24Kf + -machine malta ) + QEMU=( qemu-system-"${ARCH}" ) + ARCH=mips ;; + + ppc32) + ARCH=powerpc + QEMU_ARCH_ARGS=( -append "console=ttyS0${RDINIT}" + -machine bamboo + -no-reboot ) + QEMU_RAM=128m + QEMU=( qemu-system-ppc ) ;; + + ppc64) + ARCH=powerpc + KIMAGE=vmlinux + QEMU_ARCH_ARGS=( "${APPEND_RDINIT[@]}" + -machine pseries + -vga none ) + QEMU_RAM=1G + QEMU=( qemu-system-ppc64 ) ;; + + ppc64le) + ARCH=powerpc + KIMAGE=zImage.epapr + QEMU_ARCH_ARGS=( "${APPEND_RDINIT[@]}" + -device "ipmi-bmc-sim,id=bmc0" + -device "isa-ipmi-bt,bmc=bmc0,irq=10" + -L "${IMAGES_DIR}/" -bios skiboot.lid + -machine powernv ) + QEMU_RAM=2G + QEMU=( qemu-system-ppc64 ) ;; + + x86_64) + KIMAGE=bzImage + QEMU_ARCH_ARGS=( -append "console=ttyS0${RDINIT}" ) + # Use KVM if the processor supports it (first part) and the KVM module is loaded (second part) + [[ $(grep -c -E 'vmx|svm' /proc/cpuinfo) -gt 0 && $(lsmod 2>/dev/null | grep -c kvm) -gt 0 ]] && \ + QEMU_ARCH_ARGS=( "${QEMU_ARCH_ARGS[@]}" -cpu host -d "unimp,guest_errors" -enable-kvm ) + QEMU=( qemu-system-x86_64 ) ;; + esac + checkbin "${QEMU[*]}" + + [[ ${KIMAGE:=zImage} = "vmlinux" ]] || BOOT_DIR=arch/${ARCH}/boot/ + KERNEL=${KBUILD_DIR}/${BOOT_DIR}${KIMAGE} + [[ -f ${KERNEL} ]] || die "${KERNEL} does not exist!" +} + + +# Invoke QEMU +function invoke_qemu() { + ${INTERACTIVE} || QEMU=( timeout "${TIMEOUT:=3m}" unbuffer "${QEMU[@]}" ) + + set -x + "${QEMU[@]}" \ + "${QEMU_ARCH_ARGS[@]}" \ + -display none \ + -initrd "${ROOTFS}" \ + -kernel "${KERNEL}" \ + -m "${QEMU_RAM:=512m}" \ + -serial mon:stdio + RET=${?} + set +x + + return ${RET} +} + + +parse_parameters "${@}" +sanity_check +decomp_rootfs +setup_qemu_args +invoke_qemu diff --git a/buildroot/buildroot-2019.02.3.tar.gz.sha256 b/buildroot/buildroot-2019.02.3.tar.gz.sha256 deleted file mode 100644 index e160728..0000000 --- a/buildroot/buildroot-2019.02.3.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -31a0dd7f5df75d20f6b74f0684918b643e5bf08d87dd5f9f02525852eecccf95 buildroot-2019.02.3.tar.gz diff --git a/buildroot/buildroot-2020.02.tar.gz.sha256 b/buildroot/buildroot-2020.02.tar.gz.sha256 new file mode 100644 index 0000000..d63ffaf --- /dev/null +++ b/buildroot/buildroot-2020.02.tar.gz.sha256 @@ -0,0 +1 @@ +d1fa8ee1a3a79d42266db41e470e8d31075de0ebd36bc9b424648c4d100c4105 buildroot-2020.02.tar.gz diff --git a/buildroot/rebuild.sh b/buildroot/rebuild.sh index d40b2be..9d3aa64 100755 --- a/buildroot/rebuild.sh +++ b/buildroot/rebuild.sh @@ -1,15 +1,18 @@ #!/usr/bin/env bash # Takes a list of architectures to build images for as the parameter +# Prints an error message in bold red then exits +function die() { + printf "\n\033[01;31m%s\033[0m\n" "${1}" + exit 1 +} + function download_br() { mkdir -p src TARBALL=buildroot-${BUILDROOT_VERSION}.tar.gz rm -f "${TARBALL}" curl -LO https://buildroot.org/downloads/"${TARBALL}" - if ! sha256sum --quiet -c "${TARBALL}".sha256; then - echo "Downloaded tarball's hash does not match known good one! Please try redownloading." - exit 1 - fi + sha256sum --quiet -c "${TARBALL}".sha256 || die "Downloaded tarball's hash does not match known good one! Please try redownloading." tar -xzf "${TARBALL}" -C src --strip-components=1 rm -f "${TARBALL}" } @@ -20,19 +23,23 @@ set -u # Move into the folder that contains this script cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" || exit 1 +# Make sure the user has zstd installed +command -v zstd &>/dev/null || die "zstd could not be found on your system, please install it!" + # Generate list of configs to build CONFIGS=() +[[ ${#} -eq 0 ]] && die "Please specify the configs that you want to build as parameters to this script!" while (( ${#} )); do case ${1} in all) for CONFIG in *.config; do CONFIGS+=( "../${CONFIG}" ); done ;; arm64|arm|mips|mipsel|ppc32|ppc64|ppc64le|x86_64) CONFIGS+=( "../${1}.config" ) ;; - *) echo "Unknown parameter '${1}', exiting!"; exit 1 ;; + *) die "Unknown parameter '${1}', exiting!" ;; esac shift done -# Download latest buildroot release -BUILDROOT_VERSION=2019.02.3 +# Download latest LTS buildroot release +BUILDROOT_VERSION=2020.02 if [[ -d src ]]; then if [[ $(cd src && make print-version | cut -d - -f 1 2>/dev/null) != "${BUILDROOT_VERSION}" ]]; then rm -rf src @@ -70,10 +77,7 @@ for CONFIG in "${CONFIGS[@]}"; do # Make sure images exist before moving them IMAGES=( "output/images/rootfs.cpio" ) for IMAGE in "${IMAGES[@]}"; do - if [[ ! -f ${IMAGE} ]]; then - echo "${IMAGE} could not be found! Did the build error?" - exit 1 - fi - cp -v "${IMAGE}" "${IMAGES_FOLDER}" + [[ -f ${IMAGE} ]] || die "${IMAGE} could not be found! Did the build error?" + zstd -19 "${IMAGE}" -o "${IMAGES_FOLDER}/${IMAGE##*/}.zst" || die "Compressing ${IMAGE##*/} failed!" done done diff --git a/images/arm/rootfs.cpio.zst b/images/arm/rootfs.cpio.zst new file mode 100644 index 0000000..fc3cd55 Binary files /dev/null and b/images/arm/rootfs.cpio.zst differ diff --git a/images/arm64/rootfs.cpio.zst b/images/arm64/rootfs.cpio.zst new file mode 100644 index 0000000..10e2de9 Binary files /dev/null and b/images/arm64/rootfs.cpio.zst differ diff --git a/images/mips/rootfs.cpio.zst b/images/mips/rootfs.cpio.zst new file mode 100644 index 0000000..66d5c9e Binary files /dev/null and b/images/mips/rootfs.cpio.zst differ diff --git a/images/mipsel/rootfs.cpio.zst b/images/mipsel/rootfs.cpio.zst new file mode 100644 index 0000000..45188cb Binary files /dev/null and b/images/mipsel/rootfs.cpio.zst differ diff --git a/images/ppc32/rootfs.cpio.zst b/images/ppc32/rootfs.cpio.zst new file mode 100644 index 0000000..3924c4c Binary files /dev/null and b/images/ppc32/rootfs.cpio.zst differ diff --git a/images/ppc64/rootfs.cpio.zst b/images/ppc64/rootfs.cpio.zst new file mode 100644 index 0000000..88112fd Binary files /dev/null and b/images/ppc64/rootfs.cpio.zst differ diff --git a/images/ppc64le/build-skiboot.sh b/images/ppc64le/build-skiboot.sh new file mode 100755 index 0000000..c2eeaff --- /dev/null +++ b/images/ppc64le/build-skiboot.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -eux + +BASE=$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd) +VER=${1} +TMP=$(mktemp -d) + +trap 'rm -rf "${TMP}"' EXIT INT TERM + +# Build skiboot +cd "${TMP}" +curl -LSs https://github.com/open-power/skiboot/archive/v"${VER}".tar.gz | tar xzf - +cd skiboot-"${VER}" +CROSS=${CROSS:-powerpc64le-linux-gnu-} SKIBOOT_VERSION=v${VER} make -j"$(nproc)" +cp -v skiboot.lid "${BASE}" +rm -rf "${PWD}" diff --git a/images/ppc64le/rootfs.cpio.zst b/images/ppc64le/rootfs.cpio.zst new file mode 100644 index 0000000..d8e52d6 Binary files /dev/null and b/images/ppc64le/rootfs.cpio.zst differ diff --git a/images/ppc64le/skiboot.lid b/images/ppc64le/skiboot.lid new file mode 100644 index 0000000..ab9af55 Binary files /dev/null and b/images/ppc64le/skiboot.lid differ diff --git a/images/x86_64/rootfs.cpio.zst b/images/x86_64/rootfs.cpio.zst new file mode 100644 index 0000000..db5e802 Binary files /dev/null and b/images/x86_64/rootfs.cpio.zst differ