diff options
author | Sergey Shatunov | 2020-01-31 21:04:08 +0800 |
---|---|---|
committer | Sergey Shatunov | 2020-01-31 21:07:53 +0800 |
commit | 41f1745de0adf704cf51801ecd9e9e4ef5ef451b (patch) | |
tree | 8c39339606cd2bfd7a7cf2bc96c955e2c422ede7 | |
download | aur-41f1745de0adf704cf51801ecd9e9e4ef5ef451b.tar.gz |
Initial commit
-rw-r--r-- | .SRCINFO | 35 | ||||
-rw-r--r-- | .gitignore | 3 | ||||
-rwxr-xr-x | 50-generate-efistub.install | 54 | ||||
-rw-r--r-- | 55-unifed-arch-kernel-remove.hook | 12 | ||||
-rw-r--r-- | 75-sign-for-secure-boot.install | 26 | ||||
-rw-r--r-- | 95-unifed-arch-kernel-install.hook | 31 | ||||
-rw-r--r-- | PKGBUILD | 46 | ||||
-rw-r--r-- | config | 12 | ||||
-rwxr-xr-x | uak | 164 | ||||
-rwxr-xr-x | uak-script | 137 |
10 files changed, 520 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..23b3d754a359 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,35 @@ +pkgbase = unifed-arch-kernel + pkgdesc = Generates unifed archlinux images using pacman power + pkgver = 0.0.4 + pkgrel = 1 + url = https://aur.archlinux.org/packages/unifed-arch-kernel/ + arch = x86_64 + license = GPL + source = uak-script + source = uak + source = config + source = 50-generate-efistub.install + source = 55-unifed-arch-kernel-remove.hook + source = 75-sign-for-secure-boot.install + source = 95-unifed-arch-kernel-install.hook + md5sums = 2ffcf000edef6ab1e85f62c3e5f910c4 + md5sums = 15d02966c33006a8f9dc6456953e3a47 + md5sums = cf19112a5294756657e8e2e3ebf6226d + md5sums = 5b263fc13f06b08b3714337e28f44424 + md5sums = 9105de5ff7f384b1e48bdd4972b87917 + md5sums = 6759b0a4b35dff92e8bde49dd8bbe2e1 + md5sums = 9752535dff10105c003f9108528bd50a + +pkgname = unifed-arch-kernel + depends = pacman + depends = systemd + depends = bash + depends = mkinitcpio + depends = binutils + depends = coreutils + backup = etc/uak/config + +pkgname = unifed-arch-kernel-secure-boot + depends = unifed-arch-kernel + depends = sbsigntools + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..26ac48df7db9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +pkg/ +src/ +*.pkg.tar* diff --git a/50-generate-efistub.install b/50-generate-efistub.install new file mode 100755 index 000000000000..6b50cf24fbc7 --- /dev/null +++ b/50-generate-efistub.install @@ -0,0 +1,54 @@ +#!/bin/bash -e +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +function osrel() { + /usr/bin/cat "$OS_RELEASE_DEST" + if [ $# -gt 1 ]; then + for key in $(seq 1 2 $#); do + value=$((key + 1)) + printf '%s=%s\n' "${!key}" "${!value}" + done + fi +} + +if [[ "$COMMAND" == "add" ]]; then + declare -a BOOT_OPTIONS + + if [[ -f /etc/uak/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /etc/uak/cmdline || true + elif [[ -f /usr/lib/uak/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /usr/lib/uak/cmdline || true + elif [[ -f /boot/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /boot/cmdline || true + elif [[ -f /etc/kernel/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline || true + elif [[ -f /usr/lib/kernel/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /usr/lib/kernel/cmdline || true + else + read -r -d '' -a boot_option_line < /proc/cmdline || true + for boot_option in "${boot_option_line[@]}"; do + [[ "${boot_option#initrd=*}" != "$boot_option" ]] && continue + BOOT_OPTIONS+=("$boot_option") + done + fi + + if ! (( ${#BOOT_OPTIONS[@]} )) && [[ "$UAK_WARN_EMPTY_BOOT_OPTIONS" != "false" ]]; then + warning "Creating image with empty boot options, most highly it's not what do you want to do" + warning "Please put boot options to the /etc/uak/cmdline and run 'uak regenerate' to regenerate all boot images" + fi + + objcopy_args=() + + if [[ -f "$UAK_SPLASH" ]]; then + objcopy_args+=(--add-section ".splash=$UAK_SPLASH" --change-section-vma '.splash=0x40000') + fi + + /usr/bin/objcopy \ + --add-section .osrel=<(osrel VERSION_ID "$KERNEL_VERSION") --change-section-vma '.osrel=0x20000' \ + --add-section .cmdline=<(echo "${BOOT_OPTIONS[@]}") --change-section-vma '.cmdline=0x30000' \ + --add-section .linux="$KERNEL_IMAGE" --change-section-vma '.linux=0x2000000' \ + --add-section .initrd=<(/usr/bin/cat "${INITRDS[@]}") --change-section-vma '.initrd=0x3000000' \ + "${objcopy_args[@]}" \ + /usr/lib/systemd/boot/efi/linuxx64.efi.stub "$EFISTUB_IMAGE" +fi diff --git a/55-unifed-arch-kernel-remove.hook b/55-unifed-arch-kernel-remove.hook new file mode 100644 index 000000000000..1f77af6acdd7 --- /dev/null +++ b/55-unifed-arch-kernel-remove.hook @@ -0,0 +1,12 @@ +[Trigger] +Type = File +Operation = Remove +Target = usr/lib/modules/*/vmlinuz + +[Action] +Description = Removing unifed ArchLinux EFI image... +Depends = unifed-arch-kernel +When = PreTransaction +Exec = /usr/share/libalpm/scripts/uak-script remove +NeedsTargets + diff --git a/75-sign-for-secure-boot.install b/75-sign-for-secure-boot.install new file mode 100644 index 000000000000..973467abc93c --- /dev/null +++ b/75-sign-for-secure-boot.install @@ -0,0 +1,26 @@ +#!/bin/bash -e +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +if [[ ! "$UAK_EFI_KEYS_PATH" ]]; then + UAK_EFI_KEYS_PATH=/etc/efi-keys +fi + +if [[ "$COMMAND" == "add" ]]; then + sign=1 + + if [[ ! -f "$UAK_EFI_KEYS_PATH/db.crt" ]]; then + warning "Missing db.crt in $UAK_EFI_KEYS_PATH. Skip signing" + sign=0 + fi + + if [[ ! -f "$UAK_EFI_KEYS_PATH/db.key" ]]; then + warning "Missing db.key in $UAK_EFI_KEYS_PATH. Skip signing" + sign=0 + fi + + if (( sign )) && [[ -f "$EFISTUB_IMAGE" ]]; then + /usr/bin/sbsign --key "$UAK_EFI_KEYS_PATH/db.key" --cert "$UAK_EFI_KEYS_PATH/db.crt" --output "${EFISTUB_IMAGE}" "$EFISTUB_IMAGE" 2> /dev/null + fi +fi + diff --git a/95-unifed-arch-kernel-install.hook b/95-unifed-arch-kernel-install.hook new file mode 100644 index 000000000000..f3bf7ee0b81c --- /dev/null +++ b/95-unifed-arch-kernel-install.hook @@ -0,0 +1,31 @@ +[Trigger] +Type = File +Operation = Install +Operation = Upgrade +Target = usr/lib/modules/*/vmlinuz +Target = usr/lib/initcpio/* +Target = usr/lib/systemd/boot/efi/linuxx64.efi.stub +Target = usr/lib/os-release +Target = boot/*-ucode.img +Target = usr/bin/uak +Target = usr/share/libalpm/scripts/uak-script +Target = usr/lib/uak/install.d/*.install + +[Trigger] +Type = File +Operation = Remove +Target = usr/lib/initcpio/* +Target = boot/*-ucode.img + +[Trigger] +Type = Package +Operation = Install +Operation = Upgrade +Target = unifed-arch-kernel + +[Action] +Description = Creating unifed ArchLinux EFI image... +Depends = unifed-arch-kernel +When = PostTransaction +Exec = /usr/share/libalpm/scripts/uak-script install +NeedsTargets diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..65511bcd9313 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,46 @@ +# Maintainer: Sergey Shatunov <me@prok.pw> + +pkgname=('unifed-arch-kernel' 'unifed-arch-kernel-secure-boot') +pkgbase=unifed-arch-kernel +pkgver=0.0.4 +pkgrel=1 +pkgdesc='Generates unifed archlinux images using pacman power' +arch=(x86_64) +url='https://aur.archlinux.org/packages/unifed-arch-kernel/' +license=('GPL') +source=('uak-script' + 'uak' + 'config' + '50-generate-efistub.install' + '55-unifed-arch-kernel-remove.hook' + '75-sign-for-secure-boot.install' + '95-unifed-arch-kernel-install.hook') +md5sums=('2ffcf000edef6ab1e85f62c3e5f910c4' + '15d02966c33006a8f9dc6456953e3a47' + 'cf19112a5294756657e8e2e3ebf6226d' + '5b263fc13f06b08b3714337e28f44424' + '9105de5ff7f384b1e48bdd4972b87917' + '6759b0a4b35dff92e8bde49dd8bbe2e1' + '9752535dff10105c003f9108528bd50a') + +package_unifed-arch-kernel() { + depends=('pacman' 'systemd' 'bash' 'mkinitcpio' 'binutils' 'coreutils') + backup=(etc/uak/config) + + install -d "$pkgdir/etc/uak/install.d" + install -d "$pkgdir/usr/lib/uak/install.d" + + install -D "$srcdir/uak" "$pkgdir/usr/bin/uak" + install -D "$srcdir/uak-script" "$pkgdir/usr/share/libalpm/scripts/uak-script" + install -D "$srcdir/config" "$pkgdir/etc/uak/config" + install -D "$srcdir/50-generate-efistub.install" "$pkgdir/usr/lib/uak/install.d/50-generate-efistub.install" + install -D "$srcdir/95-unifed-arch-kernel-install.hook" "$pkgdir/usr/share/libalpm/hooks/95-unifed-arch-kernel-install.hook" + install -D "$srcdir/55-unifed-arch-kernel-remove.hook" "$pkgdir/usr/share/libalpm/hooks/55-unifed-arch-kernel-remove.hook" +} + +package_unifed-arch-kernel-secure-boot() { + depends=('unifed-arch-kernel' 'sbsigntools') + + install -d "$pkgdir/usr/lib/uak/install.d" + install -D "$srcdir/75-sign-for-secure-boot.install" "$pkgdir/usr/lib/uak/install.d/75-sign-for-secure-boot.install" +} diff --git a/config b/config new file mode 100644 index 000000000000..def7a57f0eb6 --- /dev/null +++ b/config @@ -0,0 +1,12 @@ +# Path to the EFI System Partition +#UAK_ESP_PATH=/efi + +# Path to BMP image +#UAK_SPLASH=/usr/share/systemd/bootctl/splash-arch.bmp + +# Path to directory with efi keys (db.key & db.crt) +# Requires unifed-arch-kernel-secure-boot to be installed +#UAK_EFI_KEYS_PATH=/etc/efi-keys + +# Warn when attempt to create image without are boot options +#UAK_WARN_EMPTY_BOOT_OPTIONS=true @@ -0,0 +1,164 @@ +#!/bin/bash -e +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +export LC_COLLATE=C + +source /usr/share/makepkg/util/message.sh + +function check_root() { + if [[ "$EUID" != 0 ]]; then + error "Must be runned with superuser privilegies" + exit 2 + fi +} + +function dropindirs_sort() { + local suffix=$1; shift + local -a files + local f d i + + readarray -t files <<<"$( + for d in "$@"; do + for i in "$d/"*"$suffix"; do + if [[ -e "$i" ]]; then + echo "${i##*/}" + fi + done + done | sort -Vu + )" + + for f in "${files[@]}"; do + for d in "$@"; do + if [[ -e "$d/$f" ]]; then + echo "$d/$f" + continue 2 + fi + done + done +} + +function die() { + code="$1" + shift + echo "$*" >&2 + exit "$code" +} + +function usage() { + echo "Usage:" + echo " $0 add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]" + echo " $0 remove KERNEL-VERSION" + echo " $0 regenerate" +} + +for i in "$@"; do + if [ "$i" == "--help" ] || [ "$i" == "-h" ]; then + usage + exit 0 + fi +done + +if [[ -f /etc/os-release ]]; then + OS_RELEASE_DEST=/etc/os-release + source "$OS_RELEASE_DEST" +elif [[ -f /usr/lib/os-release ]]; then + OS_RELEASE_DEST=/usr/lib/os-release + source "$OS_RELEASE_DEST" +else + warning "Missing os-release, things can go wrong AND THEY WILL GO WRONG" +fi + +if [[ -f /etc/uak/config ]]; then + source /etc/uak/config +fi + +if [[ ! "$UAK_ESP_PATH" ]]; then + UAK_ESP_PATH=$(bootctl --print-esp-path) +fi + +if [[ ! -d "$UAK_ESP_PATH" ]]; then + die 1 "Invalid ESP path: $UAK_ESP_PATH" +fi + +if [[ ! "$UAK_SPLASH" ]]; then + UAK_SPLASH=/usr/share/systemd/bootctl/splash-arch.bmp +fi + +export UAK_ESP_PATH UAK_SPLASH + +export UAK_ESP_TARGET="$UAK_ESP_PATH/EFI/Linux" + +COMMAND="$1" + +case "$COMMAND" in + add) + check_root + + KERNEL_VERSION="$2" + KERNEL_IMAGE="$3" + INITRDS=( "${@:4}" ) + + if [[ ! $KERNEL_VERSION ]] || [[ ! "$KERNEL_IMAGE" ]]; then + die 1 "Not enough arguments" + fi + + if [[ ! -f "$KERNEL_IMAGE" ]]; then + die 2 "Kernel image '${KERNEL_IMAGE}' not a file" + fi + + shift 3 + + EFISTUB_IMAGE=$(mktemp) + EFISTUB_INSTALL_PATH="$UAK_ESP_TARGET/$ID-$KERNEL_VERSION.efi" + ;; + remove) + check_root + + KERNEL_VERSION="$2" + + if [[ ! $KERNEL_VERSION ]]; then + die 1 "Not enough arguments" + fi + + shift 2 + + EFISTUB_INSTALL_PATH="$UAK_ESP_TARGET/$ID-$KERNEL_VERSION.efi" + ;; + regenerate) + check_root + + exec /usr/share/libalpm/scripts/uak-script install-all + ;; + '') + usage + ;; + *) + die 1 "Unknown command '$COMMAND'" + ;; +esac + +readarray -t PLUGINS <<<"$( + dropindirs_sort ".install" \ + "/etc/uak/install.d" \ + "/usr/lib/uak/install.d" +)" + +for plugin in "${PLUGINS[@]}"; do + if [[ -x "$plugin" ]]; then + source "$plugin" + fi +done + + +if [[ "$COMMAND" == "add" ]]; then + if [[ -f "$EFISTUB_IMAGE" ]]; then + install -DT "$EFISTUB_IMAGE" "$EFISTUB_INSTALL_PATH" || warning "Unable to install image at $EFISTUB_INSTALL_PATH" + else + warning "No image was generated, skip install" + fi +elif [[ "$COMMAND" == "remove" ]]; then + if [[ -f "$EFISTUB_INSTALL_PATH" ]]; then + unlink "$EFISTUB_INSTALL_PATH" || warning "Unable to remove image at '$EFISTUB_INSTALL_PATH'" + fi +fi diff --git a/uak-script b/uak-script new file mode 100755 index 000000000000..e91ca12eb646 --- /dev/null +++ b/uak-script @@ -0,0 +1,137 @@ +#!/bin/bash -e +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +source /usr/share/makepkg/util/message.sh + +# grabbed from mkinitcpio +kver() { + # this is intentionally very loose. only ensure that we're + # dealing with some sort of string that starts with something + # resembling dotted decimal notation. remember that there's no + # requirement for CONFIG_LOCALVERSION to be set. + local kver re='^[[:digit:]]+(\.[[:digit:]]+)+' + + # scrape the version out of the kernel image. locate the offset + # to the version string by reading 2 bytes out of image at at + # address 0x20E. this leads us to a string of, at most, 128 bytes. + # read the first word from this string as the kernel version. + local offset=$(hexdump -s 526 -n 2 -e '"%0d"' "$1") + [[ $offset = +([0-9]) ]] || return 1 + + read kver _ < \ + <(dd if="$1" bs=1 count=127 skip=$(( offset + 0x200 )) 2>/dev/null) + + [[ $kver =~ $re ]] || return 1 + + printf '%s' "$kver" +} + +function do_uak() { + msg "uak $*" + /usr/bin/uak "$@" || return $? +} + +ACTION="$1" + +if [[ $ACTION == "install-preset" ]]; then + kernel="$2" + pkgbase="$3" + kernel_version="$4" + + source "/etc/mkinitcpio.d/${pkgbase}.preset" + + for preset in "${PRESETS[@]}"; do + preset_kernel_version=${kernel_version}-${preset} + if [[ "$preset" == "default" ]]; then + preset_kernel_version=${kernel_version} + fi + + preset_initrd=${preset}_image + + if ! [[ -f ${!preset_initrd} ]]; then + warning "No image file specified for preset $preset" + continue + fi + + do_uak add "$preset_kernel_version" "$kernel" $(echo /boot/*-ucode.img) "${!preset_initrd}" + done + + exit 0 +elif [[ $ACTION == "remove-preset" ]]; then + pkgbase="$2" + kernel_version="$3" + + source "/etc/mkinitcpio.d/${pkgbase}.preset" + + for preset in "${PRESETS[@]}"; do + preset_kernel_version=${kernel_version}-${preset} + if [[ "$preset" == "default" ]]; then + preset_kernel_version=${kernel_version} + fi + + do_uak remove "$preset_kernel_version" || exit 1 + done + + exit 0 +fi + +ALL=0 +KERNELS=() + +if [[ $ACTION == "install-all" ]]; then + ALL=1 + ACTION="install" +elif [[ $ACTION == "remove-all" ]]; then + ALL=1 + ACTION="remove" +elif [[ $ACTION != "install" ]] && [[ $ACTION != "remove" ]]; then + error "Unknown action: $ACTION" + exit 1 +else + while read -r line; do + if [[ $line != */vmlinuz ]]; then + # triggers when it's a change to usr/lib/initcpio/*, usr/lib/systemd/boot/efi/linuxx64.efi.stub or boot/*-ucode.img + if [[ $ACTION == "install" ]]; then + ALL=1 + fi + continue + fi + + if ! read -r pkgbase > /dev/null 2>&1 < "${line%/vmlinuz}/pkgbase"; then + # if the kernel has no pkgbase, we skip it + continue + fi + + KERNELS+=("$line") + done +fi + +if (( ALL )); then + KERNELS=() + + for kernel in /usr/lib/modules/*/vmlinuz; do + if ! read -r pkgbase > /dev/null 2>&1 < "${kernel%/vmlinuz}/pkgbase"; then + # if the kernel has no pkgbase, we skip it + continue + fi + KERNELS+=("$kernel") + done +fi + +for kernel in "${KERNELS[@]}"; do + read -r pkgbase < "${kernel%/vmlinuz}/pkgbase"; + + if ! [[ -f "/etc/mkinitcpio.d/${pkgbase}.preset" ]]; then + error "Not found mkinitcpio preset for kernel $pkgbase (with image $kernel" + exit 1 + fi + + kernel_version=$(kver "$kernel") + + if [[ $ACTION == "install" ]]; then + "$0" install-preset "$kernel" "$pkgbase" "$kernel_version" + else + "$0" remove-preset "$pkgbase" "$kernel_version" + fi +done |