qubes-linux-utils/archlinux/PKGBUILD-qubes-prepare-vm-kernel.sh

176 lines
4.7 KiB
Bash

#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2015 Marek Marczykowski-Górecki
# <marmarekp@invisiblethingslab.com>
#
# Copyright © 2016 Sébastien Luttringer
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
set -e
basedir=/var/lib/qubes/vm-kernels
function build_modules_img() {
kver=$1
output_file=$2
mkdir /tmp/qubes-modules-$kver
truncate -s 400M /tmp/qubes-modules-$kver.img
mkfs -t ext3 -F /tmp/qubes-modules-$kver.img > /dev/null
mount /tmp/qubes-modules-$kver.img /tmp/qubes-modules-$kver -o loop
cp -a -t /tmp/qubes-modules-$kver /lib/modules/$kver
umount /tmp/qubes-modules-$kver
rmdir /tmp/qubes-modules-$kver
mv /tmp/qubes-modules-$kver.img $output_file
}
function build_initramfs() {
kver=$1
output_file=$2
/sbin/dracut --nomdadmconf --nolvmconf --force \
--modules "kernel-modules qubes-vm-simple" \
--conf /dev/null --confdir /var/empty \
-d "xenblk xen-blkfront cdrom ext4 jbd2 crc16 dm_snapshot" \
$output_file $kver
chmod 644 "$output_file"
}
function build_initcpio() {
kver=$1
output_file=$2
echo $output_file
config_file=/etc/mkinitcpio-qubes.conf
echo "--> Building initcpio configuration file"
sed 's/^HOOKS="base/HOOKS="lvm2 qubes base/' "/etc/mkinitcpio.conf" > "$config_file"
mkinitcpio --config "$config_file" -k "$kver" -g "$output_file"
chmod 644 "$output_file"
echo "--> Copy built initramfs to /boot"
cp "$output_file" /boot/
}
do_prepare_xen_kernel() {
kernel_version="$1"
kernel_base="$2"
kernel_code="$3"
if [ -n "$kernel_code" ] ; then
kernel_name="linux-$kernel_code"
else
kernel_name="linux"
fi
output_dir="$basedir/$kernel_version"
echo "--> Building files for $kernel_version in $output_dir"
mkdir -p "$output_dir"
cp "/boot/vmlinuz-$kernel_name" "$output_dir/vmlinuz-$kernel_name"
echo "---> Generating modules.img"
build_modules_img "$kernel_version" "$output_dir/modules.img"
echo "---> Generating initramfs"
build_initcpio "$kernel_version" "$output_dir/initramfs-$kernel_name.img"
echo "--> Done."
}
# display what to run and run it quietly
run() {
echo "==> $*"
"$@" > /dev/null
}
# check kernel is valid for action
# it means kernel and its headers are installed
# $1: kernel version
check_kernel() {
local kver="$1"; shift
echo "Install tree: $install_tree/$kver/kernel"
if [[ ! -d "$install_tree/$kver/kernel" ]]; then
echo "==> No kernel $kver modules. You must install them to use DKMS!"
return 1
elif [[ ! -d "$install_tree/$kver/build/include" ]]; then
echo "==> No kernel $kver headers. You must install them to use DKMS!"
return 1
fi
return 0
}
# handle actions on kernel addition/upgrade/removal
# $1: kernel version
# $*: dkms args
do_kernel() {
local kver="$1"; shift
check_kernel "$kver" || return
# do $@ once for each dkms module in $source_tree
local path
for path in "$install_tree"/"$kver"/extra/u2mfn.ko; do
echo "Preparing kernel for $path"
if [[ "$path" =~ ^$install_tree/([^/]+)-([^/]+)/extra/u2mfn\.ko$ ]]; then
do_prepare_xen_kernel "$kver" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
fi
done
}
# emulated program entry point
main() {
# prevent to have all each dkms call to fail
if (( EUID )); then
echo 'You must be root to use this hook' >&2
exit 1
fi
# dkms path from framework config
# note: the alpm hooks which trigger this script use static path
source_tree='/usr/src'
install_tree='/usr/lib/modules'
# check source_tree and install_tree exists
local path
for path in "$source_tree" "$install_tree"; do
if [[ ! -d "$path" ]]; then
echo "==> Missing mandatory directory: $path. Exiting!"
return 1
fi
done
if [ -n "$1" ] ; then
echo $install_tree
if [[ "$1" =~ ^$install_tree/([^/]+)/ ]]; then
do_kernel "${BASH_REMATCH[1]}"
fi
else
# parse stdin paths to guess what do do
while read -r path; do
if [[ "/$path" =~ ^$install_tree/([^/]+)/ ]]; then
do_kernel "${BASH_REMATCH[1]}"
fi
done
fi
return 0
}
main "$@"