summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Shatunov2020-01-31 21:04:08 +0800
committerSergey Shatunov2020-01-31 21:07:53 +0800
commit41f1745de0adf704cf51801ecd9e9e4ef5ef451b (patch)
tree8c39339606cd2bfd7a7cf2bc96c955e2c422ede7
downloadaur-41f1745de0adf704cf51801ecd9e9e4ef5ef451b.tar.gz
Initial commit
-rw-r--r--.SRCINFO35
-rw-r--r--.gitignore3
-rwxr-xr-x50-generate-efistub.install54
-rw-r--r--55-unifed-arch-kernel-remove.hook12
-rw-r--r--75-sign-for-secure-boot.install26
-rw-r--r--95-unifed-arch-kernel-install.hook31
-rw-r--r--PKGBUILD46
-rw-r--r--config12
-rwxr-xr-xuak164
-rwxr-xr-xuak-script137
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
diff --git a/uak b/uak
new file mode 100755
index 000000000000..aee5cef12fc7
--- /dev/null
+++ b/uak
@@ -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