Skip to content

Instantly share code, notes, and snippets.

@nabijaczleweli
Last active September 24, 2020 00:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nabijaczleweli/1530eac3992945c07a7994021873c3bf to your computer and use it in GitHub Desktop.
Save nabijaczleweli/1530eac3992945c07a7994021873c3bf to your computer and use it in GitHub Desktop.
klapki(8) klapki.8.ronn
SHA1(3ssl) https://manpages.debian.org/buster/libssl-doc/SHA1.3ssl.en.html
efibootmgr(8) https://manpages.debian.org/buster/efibootmgr/efibootmgr.8.en.html
efivar(1) https://manpages.debian.org/buster/efivar/efivar.1.en.html
execl(3) https://manpages.debian.org/buster/manpages-dev/execl.3.en.html
gethostname(2) https://manpages.debian.org/buster/manpages-dev/gethostname.2.en.html
memfd_create(2) https://manpages.debian.org/buster/manpages-dev/memfd_create.2.en.html
kernel-install(8) https://www.freedesktop.org/software/systemd/man/kernel-install.html
.\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "KLAPKI" "8" "September 2020" ""
.SH "NAME"
\fBklapki\fR \- EFI boot manager; or, well, an EFI bootorder compiler\.
.SH "SYNOPSIS"
\fBklapki\fR [\fB\-nvVEh\fR]… [\fBop\fR [\fBarg\fR…]]…
.SH "DESCRIPTION"
klapki(8) generates and manages EFI boot entries on platforms compatible therewith\.
.P
This command\-line interface is based on running a set of operations (see \fIOPS\fR) which modify the state and context, then settling the new set\-up, then committing it; this means that, barring I/O errors, {dump}ing after the last operation with \-n is an accurate representation of what would be committed without it\.
.P
Care is taken to only write what is needed and only when it\'s needed – files and wanted entries are hashed with SHA1(3ssl) and only updated on mismatch\.
.P
Minimal state is stored, and it\'s only supplementary\. This means that removing all instances of a kernel boot entry with tools such as efibootmgr(8), efivar(1), or the platform UI will make klapki(8) forget about the kernel entirely, after minor complaints\.
.P
klapki(8)\'s entries \fIcan\fR be moved across \fBBootNNNN\fR entries, however, so long as they are kept identical\.
.P
The entry description and kernel cmdline are controlled via small executable files, see \fIWISDOM\fR\.
.SH "OPTIONS"
.TP
\fB\-n\fR
Don\'t commit – nothing will be written to the filesystem or the firmware\.
.TP
\fB\-v\fR
Verbose operation\.
.TP
\fB\-V\fR
Very verbose – adds a {dump} op in\-between each specified op\.
.TP
\fB\-E\fR
Increase libefivar verbosity level\.
.IP
At time of writing, libefivar supports \fBLOG_VERBOSE\fR and \fBLOG_DEBUG\fR, which require \-E to be specified one and two times, respectively\.
.IP
See the \fISEE ALSO\fR sexion for details\.
.TP
\fB\-h\fR
Show a help message with these flags, recognised environment variables (see \fIENVIRONMENT\fR) and ops (see \fIOPS\fR)\.
.TP
\fBop\fR [\fBarg\fR…]
Specify an operation to run and arguments to pass to it\.
.IP
See \fIOPS\fR for more detail\.
.SH "ENVIRONMENT"
.TP
\fBKLAPKI_HOST\fR=
By default, klapki(8) uses the value found in \fB/etc/machine\-id\fR (or, failing that, the current hostname, as obtained with gethostname(2)) as the identifier for the host\.
.IP
If this environment variable is present, it will be used instead; note, that the host identifier is used verbatim as an EFI variable name under klapki\'s GUID (a8a9ad3a\-f831\-11ea\-946d\-674ccd7415cc)\.
.TP
\fBKLAPKI_WISDOM\fR=
To obtain the description and cmdline, klapki(8) invokes respectively\-named files under the wisdom root via execl(3), which is \fB/etc/klapki\fR by defailt\. This value overrides that path\. If not empty, a \'/\' is additionally appended before the executable name\.
.IP
See also \fIWISDOM\fR below\.
.TP
\fBKLAPKI_EFI_ROOT\fR=
By default, klapki(8) puts newly\-installed files in \fB\eklapki\e{host}\e{version}\fR under the ESP\.
.IP
If present, this overrides the constant prefix\. Par exemple, setting \fBKLAPKI_EFI_ROOT\fR= when adding a kernel will put it and the initrds directly under \fB\e{host}\e{version}\fR (note that by default this collides with kernel\-install(8))\.
.SH "OPS"
.TP
\fBdump\fR
Write some state (boot order, total boot entries, boot position, each wanted entry, boot variants) and context (our kernels, fresh kernels, deleted files) to the standard output\.
.TP
\fBbootpos\fR <\fBposition\fR>
Change the boot position to 0\-based <\fBposition\fR>\.
.IP
The cluster of entries for the current host can be placed at any point in the boot order; it\'s 0 (i\.e\. at the beginning) by default, but if you have another operating system or boot\-loader and wish to have it be the default, you can simply move klapki(8) down the required amount of entries\.
.IP
See description of addvariant below for sorting inside the cluster\.
.TP
\fBaddkernel\fR <\fBversion\fR> <\fBimage\fR> [\fBinitrd\fR…] <\fB""\fR>
Allocate entries for the kernel with version <\fBversion\fR> whose image resides at <\fBimage\fR> and initrds at [\fBinitrd\fR]…\. The list of initrds is terminated with an empty argument\.
.IP
This directive is ignored if a kernel with version <\fBversion\fR> is already known\. See delkernel below\.
.IP
The kernel image and initrds will be copied to the ESP (see \fBKLAPKI_EFI_ROOT\fR= in \fIENVIRONMENT\fR) during context commit\.
.TP
\fBdelkernel\fR <\fBversion\fR>
Purge all entries for which the version is <\fBversion\fR>\.
.IP
The kernel image, initrds and containing folder will, if not used, be removed from the ESP during context commit\.
.TP
\fBaddvariant\fR <\fBvariant\fR>
Add an explicit variant <\fBvariant\fR> to the end, if not already known\. Accompanying boot entries will be allocated in the derivation phase as needed\.
.IP
Variants are a global property, and a boot entry is generated for each variant (that is: for the implicit variant, represented by the empty string, in addition to any configured explicit variants)\.
.IP
The order of explicit variants is preserved within each version group, which are sorted highest\-to\-lowest\. For example: a host with two kernels (\fI5\.8\.0\-[12]\-amd64\fR) and two explicit variants (\fIdebug\fR, \fIsilent\fR) will produce the following entries (assume \fB$KLAPKI_WISDOM/description\fR symlinked to \fB/bin/echo\fR); note how the highest kernel version is at the top:
.br
\~\~5\.8\.0\-2\-amd64
.br
\~\~5\.8\.0\-2\-amd64 debug
.br
\~\~5\.8\.0\-2\-amd64 silent
.br
\~\~5\.8\.0\-1\-amd64
.br
\~\~5\.8\.0\-1\-amd64 debug
.br
\~\~5\.8\.0\-1\-amd64 silent
.IP
After running klapki(8) with "\fIdelvariant debug addvariant debug\fR", the two explicit variants are now ordered differently (\fIsilent\fR, \fIdebug\fR), and this is reflected in the boot order; note also how the implicit variant always sorts earlier than any explicit ones:
.br
\~\~5\.8\.0\-2\-amd64
.br
\~\~5\.8\.0\-2\-amd64 silent
.br
\~\~5\.8\.0\-2\-amd64 debug
.br
\~\~5\.8\.0\-1\-amd64
.br
\~\~5\.8\.0\-1\-amd64 silent
.br
\~\~5\.8\.0\-1\-amd64 debug
.TP
\fBdelvariant\fR <\fBvariant\fR>
Remove explicit variant <\fBvariant\fR>, if any; accompanying boot entries will purged in the derivation phase as needed\.
.SH "WISDOM"
The entry description and kernel cmdline are acquired by executing \fBdescription\fR and \fBcmdline\fR in \fB/etc/klapki\fR (or \fBKLAPKI_WISDOM=\fR, see \fIENVIRONMENT\fR) with the following arguments:
.br
0: "description" or "cmdline"
.br
1: kernel version
.br
2: boot variant
.P
And the standard output tied to a memfd (see memfd_create(2)), which is then trimmed, and all newlines are replaced with a single space\.
.P
klapki(8) stops processing if the child exits with a non\-zero status or is killed by signal\. The special exit value 0x6B (107, ASCII \'k\') is used to signal an error to execl(2) the wisdom binary\.
.P
Additional \fBinitrd=\fR statements \fIshould\fR work (with warnings, since the should\. Please report on the bug tracker/mailing list (see \fIREPORTING BUGS\fR) if you use them successfully!) and will not be managed by klapki(8),
.P
The simplest \fB/etc/klapki/description\fR would be a link to \fB/bin/echo\fR\. A simple \fBcmdline\fR is a \fB/bin/sh\fR shebang + \fBecho\fR command, A cursed \fBcmdline\fR would be a \fB/bin/sh\fR shebang and an \fBawk \'{gsub(/initrd=[^ ]+ ?/, ""); print}\' /proc/cmdline\fR command\.
.SH "EXIT VALUES"
.nf
1 \- error reading configuration,
2 \- error loading state,
3 \- error resolving state,
4 \- error running an op,
5 \- error in propagation phase,
6 \- error in aging phase,
7 \- error in wisening phase,
8 \- error in saving phase,
9 \- error committing context,
10 \- error committing state\.
.fi
.SH "EXAMPLES"
A simple set\-up:
.IP "" 4
.nf
root@zoot:~# ls \-l description cmdline
\-rwxr\-xr\-x 1 root root 79 Sep 21 03:30 cmdline
lrwxrwxrwx 1 root root 9 Sep 20 04:30 description \-> /bin/echo
root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
.fi
.IP "" 0
.P
Add a kernel with a single initrd and a variant:
.IP "" 4
.nf
root@zoot:~# KLAPKI_HOST=zoot klapki addkernel 5\.8\.0\-2\-amd64 /boot/vmlinuz\-5\.8\.0\-2\-amd64 /boot/initrd\.img\-5\.8\.0\-2\-amd64 "" addvariant debug
EFI load: no config for this host (zoot) found; going to the top
Entry 000B changed
Entry 000D changed
Entry 000B: copied vmlinuz\-5\.8\.0\-2\-amd64 from /boot to \eklapki\ezoot\e5\.8\.0\-2\-amd64\e
Entry 000B: copied initrd\.img\-5\.8\.0\-2\-amd64 from /boot to \eklapki\ezoot\e5\.8\.0\-2\-amd64\e
Updating state config
Updating boot order
Writing entry 000B
Writing entry 000D
.fi
.IP "" 0
.P
Success! But the new "debug" entry doesn\'t really do much:
.IP "" 4
.nf
root@zoot:~# efibootmgr
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot0008 omitted
Boot0009* EFI Internal Shell FvVol(7cb8bdc9\-f8eb\-4f34\-aaea\-3ee4af6516a1)/FvFile(7c04a583\-9e3e\-4f1c\-ad65\-e05268d0b4d1)
Boot000A* Linux Boot Manager HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\eEFI\esystemd\esystemd\-bootx64\.efi)
Boot000B* 5\.8\.0\-2\-amd64 HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\eklapki\ezoot\e5\.8\.0\-2\-amd64\evmlinuz\-5\.8\.0\-2\-amd64)i\.n\.i\.t\.r\.d\.=\.\e\.k\.l\.a\.p\.k\.i\.\e\.z\.o\.o\.t\.\e\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\.\e\.i\.n\.i\.t\.r\.d\|\.\|\.\|\.i\.m\.g\.\-\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\. \.r\.o\.o\.t\.=\.Z\.F\.S\.=\.z\.o\.o\.t\./\.r\.o\.o\.t\. \.c\.o\.n\.s\.o\.l\.e\.=\.t\.t\.y\.S\.0\.
Boot000C* zoot 5\.8\.0\-1\-amd64 HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\e62dd03a4928c412180b3024ac6c03a90\e5\.8\.0\-1\-amd64\elinux)i\.n\.i\.t\.r\.d\.=\.\e\.6\.2\.d\.d\.0\.3\.a\.4\.9\.2\.8\.c\.4\.1\.2\.1\.8\.0\.b\.3\.0\.2\.4\.a\.c\.6\.c\.0\.3\.a\.9\.0\.\e\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.1\.\-\.a\.m\.d\.6\.4\.\e\.i\.n\.i\.t\.r\.d\|\.\|\.\|\.i\.m\.g\.\-\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.1\.\-\.a\.m\.d\.6\.4\. \.r\.o\.o\.t\.=\.Z\.F\.S\.=\.z\.o\.o\.t\./\.r\.o\.o\.t\. \.c\.o\.n\.s\.o\.l\.e\.=\.t\.t\.y\.S\.0\.
Boot000D* 5\.8\.0\-2\-amd64 debug HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\eklapki\ezoot\e5\.8\.0\-2\-amd64\evmlinuz\-5\.8\.0\-2\-amd64)i\.n\.i\.t\.r\.d\.=\.\e\.k\.l\.a\.p\.k\.i\.\e\.z\.o\.o\.t\.\e\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\.\e\.i\.n\.i\.t\.r\.d\|\.\|\.\|\.i\.m\.g\.\-\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\. \.r\.o\.o\.t\.=\.Z\.F\.S\.=\.z\.o\.o\.t\./\.r\.o\.o\.t\. \.c\.o\.n\.s\.o\.l\.e\.=\.t\.t\.y\.S\.0\.
.fi
.IP "" 0
.P
Uncontrivedly, adding a conditional with another argument to enable debugging in the Intel PRO/100 driver and re\-running klapki(8) will work:
.IP "" 4
.nf
root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
[ "$2" = "debug" ] && echo e100\.debug=16 || :
root@zoot:~# KLAPKI_WISDOM=\. KLAPKI_HOST=zoot klapki
Entry 000D changed
Updating state config
Updating entry 000D
.fi
.IP "" 0
.P
Note, that, as expected, only the state configuration (which stores the hash of the wanted entry) and the debug entry itself was updated:
.IP "" 4
.nf
root@zoot:~# efibootmgr \-v
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot000A and Boot000C omitted
Boot000B* 5\.8\.0\-2\-amd64 HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\eklapki\ezoot\e5\.8\.0\-2\-amd64\evmlinuz\-5\.8\.0\-2\-amd64)i\.n\.i\.t\.r\.d\.=\.\e\.k\.l\.a\.p\.k\.i\.\e\.z\.o\.o\.t\.\e\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\.\e\.i\.n\.i\.t\.r\.d\|\.\|\.\|\.i\.m\.g\.\-\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\. \.r\.o\.o\.t\.=\.Z\.F\.S\.=\.z\.o\.o\.t\./\.r\.o\.o\.t\. \.c\.o\.n\.s\.o\.l\.e\.=\.t\.t\.y\.S\.0\.
Boot000D* 5\.8\.0\-2\-amd64 debug HD(1,GPT,0655a4fb\-e2e9\-4fa6\-b37b\-a52633aed855,0x800,0x76800)/File(\eklapki\ezoot\e5\.8\.0\-2\-amd64\evmlinuz\-5\.8\.0\-2\-amd64)i\.n\.i\.t\.r\.d\.=\.\e\.k\.l\.a\.p\.k\.i\.\e\.z\.o\.o\.t\.\e\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\.\e\.i\.n\.i\.t\.r\.d\|\.\|\.\|\.i\.m\.g\.\-\.5\|\.\|\.\|\.8\|\.\|\.\|\.0\.\-\.2\.\-\.a\.m\.d\.6\.4\. \.r\.o\.o\.t\.=\.Z\.F\.S\.=\.z\.o\.o\.t\./\.r\.o\.o\.t\. \.c\.o\.n\.s\.o\.l\.e\.=\.t\.t\.y\.S\.0\. \.e\.1\.0\.0\|\.\|\.\|\.d\.e\.b\.u\.g\.=\.1\.6\.
.fi
.IP "" 0
.SH "AUTHOR"
Written by наб <\fInabijaczleweli@nabijaczleweli\.xyz\fR>
.SH "SPECIAL THANKS"
To all who support further development, in particular:
.IP "\[ci]" 4
ThePhD
.IP "\[ci]" 4
Embark Studios
.IP "" 0
.SH "REPORTING BUGS"
<\fIhttps://todo\.sr\.ht/~nabijaczleweli/klapki\fR>
.P
<\fI~nabijaczleweli/klapki@lists\.sr\.ht\fR>, archived at <\fIhttps://lists\.sr\.ht/~nabijaczleweli/klapki\fR>
.SH "SEE ALSO"
<\fIhttps://git\.sr\.ht/~nabijaczleweli/klapki\fR>
.P
UEFI specification, Sexion 3\.1\.3 Load Options and related: <\fIhttps://uefi\.org/sites/default/files/resources/UEFI_Spec_2_8_final\.pdf\fR>
.P
libefivar verbosity levels: <\fIhttps://github\.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util\.h#L328\fR>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf8'>
<meta name='generator' content='Ronn-NG/v0.9.1 (http://github.com/apjanke/ronn-ng/tree/0.9.1)'>
<title>klapki(8) - EFI boot manager; or, well, an EFI bootorder compiler.</title>
<style type='text/css' media='all'>
/* style: man */
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<body id='manpage'>
<div class='mp' id='man'>
<div class='man-navigation' style='display:none'>
<a href="#NAME">NAME</a>
<a href="#SYNOPSIS">SYNOPSIS</a>
<a href="#DESCRIPTION">DESCRIPTION</a>
<a href="#OPTIONS">OPTIONS</a>
<a href="#ENVIRONMENT">ENVIRONMENT</a>
<a href="#OPS">OPS</a>
<a href="#WISDOM">WISDOM</a>
<a href="#EXIT-VALUES">EXIT VALUES</a>
<a href="#EXAMPLES">EXAMPLES</a>
<a href="#AUTHOR">AUTHOR</a>
<a href="#SPECIAL-THANKS">SPECIAL THANKS</a>
<a href="#REPORTING-BUGS">REPORTING BUGS</a>
<a href="#SEE-ALSO">SEE ALSO</a>
</div>
<ol class='man-decor man-head man head'>
<li class='tl'>klapki(8)</li>
<li class='tc'></li>
<li class='tr'>klapki(8)</li>
</ol>
<h2 id="NAME">NAME</h2>
<p class="man-name">
<code>klapki</code> - <span class="man-whatis">EFI boot manager; or, well, an EFI bootorder compiler.</span>
</p>
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p><code>klapki</code> [<code>-nvVEh</code>]… [<code>op</code> [<code>arg</code>…]]…</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<!-- TODO: klapki-internals(7) maybe? -->
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> generates and manages EFI boot entries on platforms compatible therewith.</p>
<p>This command-line interface is based on running a set of operations (see <a href="#OPS" title="OPS" data-bare-link="true">OPS</a>) which modify the state and context,
then settling the new set-up, then committing it; this means that, barring I/O errors,
{dump}ing after the last operation with -n is an accurate representation of what would be committed without it.</p>
<p>Care is taken to only write what is needed and only when it's needed –
files and wanted entries are hashed with <a class="man-ref" href="https://manpages.debian.org/buster/libssl-doc/SHA1.3ssl.en.html">SHA1<span class="s">(3ssl)</span></a> and only updated on mismatch.</p>
<p>Minimal state is stored, and it's only supplementary.
This means that removing all instances of a kernel boot entry with tools such as <a class="man-ref" href="https://manpages.debian.org/buster/efibootmgr/efibootmgr.8.en.html">efibootmgr<span class="s">(8)</span></a>, <a class="man-ref" href="https://manpages.debian.org/buster/efivar/efivar.1.en.html">efivar<span class="s">(1)</span></a>,
or the platform UI will make <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> forget about the kernel entirely, after minor complaints.</p>
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a>'s entries <em>can</em> be moved across <code>BootNNNN</code> entries, however, so long as they are kept identical.</p>
<p>The entry description and kernel cmdline are controlled via small executable files, see <a href="#WISDOM" title="WISDOM" data-bare-link="true">WISDOM</a>.</p>
<!-- TODO: add how very careful not to touch any entries that aren't ours or whatever -->
<h2 id="OPTIONS">OPTIONS</h2>
<dl>
<dt><code>-n</code></dt>
<dd>Don't commit – nothing will be written to the filesystem or the firmware.</dd>
<dt><code>-v</code></dt>
<dd>Verbose operation.</dd>
<dt><code>-V</code></dt>
<dd>Very verbose – adds a {dump} op in-between each specified op.</dd>
<dt><code>-E</code></dt>
<dd>Increase libefivar verbosity level.
<p>At time of writing, libefivar supports <code>LOG_VERBOSE</code> and <code>LOG_DEBUG</code>,
which require -E to be specified one and two times, respectively.</p>
<p>See the <a href="#SEE-ALSO" title="SEE ALSO" data-bare-link="true">SEE ALSO</a> sexion for details.</p>
</dd>
<dt><code>-h</code></dt>
<dd>Show a help message with these flags, recognised environment variables (see <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>) and ops (see <a href="#OPS" title="OPS" data-bare-link="true">OPS</a>).</dd>
<dt>
<code>op</code> [<code>arg</code>…]</dt>
<dd>Specify an operation to run and arguments to pass to it.
<p>See <a href="#OPS" title="OPS" data-bare-link="true">OPS</a> for more detail.</p>
</dd>
</dl>
<h2 id="ENVIRONMENT">ENVIRONMENT</h2>
<dl>
<dt>
<code>KLAPKI_HOST</code>=</dt>
<dd>By default, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> uses the value found in <code>/etc/machine-id</code>
(or, failing that, the current hostname, as obtained with <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/gethostname.2.en.html">gethostname<span class="s">(2)</span></a>)
as the identifier for the host.
<p>If this environment variable is present, it will be used instead;
note, that the host identifier is used verbatim as an EFI variable name
under klapki's GUID (a8a9ad3a-f831-11ea-946d-674ccd7415cc).</p>
</dd>
<dt>
<code>KLAPKI_WISDOM</code>=</dt>
<dd>To obtain the description and cmdline, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> invokes respectively-named files under the wisdom root via <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/execl.3.en.html">execl<span class="s">(3)</span></a>,
which is <code>/etc/klapki</code> by defailt. This value overrides that path. If not empty, a '/' is additionally appended before the executable name.
<p>See also <a href="#WISDOM" title="WISDOM" data-bare-link="true">WISDOM</a> below.</p>
</dd>
<dt>
<code>KLAPKI_EFI_ROOT</code>=</dt>
<dd>By default, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> puts newly-installed files in <code>\klapki\{host}\{version}</code> under the ESP.
<p>If present, this overrides the constant prefix.
Par exemple, setting <code>KLAPKI_EFI_ROOT</code>= when adding a kernel will put it and the initrds directly under <code>\{host}\{version}</code>
(note that by default this collides with <a class="man-ref" href="https://www.freedesktop.org/software/systemd/man/kernel-install.html">kernel-install<span class="s">(8)</span></a>).</p>
</dd>
</dl>
<h2 id="OPS">OPS</h2>
<dl>
<dt><code>dump</code></dt>
<dd>Write some state (boot order, total boot entries, boot position, each wanted entry, boot variants)
and context (our kernels, fresh kernels, deleted files) to the standard output.</dd>
<dt>
<code>bootpos</code> &lt;<code>position</code>&gt;</dt>
<dd>Change the boot position to 0-based &lt;<code>position</code>&gt;.
<p>The cluster of entries for the current host can be placed at any point in the boot order;
it's 0 (i.e. at the beginning) by default, but if you have another operating system or boot-loader and wish to have it be the default,
you can simply move <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> down the required amount of entries.</p>
<p>See description of addvariant below for sorting inside the cluster.</p>
</dd>
<dt>
<code>addkernel</code> &lt;<code>version</code>&gt; &lt;<code>image</code>&gt; [<code>initrd</code>…] &lt;<code>""</code>&gt;</dt>
<dd>Allocate entries for the kernel with version &lt;<code>version</code>&gt; whose image resides at &lt;<code>image</code>&gt; and initrds at [<code>initrd</code>]….
The list of initrds is terminated with an empty argument.
<p>This directive is ignored if a kernel with version &lt;<code>version</code>&gt; is already known. See delkernel below.</p>
<p>The kernel image and initrds will be copied to the ESP (see <code>KLAPKI_EFI_ROOT</code>= in <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>) during context commit.</p>
</dd>
<dt>
<code>delkernel</code> &lt;<code>version</code>&gt;</dt>
<dd>Purge all entries for which the version is &lt;<code>version</code>&gt;.
<p>The kernel image, initrds and containing folder will, if not used, be removed from the ESP during context commit.</p>
</dd>
<dt>
<code>addvariant</code> &lt;<code>variant</code>&gt;</dt>
<dd>Add an explicit variant &lt;<code>variant</code>&gt; to the end, if not already known. Accompanying boot entries will be allocated in the derivation phase as needed.
<p>Variants are a global property, and a boot entry is generated for each variant
(that is: for the implicit variant, represented by the empty string, in addition to any configured explicit variants).</p>
<p>The order of explicit variants is preserved within each version group, which are sorted highest-to-lowest.
For example: a host with two kernels (<em>5.8.0-[12]-amd64</em>) and two explicit variants (<em>debug</em>, <em>silent</em>) will produce the following entries
(assume <code>$KLAPKI_WISDOM/description</code> symlinked to <code>/bin/echo</code>); note how the highest kernel version is at the top:<br>
  5.8.0-2-amd64<br>
  5.8.0-2-amd64 debug<br>
  5.8.0-2-amd64 silent<br>
  5.8.0-1-amd64<br>
  5.8.0-1-amd64 debug<br>
  5.8.0-1-amd64 silent</p>
<p>After running <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> with "<em>delvariant debug addvariant debug</em>", the two explicit variants are now ordered differently (<em>silent</em>, <em>debug</em>),
and this is reflected in the boot order; note also how the implicit variant always sorts earlier than any explicit ones:<br>
  5.8.0-2-amd64<br>
  5.8.0-2-amd64 silent<br>
  5.8.0-2-amd64 debug<br>
  5.8.0-1-amd64<br>
  5.8.0-1-amd64 silent<br>
  5.8.0-1-amd64 debug</p>
</dd>
<dt>
<code>delvariant</code> &lt;<code>variant</code>&gt;</dt>
<dd>Remove explicit variant &lt;<code>variant</code>&gt;, if any; accompanying boot entries will purged in the derivation phase as needed.</dd>
</dl>
<h2 id="WISDOM">WISDOM</h2>
<p>The entry description and kernel cmdline are acquired by executing <code>description</code> and <code>cmdline</code> in <code>/etc/klapki</code> (or <code>KLAPKI_WISDOM=</code>, see <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>)
with the following arguments:<br>
0: "description" or "cmdline"<br>
1: kernel version<br>
2: boot variant</p>
<p>And the standard output tied to a memfd (see <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/memfd_create.2.en.html">memfd_create<span class="s">(2)</span></a>), which is then trimmed, and all newlines are replaced with a single space.</p>
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> stops processing if the child exits with a non-zero status or is killed by signal.
The special exit value 0x6B (107, ASCII 'k') is used to signal an error to <span class="man-ref">execl<span class="s">(2)</span></span> the wisdom binary.</p>
<p>Additional <code>initrd=</code> statements <em>should</em> work (with warnings, since the should.
Please report on the bug tracker/mailing list (see <a href="#REPORTING-BUGS" title="REPORTING BUGS" data-bare-link="true">REPORTING BUGS</a>) if you use them successfully!) and will not be managed by <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a>,</p>
<p>The simplest <code>/etc/klapki/description</code> would be a link to <code>/bin/echo</code>.
A simple <code>cmdline</code> is a <code>/bin/sh</code> shebang + <code>echo</code> command,
A cursed <code>cmdline</code> would be a <code>/bin/sh</code> shebang and an <code>awk '{gsub(/initrd=[^ ]+ ?/, ""); print}' /proc/cmdline</code> command.</p>
<h2 id="EXIT-VALUES">EXIT VALUES</h2>
<pre><code>1 - error reading configuration,
2 - error loading state,
3 - error resolving state,
4 - error running an op,
5 - error in propagation phase,
6 - error in aging phase,
7 - error in wisening phase,
8 - error in saving phase,
9 - error committing context,
10 - error committing state.
</code></pre>
<h2 id="EXAMPLES">EXAMPLES</h2>
<p>A simple set-up:</p>
<pre><code>root@zoot:~# ls -l description cmdline
-rwxr-xr-x 1 root root 79 Sep 21 03:30 cmdline
lrwxrwxrwx 1 root root 9 Sep 20 04:30 description -&gt; /bin/echo
root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
</code></pre>
<p>Add a kernel with a single initrd and a variant:</p>
<pre><code>root@zoot:~# KLAPKI_HOST=zoot klapki addkernel 5.8.0-2-amd64 /boot/vmlinuz-5.8.0-2-amd64 /boot/initrd.img-5.8.0-2-amd64 "" addvariant debug
EFI load: no config for this host (zoot) found; going to the top
Entry 000B changed
Entry 000D changed
Entry 000B: copied vmlinuz-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Entry 000B: copied initrd.img-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Updating state config
Updating boot order
Writing entry 000B
Writing entry 000D
</code></pre>
<p>Success! But the new "debug" entry doesn't really do much:</p>
<pre><code>root@zoot:~# efibootmgr
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot0008 omitted
Boot0009* EFI Internal Shell FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
Boot000A* Linux Boot Manager HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\EFI\systemd\systemd-bootx64.efi)
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000C* zoot 5.8.0-1-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\62dd03a4928c412180b3024ac6c03a90\5.8.0-1-amd64\linux)i.n.i.t.r.d.=.\.6.2.d.d.0.3.a.4.9.2.8.c.4.1.2.1.8.0.b.3.0.2.4.a.c.6.c.0.3.a.9.0.\.5...8...0.-.1.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.1.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
</code></pre>
<p>Uncontrivedly, adding a conditional with another argument to enable debugging in the Intel PRO/100 driver and re-running <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> will work:</p>
<pre><code>root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
[ "$2" = "debug" ] &amp;&amp; echo e100.debug=16 || :
root@zoot:~# KLAPKI_WISDOM=. KLAPKI_HOST=zoot klapki
Entry 000D changed
Updating state config
Updating entry 000D
</code></pre>
<p>Note, that, as expected, only the state configuration (which stores the hash of the wanted entry) and the debug entry itself was updated:</p>
<pre><code>root@zoot:~# efibootmgr -v
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot000A and Boot000C omitted
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0. .e.1.0.0...d.e.b.u.g.=.1.6.
</code></pre>
<h2 id="AUTHOR">AUTHOR</h2>
<p>Written by наб &lt;<a href="mailto:nabijaczleweli@nabijaczleweli.xyz" data-bare-link="true">nabijaczleweli@nabijaczleweli.xyz</a>&gt;</p>
<h2 id="SPECIAL-THANKS">SPECIAL THANKS</h2>
<p>To all who support further development, in particular:</p>
<ul>
<li>ThePhD</li>
<li>Embark Studios</li>
</ul>
<h2 id="REPORTING-BUGS">REPORTING BUGS</h2>
<p>&lt;<a href="https://todo.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://todo.sr.ht/~nabijaczleweli/klapki</a>&gt;</p>
<p>&lt;<a href="mailto:~nabijaczleweli/klapki@lists.sr.ht" data-bare-link="true">~nabijaczleweli/klapki@lists.sr.ht</a>&gt;, archived at &lt;<a href="https://lists.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://lists.sr.ht/~nabijaczleweli/klapki</a>&gt;</p>
<h2 id="SEE-ALSO">SEE ALSO</h2>
<p>&lt;<a href="https://git.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://git.sr.ht/~nabijaczleweli/klapki</a>&gt;</p>
<p>UEFI specification, Sexion 3.1.3 Load Options and related:
&lt;<a href="https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf" data-bare-link="true">https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf</a>&gt;</p>
<p>libefivar verbosity levels:
&lt;<a href="https://github.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util.h#L328" data-bare-link="true">https://github.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util.h#L328</a>&gt;</p>
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>September 2020</li>
<li class='tr'>klapki(8)</li>
</ol>
</div>
</body>
</html>

