Skip to content

Instantly share code, notes, and snippets.

@compenguy
Created April 2, 2017 17:59
Show Gist options
  • Save compenguy/f797558f7ec692ca3de71f59fe678a87 to your computer and use it in GitHub Desktop.
Save compenguy/f797558f7ec692ca3de71f59fe678a87 to your computer and use it in GitHub Desktop.
Super-rough script to generate a UEFI-ready LEDE disk image and boot QEMU with it
#!/bin/bash
LEDE_KERNEL="${HOME}/Downloads/lede-17.01.0-r3205-59508e3-x86-64-vmlinuz"
LEDE_KERNEL_URL="https://downloads.lede-project.org/releases/17.01.0/targets/x86/64/lede-17.01.0-r3205-59508e3-x86-64-vmlinuz"
LEDE_ROOT_IMG_GZ="${HOME}/Downloads/lede-17.01.0-r3205-59508e3-x86-64-combined-ext4.img.gz"
LEDE_ROOT_IMG=""
LEDE_ROOT_IMG_URL="https://downloads.lede-project.org/releases/17.01.0/targets/x86/64/lede-17.01.0-r3205-59508e3-x86-64-generic-rootfs.tar.gz"
QEMU_RAM_MEG="1024"
QEMU_DISK_IMG="${HOME}/sda.img"
QEMU_DISK_SIZE_MiB="1024"
QEMU_UEFI_IMG="/usr/share/ovmf/OVMF.fd"
QEMU_EXTRA_FLAGS="-net none -snapshot"
MOUNT_ROOT="/mnt"
LOOP=""
function get_stack () {
STACK=""
local i message="${1:-""}"
local stack_size=${#FUNCNAME[@]}
# to avoid noise we start with 1 to skip the get_stack function
for (( i=1; i<$stack_size; i++ )); do
local func="${FUNCNAME[$i]}"
[ x$func = x ] && func=MAIN
local linen="${BASH_LINENO[$(( i - 1 ))]}"
local src="${BASH_SOURCE[$i]}"
[ x"$src" = x ] && src=non_file_source
STACK+=$'\n'" at: "$func" "$src" "$linen
done
STACK="${message}${STACK}"
}
function cleanup_before_exit () {
local rv=$?
if [ ${rv} -ne 0 ]; then
get_stack "Failed executing"
error "${STACK}"
info "Check ${LOG_FILE} for details."
fi
deinit
info "Clean up completed"
}
trap cleanup_before_exit EXIT
function prompt() {
local msg="$1"
local var="$2"
local default="${3:-${!var}}"
while true; do
# prompt user for input
if [ -n "${default}" ]; then
read -p "${msg} [${default}] " ${var}
else
read -p "${msg} " ${var}
fi
# verify input, fall back on default if available
if [ -z "${!var}" ] && [ -n "${default}" ]; then
eval "${var}=${default}"
fi
if [ -n "${var}" ]; then
break
fi
done
}
function configure() {
prompt "Path to kernel:" LEDE_KERNEL
if [ ! -f "${LEDE_KERNEL}" ]; then
echo "Specified kernel does not exist."
prompt "Kernel download url:" LEDE_KERNEL_URL
wget "${LEDE_KERNEL_URL}" --output-document "${LEDE_KERNEL}"
fi
if [ ! -f "${LEDE_KERNEL}" ]; then
echo "Requested kernel doesn't exist."
exit 1
fi
prompt "Path to compressed rootfs:" LEDE_ROOT_IMG_GZ
if [ ! -f "${LEDE_ROOT_IMG_GZ}" ]; then
echo "Specified kernel does not exist."
prompt "LEDE rootfs download url:" LEDE_ROOT_IMG_URL
wget "${LEDE_ROOT_IMG_URL}" --output-document "${LEDE_ROOT_IMG_GZ}"
fi
if [ ! -f "${LEDE_ROOT_IMG_GZ}" ]; then
echo "Requested rootfs doesn't exist."
exit 1
fi
prompt "QEMU RAM size:" QEMU_RAM_MEG
prompt "QEMU disk size:" QEMU_DISK_SIZE_MiB
if [ ! -f "${QEMU_UEFI_IMG}" ]; then
echo "UEFI image file doesn't exist (${QEMU_UEFI_IMG}). Install 'ovmf' and retry."
exit 1
fi
prompt "Local mount point:" MOUNT_ROOT
}
function init() {
echo "Creating QEMU disk image..."
dd if=/dev/zero of="${QEMU_DISK_IMG}" bs=1MiB count=${QEMU_DISK_SIZE_MiB}
echo "Mounting disk image..."
LOOP=$(sudo losetup --find --show "${QEMU_DISK_IMG}")
if [ $? -ne 0 ] || [ -z "${LOOP}" ]; then
echo "Unable to set up loopback device."
exit 1
fi
echo "Partitioning QEMU disk image..."
echo "Currently, the next bits are broken,"
echo "and we don't want to mess up your system"
exit 1
sudo parted "${LOOP}" mkpart ESP fat32 1MiB 257MiB
sudo parted "${LOOP}" set 1 boot on
sudo parted "${LOOP}" mkpart primary ext4 257MiB 100%
sudo kpartx -v -a "${QEMU_DISK_IMG}"
if [ $? -ne 0 ]; then
echo "Unable to mount partitioned disk image."
exit 1
fi
echo "Formatting QEMU disk image..."
sudo mkfs.vfat -F 32 -n BOOT /dev/mapper/${LOOP}p1
sudo mkfs.ext4 -L ROOT /dev/mapper/${LOOP}p2
echo "Mounting QEMU BOOT partition..."
sudo mkdir "${MOUNT_ROOT}/qemuboot"
sudo mount /dev/mapper/${LOOP}p1 "${MOUNT_ROOT}/qemuboot"
echo "Populating QEMU BOOT partition..."
sudo mkdir -p "${MOUNT_ROOT}/qemuboot/EFI/BOOT"
sudo cp "${LEDE_KERNEL}" "${MOUNT_ROOT}/qemuboot/EFI/BOOT/bootx64.efi"
echo -n "fs0:\\EFI\\BOOT\\bootx64.efi root=sda2 rootfstype=ext4 rootwait console=tty0 console=ttyS0,115200n8 earlyprintk=serial,ttyS0,115200,keep noinitrd verbose" | sudo tee --append "${MOUNT_ROOT}/qemuboot/startup.nsh"
echo "Mounting QEMU ROOT partition..."
sudo mkdir "${MOUNT_ROOT}/qemuroot"
sudo mount /dev/mapper/${LOOP}p2 "${MOUNT_ROOT}/qemuroot"
echo "Decompressing LEDE root image..."
gunzip "${LEDE_ROOT_IMG_GZ}"
LEDE_ROOT_IMG="${LEDE_ROOT_IMG_GZ%%.*}"
echo "Mounting LEDE root image..."
sudo mkdir "${MOUNT_ROOT}/lederoot"
sudo mount -o loop "${LEDE_ROOT_IMG}" "${MOUNT_ROOT}/lederoot"
echo "Copying files from LEDE root to QEMU disk image..."
sudo rsync -avxHAWX --numeric-ids --info=progress2 "${MOUNT_ROOT}/lederoot/" "${MOUNT_ROOT}/qemuroot/"
}
function deinit() {
if [ -d "${MOUNT_ROOT}/qemuboot" ]; then
echo "Unmounting QEMU boot image..."
sudo umount "${MOUNT_ROOT}/qemuboot"
sudo rmdir "${MOUNT_ROOT}/qemuboot"
fi
if [ -d "${MOUNT_ROOT}/qemuroot" ]; then
echo "Unmounting QEMU root image..."
sudo umount "${MOUNT_ROOT}/qemuroot"
sudo rmdir "${MOUNT_ROOT}/qemuroot"
fi
if [ -d "${MOUNT_ROOT}/lederoot" ]; then
echo "Unmounting lede root image..."
sudo umount "${MOUNT_ROOT}/lederoot"
sudo rmdir "${MOUNT_ROOT}/lederoot"
fi
if [ -n "${LOOP}" ]; then
echo "Cleaning up loopback device ${LOOP}..."
sudo kpartx -v -d "${QEMU_DISK_IMG}"
sudo losetup --detach "${LOOP}"
fi
}
function start() {
echo qemu-system-x86_64 -m ${QEMU_RAM_MEG} -hda "${QEMU_DISK_IMG}" --bios "${QEMU_UEFI_IMG}" ${EXTRA_FLAGS}
}
configure
init
start
deini
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment