mkimage-profiles/bin/tar2fs
Michael Shigorin b31af10c79 tar2fs: generate proper boot.conf for e2k
This one supports multiple kernels (and tweaks boot
labels aiming to simplify target kernel selection
for the CPU at hand) instead of an earlier attempt
to fill in a template.

No need for the template so just drop it.
2018-05-21 22:50:07 +03:00

298 lines
7.2 KiB
Bash
Executable File

#!/bin/bash -ex
# usage:
# tar2fs chroot.tar image.raw [size_in_bytes [fstype]]
. shell-error
export LANG=C
if [ $# -lt 2 ]; then
fatal "error: tar2fs needs at least two arguments"
fi
# this needs env_keep sudo setup to actually work
if [ -n "$GLOBAL_BUILDDIR" ]; then
WORKDIR="$GLOBAL_BUILDDIR/vmroot"
else
WORKDIR="$(mktemp --tmpdir -d vmroot-XXXXX)"
fi
[ -n "$WORKDIR" ] || fatal "couldn't come up with suitable WORKDIR"
[ -n "$GLOBAL_DEBUG" ] || message "WORKDIR: $WORKDIR"
MB=1048576 # a parted's "megabyte" in bytes is *broken*
SIZE_FACTOR=2 # multiply the sizes found by this value
BOOT_SIZE_FACTOR=2 # multiply /boot size by this value additionally
CUR_BOUNDARY=0 # align first partition at 1MB for performance (+1)
INITRD_MODULES=
BOOTFSTYPE=
BOOTPART=
ARCH="$(arch)" # NB: sudo => no GLOBAL_ will do either; mind qemu-*
case "$ARCH" in
*86*)
# NB: different storage modules might be needed for non-kvm
INITRD_MODULES="sd_mod ata_piix ahci virtio-scsi virtio-blk"
BLOCKDEV="/dev/sda" # might be /dev/vda for virtio
ROOTPART="1"
;;
arm*)
BOOTFSTYPE="ext2" # support expected in every sane target uboot
BLOCKDEV="/dev/mmcblk0p" # ...hopefully...
BOOTPART="1"
ROOTPART="2"
;;
e2k)
BOOTFSTYPE="ext2" # firmware knows it
BLOCKDEV="/dev/sda" # ...hopefully...
BOOTPART="1"
ROOTPART="2"
;;
esac
# figure out the part taken by /boot in the given tarball
boot_size() {
if [ -n "$BOOTPART" ]; then
tar tvf "$1" \
| awk ' \
BEGIN { sum=0 }
/^-.* \.\/boot\// { sum=sum+$3 }
END { print sum }'
else
echo "0"
fi
}
# parted wrapper for convenience
parting() { parted "$LOOPDEV" --align optimal --script -- "$@"; }
# unfortunately parted is insane enough to lump alignment controls
# into unit controls so creating adjacent partitions sized in MiB
# is not as straightforward as it might be... thus "+1" padding;
# see also http://www.gnu.org/software/parted/manual/parted.html#unit
mkpart() {
# a bit different start/end semantics to handle end of device too
local start="$(($CUR_BOUNDARY + 1))" # yes, we lose a megabyte
if [ -n "$1" ]; then
CUR_BOUNDARY="$(($start + $1))"
local end="$CUR_BOUNDARY"MiB
else
local end="-1s" # last sector of the image
fi
parting mkpart primary ext2 "$start"MiB "$end"
}
# a tarball containing chroot with a kernel
TAR="$1"
[ -s "$TAR" ] || fatal "source tarball doesn't really exist"
# a path to the image to be generated
IMG="$2"
[ -d "$(dirname "$IMG")" ] || fatal "target directory doesn't exist"
# 0 means auto; if a value is specified it holds (no /boot subtracted)
ROOTSIZE="$3"
[ -n "$ROOTSIZE" -a "$ROOTSIZE" != 0 ] || unset ROOTSIZE
# image size in bytes
TARSIZE="$(stat -Lc %s "$TAR")"
# /boot size in that tarball
BOOTSIZE="$(boot_size "$TAR")"
DEFSIZE="$(($SIZE_FACTOR * ($TARSIZE - $BOOTSIZE)))" # (exact sizes)
ROOTSIZE="$((${ROOTSIZE:-$DEFSIZE} + $MB - 1))" # for ceil rounding to MB
# image and /boot sizes in megabytes
ROOTSIZEM="$(($ROOTSIZE / $MB))"
BOOTSIZEM="$((($SIZE_FACTOR * $BOOT_SIZE_FACTOR * $BOOTSIZE + $MB - 1) / $MB))"
# tested to work: ext[234], jfs
# NB: xfs doesn't have a spare sector for the bootloader
ROOTFSTYPE="${4:-ext4}"
# single root partition hardwired so far,
# add another image for home/data/swap if needed
ROOTDEV="$BLOCKDEV$ROOTPART"
# last preparations...
MKFS="mkfs.$ROOTFSTYPE ${BOOTFSTYPE:+mkfs.$BOOTFSTYPE}"
for i in losetup sfdisk parted kpartx $MKFS; do
if ! type -t "$i" >&/dev/null; then
fatal "$i required but not found in host system"
fi
done
LOOPDEV="$(losetup --find)" # would be sad about non-binary megabytes too
ROOTFS="$WORKDIR/chroot"
BOOTFS=
if [ -n "$BOOTPART" ]; then
BOOTFS="$ROOTFS/boot"
fi
exit_handler() {
rc=$?
if [ -n "$ROOTFS" ]; then
umount ${BOOTFS:+"$BOOTFS"} "$ROOTFS"{/dev,/proc,/sys,}
if [ -n "$LOOPDEV" ]; then
kpartx -d -s "$LOOPDEV" || {
sleep 10
kpartx -d -s -v "$LOOPDEV"
}
losetup --detach "$LOOPDEV"
fi
rm -r -- "$ROOTFS"
rmdir -- "$WORKDIR"
fi
exit $rc
}
# handle -e in shebang as well
trap exit_handler EXIT ERR
# prepare disk image and a filesystem inside it
rm -f -- "$IMG"
OFFSET="$(($CUR_BOUNDARY + $BOOTSIZEM + $ROOTSIZEM - 1))"
dd if=/dev/zero of="$IMG" conv=notrunc bs=$MB count=1 seek="$OFFSET"
losetup "$LOOPDEV" "$IMG"
parting mklabel msdos
if [ -n "$BOOTPART" ]; then
BOOTDEV="$BLOCKDEV$BOOTPART"
mkpart "$BOOTSIZEM"
fi
# not ROOTSIZEM but "the rest"; somewhat non-trivial arithmetics lurk in parted
mkpart
kpartx -a -s "$LOOPDEV"
LOOPROOT="/dev/mapper/$(basename "$LOOPDEV")p$ROOTPART"
mkfs."$ROOTFSTYPE" "$LOOPROOT"
if [ -n "$BOOTPART" ]; then
LOOPBOOT="/dev/mapper/$(basename "$LOOPDEV")p$BOOTPART"
mkfs."$BOOTFSTYPE" "$LOOPBOOT"
fi
ROOTUUID="$(blkid -s UUID -o value -c /dev/null "$LOOPROOT")"
if [ -n "$ROOTUUID" ]; then
ROOTDEV="UUID=$ROOTUUID"
else
ROOTDEV="$LOOPROOT"
fi
if [ -n "$BOOTPART" ]; then
BOOTUUID="$(blkid -s UUID -o value -c /dev/null "$LOOPBOOT")"
if [ -n "$ROOTUUID" ]; then
BOOTDEV="UUID=$BOOTUUID"
fi
fi
# mount and populate it
mkdir -pm755 "$ROOTFS"
mount "$LOOPROOT" "$ROOTFS"
if [ -n "$BOOTPART" ]; then
mkdir -pm700 "$BOOTFS"
mount "$LOOPBOOT" "$BOOTFS"
fi
tar -C "$ROOTFS" --numeric-owner -xf "$TAR"
for i in /dev /proc /sys; do mount --bind "$i" "$ROOTFS$i"; done
# loop device so lilo could work...
echo "$ROOTDEV / $ROOTFSTYPE relatime 1 1" >> "$ROOTFS/etc/fstab"
# target device at once
if [ -n "$BOOTPART" ]; then
echo "$BOOTDEV /boot $BOOTFSTYPE defaults 1 2" >> "$ROOTFS/etc/fstab"
fi
echo "MODULES_PRELOAD += $INITRD_MODULES $ROOTFSTYPE" >> "$ROOTFS/etc/initrd.mk"
case "$ARCH" in
*86*)
echo "FEATURES += qemu" >> "$ROOTFS/etc/initrd.mk"
;;
e2k)
echo "FEATURES += usb" >> "$ROOTFS/etc/initrd.mk"
;;
esac
# NB: don't stick BOOTFS here, it has slightly different semantics
pushd $ROOTFS/boot
KVERSIONS=
if [ -s .origver ]; then
while read kver; do
chroot "$ROOTFS" make-initrd -k "$kver"
KVERSIONS="$KVERSIONS $kver"
done < .origver
fi
[ -n "$KVERSIONS" ] || fatal "unable to deduce kernel version"
rm -f .origver
# ...target device too
sed -i "s,$LOOPROOT,$ROOTDEV," "$ROOTFS/etc/fstab"
# FIXME: relies on particular (current) kernel package naming scheme
for v in $KVERSIONS; do
l="$(echo "$v" | sed -r 's,.*elbrus-([0-9a-z]+)-.*$,\1,')"
cat >> boot.conf <<EOF
label=$l
partition=0
image=/image-$v
initrd=/initrd-$v.img
cmdline=console=ttyS0,115200 console=tty0 consoleblank=0 hardreset root=UUID=$ROOTUUID
EOF
done
echo "** start of boot.conf"
cat boot.conf
echo "** end of boot.conf"
popd
if [ -x "$ROOTFS"/sbin/lilo ]; then
# configure and install bootloader
REGEXP='^.*: ([0-9]+) cylinders, ([0-9]+) heads, ([0-9]+) sectors/track*$'
set -- $(sfdisk -g "$LOOPDEV" | grep -E "$REGEXP" | sed -r "s@$REGEXP@\1 \2 \3@")
LILO_COMMON="lba32
delay=1
vga=0
image=/boot/vmlinuz
initrd=/boot/initrd.img
append=\"root=$ROOTDEV rootdelay=3 console=tty1 console=ttyS0,115200n8\"
label=linux"
cat > "$ROOTFS"/etc/lilo-loop.conf <<-EOF
boot=$LOOPDEV
disk=$LOOPDEV
bios=0x80
cylinders=$1
heads=$2
sectors=$3
partition=$LOOPROOT
start=63
$LILO_COMMON
EOF
chroot "$ROOTFS" lilo -C /etc/lilo-loop.conf
cat > "$ROOTFS"/etc/lilo.conf <<-EOF
boot=$BLOCKDEV
$LILO_COMMON
EOF
fi
if [ -n "$SUDO_USER" ]; then
chown "$SUDO_USER:$(id -g "$SUDO_USER")" "$IMG" "$ROOTFS" "$WORKDIR" ||:
fi