klapki(8) -- EFI boot manager; or, well, an EFI bootorder compiler.

SYNOPSIS

klapki [-nvVEh]… [op [arg…]]…

DESCRIPTION

klapki(8) generates and manages EFI boot entries on platforms compatible therewith.

This command-line interface is based on running a set of operations (see [OPS][]) which modify the state and context, then settling the new set-up, then committing it; this means that, barring I/O errors, {dump}ing after the last operation with -n is an accurate representation of what would be committed without it.

Care is taken to only write what is needed and only when it's needed – files and wanted entries are hashed with SHA1(3ssl) and only updated on mismatch.

Minimal state is stored, and it's only supplementary. This means that removing all instances of a kernel boot entry with tools such as efibootmgr(8), efivar(1), or the platform UI will make klapki(8) forget about the kernel entirely, after minor complaints.

klapki(8)'s entries can be moved across BootNNNN entries, however, so long as they are kept identical.

The entry description and kernel cmdline are controlled via small executable files, see [WISDOM][].

OPTIONS

  • -n: Don't commit – nothing will be written to the filesystem or the firmware.

  • -v: Verbose operation.

  • -V: Very verbose – adds a {dump} op in-between each specified op.

  • -E: Increase libefivar verbosity level.

    At time of writing, libefivar supports LOG_VERBOSE and LOG_DEBUG, which require -E to be specified one and two times, respectively.

    See the [SEE ALSO][] sexion for details.

  • -h: Show a help message with these flags, recognised environment variables (see [ENVIRONMENT][]) and ops (see [OPS][]).

  • op [arg…]: Specify an operation to run and arguments to pass to it.

    See [OPS][] for more detail.

ENVIRONMENT

  • KLAPKI_HOST=: By default, klapki(8) uses the value found in /etc/machine-id (or, failing that, the current hostname, as obtained with gethostname(2)) as the identifier for the host.

    If this environment variable is present, it will be used instead; note, that the host identifier is used verbatim as an EFI variable name under klapki's GUID (a8a9ad3a-f831-11ea-946d-674ccd7415cc).

  • KLAPKI_WISDOM=: To obtain the description and cmdline, klapki(8) invokes respectively-named files under the wisdom root via execl(3), which is /etc/klapki by defailt. This value overrides that path. If not empty, a '/' is additionally appended before the executable name.

    See also [WISDOM][] below.

  • KLAPKI_EFI_ROOT=: By default, klapki(8) puts newly-installed files in \klapki\{host}\{version} under the ESP.

    If present, this overrides the constant prefix. Par exemple, setting KLAPKI_EFI_ROOT= when adding a kernel will put it and the initrds directly under \{host}\{version} (note that by default this collides with kernel-install(8)).

OPS

  • dump: Write some state (boot order, total boot entries, boot position, each wanted entry, boot variants) and context (our kernels, fresh kernels, deleted files) to the standard output.

  • bootpos <position>: Change the boot position to 0-based <position>.

    The cluster of entries for the current host can be placed at any point in the boot order; it's 0 (i.e. at the beginning) by default, but if you have another operating system or boot-loader and wish to have it be the default, you can simply move klapki(8) down the required amount of entries.

    See description of addvariant below for sorting inside the cluster.

  • addkernel <version> <image> [initrd…] <"">: Allocate entries for the kernel with version <version> whose image resides at <image> and initrds at [initrd]…. The list of initrds is terminated with an empty argument.

    This directive is ignored if a kernel with version <version> is already known. See delkernel below.

    The kernel image and initrds will be copied to the ESP (see KLAPKI_EFI_ROOT= in [ENVIRONMENT][]) during context commit.

  • delkernel <version>: Purge all entries for which the version is <version>.

    The kernel image, initrds and containing folder will, if not used, be removed from the ESP during context commit.

  • addvariant <variant>: Add an explicit variant <variant> to the end, if not already known. Accompanying boot entries will be allocated in the derivation phase as needed.

    Variants are a global property, and a boot entry is generated for each variant (that is: for the implicit variant, represented by the empty string, in addition to any configured explicit variants).

    The order of explicit variants is preserved within each version group, which are sorted highest-to-lowest. For example: a host with two kernels (5.8.0-[12]-amd64) and two explicit variants (debug, silent) will produce the following entries (assume $KLAPKI_WISDOM/description symlinked to /bin/echo); note how the highest kernel version is at the top:
      5.8.0-2-amd64
      5.8.0-2-amd64 debug
      5.8.0-2-amd64 silent
      5.8.0-1-amd64
      5.8.0-1-amd64 debug
      5.8.0-1-amd64 silent

    After running klapki(8) with "delvariant debug addvariant debug", the two explicit variants are now ordered differently (silent, debug), and this is reflected in the boot order; note also how the implicit variant always sorts earlier than any explicit ones:
      5.8.0-2-amd64
      5.8.0-2-amd64 silent
      5.8.0-2-amd64 debug
      5.8.0-1-amd64
      5.8.0-1-amd64 silent
      5.8.0-1-amd64 debug

  • delvariant <variant>: Remove explicit variant <variant>, if any; accompanying boot entries will purged in the derivation phase as needed.

WISDOM

The entry description and kernel cmdline are acquired by executing description and cmdline in /etc/klapki (or KLAPKI_WISDOM=, see [ENVIRONMENT][]) with the following arguments:
0: "description" or "cmdline"
1: kernel version
2: boot variant

And the standard output tied to a memfd (see memfd_create(2)), which is then trimmed, and all newlines are replaced with a single space.

klapki(8) stops processing if the child exits with a non-zero status or is killed by signal. The special exit value 0x6B (107, ASCII 'k') is used to signal an error to execl(2) the wisdom binary.

Additional initrd= statements should work (with warnings, since the should. Please report on the bug tracker/mailing list (see [REPORTING BUGS][]) if you use them successfully!) and will not be managed by klapki(8),

The simplest /etc/klapki/description would be a link to /bin/echo. A simple cmdline is a /bin/sh shebang + echo command, A cursed cmdline would be a /bin/sh shebang and an awk '{gsub(/initrd=[^ ]+ ?/, ""); print}' /proc/cmdline command.

EXIT VALUES

1 - error reading configuration,
2 - error loading state,
3 - error resolving state,
4 - error running an op,
5 - error in propagation phase,
6 - error in aging phase,
7 - error in wisening phase,
8 - error in saving phase,
9 - error committing context,
10 - error committing state.

