diff --git a/README.md b/README.md index 55c3fd3..efd47b0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,67 @@ # zbm-syslinux-pacman-hook -Arch Linux pacman hook to automatically recreate syslinux and MBR after updates \ No newline at end of file +Arch Linux pacman hook to automatically recreate syslinux and MBR after updates + +# Setup + +Get started like so: + +1. Install dependency `rsync` +1. Clone repo into arbitrary path `` +1. Make `pacman-zbm-syslinux-regen.sh` executable + ``` + chmod +x /pacman-zbm-syslinux-regen.sh + ``` +1. Symlink to files, for example + ``` + sudo ln -s /pacman-zbm-syslinux-regen.sh /usr/local/bin/pacman-zbm-syslinux-regen + sudo ln -s /pacman-zbm-syslinux-regen.hook /usr/share/libalpm/hooks/pacman-zbm-syslinux-regen.hook + ``` + Note that while you may choose an arbitrary location for your shell script symlink `pacman-zbm-syslinux-regen.hook` file references `/usr/local/bin/pacman-zbm-syslinux-regen`. Change that accordingly if you need to. + +# What's it do? + +In `pacman` whenever the `syslinux` package is getting updated this hook will replace all `*.c32` COMBOOT module files in `/boot/syslinux`, will reinstall newest `extlinux` and write the newest `mbr.bin` Master Boot Record file onto the boot disk. + +This happens as a `PostTransaction` in `pacman`. + +We identify the boot disk via: +``` +findmnt --noheadings --target "${boot_dir}" --output 'SOURCE' +``` + +Where `"${boot_dir}"` is: +``` +boot_dir='/boot/syslinux' +``` + +If this returns zero or more than one mounted drive we bail, print an error message and do not do any operations. + +# 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. + +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`. + +# Development + +## Conventional commits + +This project uses [Conventional Commits](https://www.conventionalcommits.org/) for its commit messages. + +### Commit types + +Commit _types_ besides `fix` and `feat` are: + +- `build`: Project structure, directory layout, build instructions for roll-out +- `refactor`: Keeping functionality while streamlining or otherwise improving function flow +- `test`: Working on test coverage +- `docs`: Documentation for project or components + +### Commit scopes + +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 +- `hook`: Configuring the hook(s) +- `meta`: Affects the project's repo layout, readme content, file names etc. diff --git a/pacman-zbm-syslinux-regen.hook b/pacman-zbm-syslinux-regen.hook new file mode 100644 index 0000000..fd9f052 --- /dev/null +++ b/pacman-zbm-syslinux-regen.hook @@ -0,0 +1,11 @@ +[Trigger] +Operation = Upgrade +Type = Package +Target = syslinux + +[Action] +Description = Regen syslinux and MBR +When = PostTransaction +Exec = /usr/local/bin/pacman-zbm-syslinux-regen +Depends = rsync +AbortOnFail diff --git a/pacman-zbm-syslinux-regen.sh b/pacman-zbm-syslinux-regen.sh new file mode 100644 index 0000000..d74ac9a --- /dev/null +++ b/pacman-zbm-syslinux-regen.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +boot_dir='/boot/syslinux' +boot_dir="${boot_dir%/}" +boot_disk="$(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 + 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}"