+# prepare VM image for usage with debootstrap {{{
+prepare_vm() {
+ if [ -z "$VIRTUAL" ] ; then
+ return 0 # be quiet by intention
+ fi
+
+ if [ -b "$TARGET" -a -n "$VMFILE" ] ; then
+ eerror "Error: specified virtual disk target ($TARGET) is an existing block device."
+ eend 1
+ bailout 1
+ fi
+ if [ ! -b "$TARGET" -a -z "$VMFILE" ] ; then
+ eerror "Error: specified virtual disk target ($TARGET) does not exist yet."
+ eend 1
+ bailout 1
+ fi
+
+ ORIG_TARGET="$TARGET" # store for later reuse
+
+ if [ -n "$VMFILE" ]; then
+ qemu-img create -f raw "${TARGET}" "${VMSIZE}"
+ fi
+ echo 4 66 | /usr/share/grml-debootstrap/bootgrub.mksh -A | dd of="$TARGET" conv=notrunc
+ dd if=/dev/zero bs=1 conv=notrunc count=64 seek=446 of="$TARGET"
+ if [ "$FIXED_DISK_IDENTIFIERS" = "yes" ] ; then
+ einfo "Adjusting disk signature to a fixed (non-random) value"
+ MBRTMPFILE=$(mktemp)
+ dd if="${TARGET}" of="${MBRTMPFILE}" bs=512 count=1
+ echo -en "\x41\x41\x41\x41\x41" | dd of="${MBRTMPFILE}" conv=notrunc seek=440 bs=1
+ dd if="${MBRTMPFILE}" of="${TARGET}" conv=notrunc
+ eend $?
+ fi
+ parted -s "${TARGET}" 'mkpart primary ext4 2M -1'
+
+ # if dm-mod isn't available then kpartx will fail with
+ # "Is device-mapper driver missing from kernel? [...]"
+ if ! kpartx -av $TARGET >/dev/null 2>&1 || ! grep -q device-mapper /proc/misc >/dev/null 2>&1 ; then
+ einfo "Device-mapper not ready yet, trying to load dm-mod module."
+ modprobe dm-mod ; eend $?
+ fi
+
+ # make sure loop module is present
+ if ! losetup -f >/dev/null 2>&1; then
+ einfo "Can not find a usable loop device, retrying after loading loop module."
+ modprobe loop
+ if losetup -f >/dev/null 2>&1; then
+ einfo "Found a usable loop device now, continuing."
+ else
+ eerror "Error finding usable loop device" ; eend 1
+ bailout 1
+ fi
+ fi
+
+ DEVINFO=$(kpartx -av $TARGET) # 'add map loop1p1 (253:0): 0 6289408 linear /dev/loop1 2048'
+ if [ -z "${DEVINFO}" ] ; then
+ eerror "Error setting up loopback device." ; eend 1
+ bailout 1
+ fi
+
+ # hopefully this always works as expected
+ LOOP=$(echo ${DEVINFO} | sed 's/.* linear //; s/ [[:digit:]]*//') # '/dev/loop1'
+ BLOCKDEV=$(echo "${DEVINFO}" | sed -e 's/.* (\(.*:.*\)).*/\1/') # '253:0'
+ LOOP_PART="$(echo ${DEVINFO##add map } | sed 's/ .*//')" # '/dev/loop1p1'
+ export TARGET="/dev/mapper/$LOOP_PART" # '/dev/mapper/loop1p1'
+
+ blockdev --rereadpt "${LOOP}"
+
+ if [ -z "$TARGET" ] ; then
+ eerror "Error: target could not be set to according /dev/mapper/* device." ; eend 1
+ bailout 1
+ fi
+}
+# }}}
+
+# make VM image bootable and unmount it {{{
+finalize_vm() {
+ if [ -z "${VIRTUAL}" ] ; then
+ return 0
+ fi
+
+ if ! mount "${TARGET}" "${MNTPOINT}" ; then
+ eerror "Error: Mounting ${TARGET} failed, can not continue." ; eend 1
+ bailout 1
+ fi
+
+ einfo "Installing Grub as bootloader."
+ mount -t proc none "${MNTPOINT}"/proc
+ mount -t sysfs none "${MNTPOINT}"/sys
+ mount --bind /dev "${MNTPOINT}"/dev
+
+ mkdir -p "${MNTPOINT}/boot/grub"
+ if ! [ -d "${MNTPOINT}"/usr/lib/grub/i386-pc/ ] ; then
+ eerror "Error: grub not installed inside Virtual Machine. Can not install bootloader." ; eend 1
+ bailout 1
+ fi
+
+ cp "${MNTPOINT}"/usr/lib/grub/i386-pc/* "${MNTPOINT}/boot/grub/"
+ chroot "${MNTPOINT}" grub-mkimage -O i386-pc -p "(hd0,msdos1)/boot/grub" -o /tmp/core.img biosdisk part_msdos ext2
+ dd if="${MNTPOINT}/tmp/core.img" of="${ORIG_TARGET}" conv=notrunc seek=4
+ rm -f "${MNTPOINT}/tmp/core.img"
+
+ einfo "Updating grub configuration file."
+ if [ -n "$BOOT_APPEND" ] ; then
+ sed -i "/GRUB_CMDLINE_LINUX_DEFAULT/ s#\"\$# ${BOOT_APPEND}\"#" "${MNTPOINT}"/etc/default/grub
+ fi
+ chroot "${MNTPOINT}" update-grub
+
+ umount "${MNTPOINT}"/proc
+ umount "${MNTPOINT}"/sys
+ umount "${MNTPOINT}"/dev
+
+ einfo "Adjusting grub.cfg for successful boot sequence."
+ if [ "$FIXED_DISK_IDENTIFIERS" = "yes" ]; then
+ sed -i "s;root=[^ ]\+;root=UUID=$DISK_IDENTIFIER;" /boot/grub/grub.cfg
+ else
+ sed -i "s;set root=.*;set root='(hd0,msdos1)';" "${MNTPOINT}"/boot/grub/grub.cfg
+ sed -i "s;root=[^ ]\+;root=/dev/sda1;" "${MNTPOINT}"/boot/grub/grub.cfg
+ fi
+
+ umount "${MNTPOINT}"
+ kpartx -d "${ORIG_TARGET}" >/dev/null
+}
+# }}}
+