Compare commits

...

12 Commits

3 changed files with 33 additions and 11 deletions

View File

@@ -1,12 +1,14 @@
# zbm-syslinux-pacman-hook
Arch Linux pacman hook to automatically recreate syslinux and MBR after updates
Arch Linux pacman hook to automatically recreate syslinux and MBR after updates. This hook is intended to work with [quico.space/quico-os-setup/arch-zbm](https://quico.space/quico-os-setup/arch-zbm), a root-on-ZFS installation script that uses ZFSBootMenu as its boot loader.
# Setup
> Not explicitly listed here as a step but still relevant: This `pacman` hook only makes sense if you're using Syslinux as your boot loader and have the homonymous `syslinux` package installed.
Get started like so:
1. Install dependency `rsync`
1. Install dependencies `jq` and `rsync`
1. Clone repo into arbitrary path `<repo>`
1. Make `pacman-zbm-syslinux-regen.sh` executable
```
@@ -39,7 +41,7 @@ If this returns zero or more than one mounted drive we bail, print an error mess
# Assumptions
This hook is intended to work with [quico.space/quico-os-setup/arch-zbm](https://quico.space/quico-os-setup/arch-zbm), a root on ZFS installation script that uses ZFSBootMenu as its boot loader; it's specifically intended for use on `arch-zbm` machines that use legacy BIOS. Before using this hook for any other purpose please closely review what it does and adapt to your use case as needed.
Per [headline](#zbm-syslinux-pacman-hook) this hook is intended to work with [quico.space/quico-os-setup/arch-zbm](https://quico.space/quico-os-setup/arch-zbm); it's specifically intended for use on `arch-zbm` machines that use legacy BIOS. Before using this hook for any other purpose please closely review what it does and adapt to your use case as needed.
We do not care about `pacman` events other than a `syslinux` package update. Specifically if ZFSBootMenu gets an update `syslinux` and our Master Boot Record remain unaffected. Kernel update? Same, no change needed since no kernel or module change directly influence the simple and decoupled structure of `syslinux`.
@@ -62,6 +64,6 @@ Commit _types_ besides `fix` and `feat` are:
The following _scopes_ are known for this project. A Conventional Commits commit message may optionally use one of the following scopes or none:
- `script`: Any other script work that doesn't specifically fall into the above scopes
- `script`: Work related to the commands triggered by `pacman`
- `hook`: Configuring the hook(s)
- `meta`: Affects the project's repo layout, readme content, file names etc.

View File

@@ -7,5 +7,6 @@ Target = syslinux
Description = Regen syslinux and MBR
When = PostTransaction
Exec = /usr/local/bin/pacman-zbm-syslinux-regen
Depends = jq
Depends = rsync
AbortOnFail
Depends = syslinux

View File

@@ -2,20 +2,39 @@
boot_dir='/boot/syslinux'
boot_dir="${boot_dir%/}"
boot_disk="$(findmnt --noheadings --target "${boot_dir}" --output 'SOURCE')" || {
# Returns e.g. '/dev/sda1'
boot_fs="$(findmnt --noheadings --target "${boot_dir}" --output 'SOURCE')" || {
printf -- '%s\n' \
'Unable to identify boot drive for '"'${boot_dir}'"' boot dir.' \
'Cowardly exiting. No syslinux files nor MBR were overwritten.'
exit 1
}
if [[ "$(<<<"${boot_dir}" wc -l)" -gt '1' ]]; then
if [[ "$(<<<"${boot_fs}" wc -l)" -gt '1' ]]; then
printf -- '%s\n' \
'More than one drive mounted at '"'${boot_dir}'"' boot dir.' \
'Cowardly exiting. No syslinux files nor MBR were overwritten.'
exit 1
fi
find "${boot_dir}" -type f -iname '*.c32' -delete
rsync -a '/usr/lib/syslinux/bios/'*'.c32' "${boot_dir}"'/'
extlinux --install "${boot_dir}"
dd bs=440 count=1 conv=notrunc if='/usr/lib/syslinux/bios/mbr.bin' of="${boot_disk}"
# Returns e.g. 'sda1'. This is the format used when traversing through lsblk
# JSON output.
boot_fs_name="$(basename "${boot_fs}")"
# May return e.g. 'sda' if "${boot_fs}" has a parent.
boot_disk="$(lsblk --output 'NAME' --json --tree | jq --raw-output '.[][] | select(.children | length > 0) | select(.children[].name=="'"${boot_fs_name}"'") | .name')"
if [[ ! "${boot_disk}" ]]; then
# There's no parent drive over "${boot_fs}" meaning "${boot_fs}" itself
# already is the parent. This is a file system on a drive and not on a
# partition. We stick to the long-form device name, e.g. '/dev/sda1'.
boot_disk="${boot_fs}"
else
# We found a parent, e.g. 'sda'. In order to work with commands below
# we'll prefix it with '/dev/'.
boot_disk='/dev/'"${boot_disk}"
fi
find "${boot_dir}" -type f -iname '*.c32' -delete && echo 'Delete old COMBOOT files from boot drive'
rsync -a '/usr/lib/syslinux/bios/'*'.c32' "${boot_dir}"'/' && echo 'Put new COMBOOT files onto boot drive'
extlinux --install "${boot_dir}" &>/dev/null && echo 'Install new extlinux boot loader'
dd bs=440 count=1 conv=notrunc if='/usr/lib/syslinux/bios/mbr.bin' of="${boot_disk}" 2>/dev/null && echo 'Overwrite MBR with newest version'