EXAMPLES

A simple set-up:

root@zoot:~# ls -l description cmdline
-rwxr-xr-x 1 root root 79 Sep 21 03:30 cmdline
lrwxrwxrwx 1 root root  9 Sep 20 04:30 description -> /bin/echo
root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0

Add a kernel with a single initrd and a variant:

root@zoot:~# KLAPKI_HOST=zoot klapki addkernel 5.8.0-2-amd64 /boot/vmlinuz-5.8.0-2-amd64 /boot/initrd.img-5.8.0-2-amd64 "" addvariant debug
EFI load: no config for this host (zoot) found; going to the top
Entry 000B changed
Entry 000D changed
Entry 000B: copied vmlinuz-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Entry 000B: copied initrd.img-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Updating state config
Updating boot order
Writing entry 000B
Writing entry 000D

Success! But the new "debug" entry doesn't really do much:

root@zoot:~# efibootmgr
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot0008 omitted
Boot0009* EFI Internal Shell    FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
Boot000A* Linux Boot Manager    HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\EFI\systemd\systemd-bootx64.efi)
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000C* zoot 5.8.0-1-amd64    HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\62dd03a4928c412180b3024ac6c03a90\5.8.0-1-amd64\linux)i.n.i.t.r.d.=.\.6.2.d.d.0.3.a.4.9.2.8.c.4.1.2.1.8.0.b.3.0.2.4.a.c.6.c.0.3.a.9.0.\.5...8...0.-.1.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.1.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug   HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.

Uncontrivedly, adding a conditional with another argument to enable debugging in the Intel PRO/100 driver and re-running klapki(8) will work:

root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
[ "$2" = "debug" ] && echo e100.debug=16 || :

root@zoot:~# KLAPKI_WISDOM=. KLAPKI_HOST=zoot klapki
Entry 000D changed
Updating state config
Updating entry 000D

Note, that, as expected, only the state configuration (which stores the hash of the wanted entry) and the debug entry itself was updated:

root@zoot:~# efibootmgr -v
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot000A and Boot000C omitted
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug   HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0. .e.1.0.0...d.e.b.u.g.=.1.6.

AUTHOR

Written by наб <nabijaczleweli@nabijaczleweli.xyz>

SPECIAL THANKS

To all who support further development, in particular:

  • ThePhD
  • Embark Studios

REPORTING BUGS

<https://todo.sr.ht/~nabijaczleweli/klapki>

<mailto:~nabijaczleweli/klapki@lists.sr.ht>, archived at <https://lists.sr.ht/~nabijaczleweli/klapki>

SEE ALSO

<https://git.sr.ht/~nabijaczleweli/klapki>

UEFI specification, Sexion 3.1.3 Load Options and related: <https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf>

libefivar verbosity levels: <https://github.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util.h#L328>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment