M .build.yml => .build.yml +1 -2
@@ 4,9 4,8 @@ packages:
- libefivar-dev
- libefiboot-dev
- libssl-dev
+ - ronn
tasks:
- - cmdline: |
- cat /proc/cmdline
- build-gcc: |
cd klapki
make
M .gitignore => .gitignore +2 -0
@@ 11,6 11,8 @@
!*.md
!src
!src/**
+!man
+!man/**
!ext
!ext/**
!test
M Makefile => Makefile +9 -2
@@ 29,15 29,16 @@ INCAR := $(foreach l,$(foreach l,fmt,$(l)/include) Catch2/single_include/catch2,
VERAR := $(foreach l,KLAPKI,-D$(l)_VERSION='$($(l)_VERSION)')
SOURCES := $(sort $(wildcard $(SRCDIR)*.cpp $(SRCDIR)**/*.cpp $(SRCDIR)**/**/*.cpp $(SRCDIR)**/**/**/*.cpp))
TEST_SOURCES := $(sort $(wildcard $(TSTDIR)*.cpp $(TSTDIR)**/*.cpp $(TSTDIR)**/**/*.cpp $(TSTDIR)**/**/**/*.cpp))
+MANPAGE_SOURCES := $(sort $(wildcard $(MANDIR)*.md $(MANDIR)**/*.md))
# Building with -flto on Clang means we can't make useful $(ARCH)es, so don't
LIBFMT := $(patsubst ext/fmt/src/%.cc,$(BLDDIR)fmt/obj/%$(OBJ),$(wildcard ext/fmt/src/*.cc))
-.PHONY : all clean build build-test fmt
+.PHONY : all clean build build-test man fmt
-all : fmt build build-test test
+all : fmt build man build-test test
test: build-test
$(OUTDIR)klapki-test$(EXE)
@@ 47,6 48,7 @@ clean :
build : fmt $(OUTDIR)klapki$(EXE)
build-test : fmt $(OUTDIR)klapki-test$(EXE)
+man : $(subst $(MANDIR),$(OUTDIR)man/,$(MANPAGE_SOURCES))
fmt : $(LIBFMT)
@@ 57,6 59,11 @@ $(OUTDIR)klapki$(EXE) : $(subst $(SRCDIR),$(OBJDIR),$(subst .cpp,$(OBJ),$(SOURCE
$(OUTDIR)klapki-test$(EXE) : $(subst $(TSTDIR),$(BLDDIR)test/,$(subst .cpp,$(OBJ),$(TEST_SOURCES))) $(subst $(SRCDIR),$(OBJDIR),$(subst .cpp,$(OBJ),$(filter-out $(SRCDIR)main.cpp,$(SOURCES)))) $(patsubst ext/fmt/src/%.cc,$(BLDDIR)fmt/obj/%$(OBJ),$(wildcard ext/fmt/src/*.cc))
$(CXX) $(CXXAR) -o$@ $^ $(PIC) $(LDAR)
+$(subst $(MANDIR),$(OUTDIR)man/,$(MANPAGE_SOURCES)) : $(MANDIR)index.txt $(MANPAGE_SOURCES)
+ @rm -rf $(dir $@) && mkdir -p $(dir $@)
+ cp $^ $(dir $@)
+ ronn $@
+
$(OBJDIR)%$(OBJ) : $(SRCDIR)%.cpp
@mkdir -p $(dir $@)
M README.md => README.md +10 -11
@@ 1,19 1,17 @@
# klapki [](LICENSE)
EFI boot manager; or, well, an EFI bootorder [compiler](//twitter.com/nabijaczleweli/status/1306144037070569472).
-## [Manpage](//rawcdn.githack.com/nabijaczleweli/feembox/man/feembox.1.html)
-<!-- TODO: put something on man.sr.ht -->
+## [Manpage](//git.sr.ht/~nabijaczleweli/klapki/tree/trunk/man/klapki.md)
-### Installation
+### Building
-dunno yet
+You'll need `libssl-dev` and `libefi{var,boot}-dev`, and `make` should hopefully Just Work™.
-#### probably a building sexion here
+### Installation
-CXX='clang++ -stdlib=libc++' make -j && ./to-zoot owo scp -P 10023 out/klapki nab@127.0.0.1:
-libssl-dev
-libefi{var,boot}-dev
+Copy `out/klapki` to `/sbin` and write a `/etc/klapki/{description,cmdline}`, as seen in the [manpage](//git.sr.ht/~nabijaczleweli/klapki/tree/trunk/man/klapki.md),
+<!-- TODO:
#### From Debian repository
The following line in `/etc/apt/sources.list` or equivalent:
@@ 36,6 34,7 @@ sudo apt install feembox
will work on x86_64 and i686.
See the [repository README](//debian.nabijaczleweli.xyz/README) for more information.
+-->
## Reporting bugs
@@ 45,11 44,11 @@ There's [the tracker](//todo.sr.ht/~nabijaczleweli/klapki), but also see the lis
Send a patch inline, as an attachment, or a git link and a ref to pull from to
[the list](//lists.sr.ht/~nabijaczleweli/klapki) ([~nabijaczleweli/klapki@lists.sr.ht](mailto:~nabijaczleweli/klapki)) or [me](mailto:nabijaczleweli@nabijaczleweli.xyz)
-directly. I'm not picky, just include the repo name in the subject prefix.
+directly. I'm not picky, just please include the repo name in the subject prefix.
-## Discussing
+## Discussion
-Please use the tracker or the list.
+Please use the tracker, the list, or [Twitter](//twitter.com/nabijaczleweli/status/1306144037070569472).
## Special thanks
M configMakefile => configMakefile +1 -0
@@ 64,3 64,4 @@ BLDDIR := out/build/
OBJDIR := $(BLDDIR)obj/
SRCDIR := src/
TSTDIR := test/
+MANDIR := man/
D klapki.md => klapki.md +0 -110
@@ 1,110 0,0 @@
-feembox(1) -- What if a feed, but it's a mailbox?
-=================================================
-
-## SYNOPSIS
-
-`feembox` [-v] [-t FROM:TO:HOW]... [-f MIME] [MAILDIR] [FEED]<br />
-`feembox` [-v] [-t FROM:TO:HOW]... [-f MIME] [MAILDIR] < feed.xml
-
-## DESCRIPTION
-
-`feembox` represents an (RSS/Atom/JSON) feed as a mailbox in the [maildir](https://cr.yp.to/proto/maildir.html) format.
-
-## OPTIONS
-
- [MAILDIR]
-
- Deliver to the specified directory instead of the CWD
-
- Parents must exist, all directory and its subdirs will be created as necessary
-
- [FEED]
-
- Read the feed from the specified file instead of stdin
-
- If "-" use stdin, otherwise must exist and be a file
-
- -v --verbose
-
- Print what's happening to the standard output,
- if specified twice: print parse debugging information.
-
- -t --transfrom <FROM:TO:HOW|FROM;TO;HOW>...
-
- Define an alternative transformation invocation HOW
- from the mime-type FROM to the mime-type TO.
-
- If the post content type matches FROM, "/bin/sh -c HOW" ("cmd /C HOW" on NT)
- is executed, its standard input tied thereto, and standard output
- to the buffer for the new multipart/alternative part TO.
-
- The separator between FROM, TO, and HOW is the platform's path list separator
- (i.e. ";" on NT and ":" elsewhere).
-
- Can be specified multiple times, in which case each transformation is invoked once,
- in order, on the current set of parts.
-
- -f --force <MIME>
-
- Force the post content type to be MIME, overriding what's specified therein.
-
- This is done before any transformations.
-
- Some feeds specify they're text/plain but are HTML,
- this can be used to massage them right.
-
-## EXIT VALUES
-
- 1 - option parse error
- 2 - feed file open failed
- 3 - feed parse failed
- 4 - maildir subdirectory read failed
- 5 - existing mail open(2)/mmap(2) failed
- 6 - creating a MAILDIR/tmp or MAILDIR/new failed
- 7 - formatting mail failed
- 8 - creating/writing/delivering mail failed
-
-## EXAMPLES
-
- Turndown (here: https://github.com/domchristie/turndown/pull/209 lightly patched to always read from stdin),
- can be used to turn HTML feeds (i.e. most of them) into usually pretty readable plaintext:
-
- P:\Rust\feembox>cat test-data/util-linux-newer.atom | target\debug\feembox -vt text/html;text/plain;turndown feedir
- ~/code/feembox$ cat test-data/util-linux-newer.atom | ./target/debug/feembox -vt 'text/html:text/plain;charset=utf-8:~/code/turndown/bin/turndown.js' feedir
- <stdin>: feed ID mailto:util-linux@vger.kernel.org, title "Util-Linux Archive on lore.kernel.org", updated 2020-05-18T11:41:20+00:00
- 25 entries:
- entry ID title updated published
- urn:uuid:d2c69230-d7ba-e4cf-ee51-2b25d53119a1 "Re: [PATCH] util-linux: Some minor fixes in some manuals" 2020-05-18T11:40:38+00:00 N/A
- urn:uuid:d9e31d9a-5d6c-8403-9661-2d303e6fb24a "Re: [PATCH] Fix dead references to kernel documentation" 2020-05-18T11:39:59+00:00 N/A
- urn:uuid:dccd47a2-d327-df9b-7ad1-9218d08a8349 "Re: Consistency fixes in util-linux man pages" 2020-05-18T10:36:15+00:00 N/A
- urn:uuid:ba1cf039-280f-f33d-199d-86f5a9c1bb1b "Re: Consistency fixes in util-linux man pages" 2020-05-18T08:28:25+00:00 N/A
- urn:uuid:98e3d4cd-17c1-ac1d-3dd9-7bbe87f6402e "[PATCH] Fix dead references to kernel documentation" 2020-05-17T15:13:35+00:00 N/A
- urn:uuid:68946069-8d16-0362-57e6-feba21ebbecb "Consistency fixes in util-linux man pages" 2020-05-16T08:25:11+00:00 N/A
- urn:uuid:94158972-3786-e3c6-7e0a-dec2988cd32b "[PATCH] ipcs.1: ipcs no longer needs read permission on IPC resources" 2020-05-16T08:10:32+00:00 N/A
- urn:uuid:37f8f0a9-d285-b8f9-5269-6eeb2475f9ba "plan for v2.35.2" 2020-05-15T13:05:16+00:00 N/A
-
- Delivering urn:uuid:ba1cf039-280f-f33d-199d-86f5a9c1bb1b to feedir/new/1591610344.M981513P12500Q1.nabuter
- Delivering urn:uuid:d2c69230-d7ba-e4cf-ee51-2b25d53119a1 to feedir/new/1591610346.M86312P12500Q2.nabuter
- Delivering urn:uuid:d9e31d9a-5d6c-8403-9661-2d303e6fb24a to feedir/new/1591610347.M339148P12500Q3.nabuter
- Delivering urn:uuid:dccd47a2-d327-df9b-7ad1-9218d08a8349 to feedir/new/1591610348.M505433P12500Q4.nabuter
-
-## AUTHOR
-
-Written by наб <<nabijaczleweli@nabijaczleweli.xyz>>
-
-## SPECIAL THANKS
-
-To all who support further development, in particular:
-
- * ThePhD
- * Embark Studios
-
-## REPORTING BUGS
-
-<<https://github.com/nabijaczleweli/feembox/issues>>
-
-## SEE ALSO
-
-<<https://github.com/nabijaczleweli/feembox>>
-
-<<https://cr.yp.to/proto/maildir.html>>
M klapki.sublime-project => klapki.sublime-project +5 -0
@@ 42,6 42,11 @@
},
{
"follow_symlinks": true,
+ "name": "Manpages",
+ "path": "man"
+ },
+ {
+ "follow_symlinks": true,
"name": "Build scripts",
"path": ".",
"file_include_patterns": [".build.yml", "*Makefile"],
A man/index.txt => man/index.txt +10 -0
@@ 0,0 1,10 @@
+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
A man/klapki.md => man/klapki.md +252 -0
@@ 0,0 1,252 @@
+klapki(8) -- EFI boot manager; or, well, an EFI bootorder compiler.
+===================================================================
+
+## SYNOPSIS
+
+`klapki` [`-nvVEh`]… [`op` [`arg`…]]…
+
+## DESCRIPTION
+<!-- TODO: klapki-internals(7) maybe? -->
+
+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:<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
+
+ 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:<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
+
+ * `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:<br />
+0: "description" or "cmdline"<br />
+1: kernel version<br />
+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>>
M src/config.cpp => src/config.cpp +2 -1
@@ 107,7 107,7 @@ std::string klapki::config::news_efi_dir() const {
while(*root == '\\' || *root == '/')
++root;
broot = root;
- std::transform(std::begin(broot), std::end(broot), std::begin(broot), [](auto c) { return c == '/' ? '\\' : c; });
+ std::replace(std::begin(broot), std::end(broot), '/', '\\');
while(!broot.empty() && broot.back() == '\\')
broot.pop_back();
vroot = broot;
@@ 143,6 143,7 @@ std::variant<klapki::config, std::string> klapki::config::read(const char ** arg
break;
case 'h':
+ // Remember to sync to klapki(8)
return fmt::format("klapki {}\n"
"Usage: {} [-nvVEh]… [op [arg…]]…\n"
"\n"
M src/context_commit.cpp => src/context_commit.cpp +1 -1
@@ 130,7 130,7 @@ std::optional<std::string> klapki::context::context::commit(const config & cfg,
auto adddir = [&](auto && ddir, auto && cbk) -> std::optional<std::string> {
if(esp_dirs.find(ddir) == std::end(esp_dirs)) {
auto dir = ddir;
- std::transform(std::begin(dir), std::end(dir), std::begin(dir), [](auto c) { return c == '\\' ? '/' : c; });
+ std::replace(std::begin(dir), std::end(dir), '\\', '/');
dir.erase(std::remove_if(std::begin(dir), std::end(dir),
[prev = '\0'](auto c) mutable {
if(prev == '/' && c == '/')
M src/context_save.cpp => src/context_save.cpp +1 -1
@@ 123,7 123,7 @@ std::optional<std::string> klapki::context::context::save(const config & cfg, st
}
}),
std::end(image_path));
- std::transform(std::begin(image_path), std::end(image_path), std::begin(image_path), [](auto c) { return isslash(c) ? '\\' : c; });
+ std::replace(std::begin(image_path), std::end(image_path), '/', '\\');
std::vector<std::uint8_t> devpath_file_node(efidp_make_file(nullptr, 0, image_path.data()));
if(efidp_make_file(devpath_file_node.data(), devpath_file_node.size(), image_path.data()) < 0)
M src/context_wisen.cpp => src/context_wisen.cpp +5 -1
@@ 49,7 49,7 @@ namespace {
if(fstat(fd, &sb) < 0)
return fmt::format("{} file stat(): {}", for_whom, strerror(errno));
- auto map = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ auto map = mmap(nullptr, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if(map == MAP_FAILED)
return fmt::format("{} file mmap(): {}", for_whom, strerror(errno));
@@ 95,6 95,8 @@ namespace {
str.remove_suffix(std::min(str.size() - str.find_last_not_of(" \f\n\r\t\v") - 1, str.size()));
}
+ static void denewline(std::string_view & str) { std::replace(const_cast<char *>(std::begin(str)), const_cast<char *>(std::end(str)), '\n', ' '); }
+
static void validate_cmdline(const std::string_view & cmdline) {
klapki::context::detail::tokenise_cmdline(cmdline, [&](auto && arg) {
if(arg.substr(0, std::strlen("initrd=")) == "initrd=") { // string_view::starts_with() is C++20
@@ 117,6 119,8 @@ std::optional<std::string> klapki::context::context::wisen(const config & cfg, s
auto cmdline = TRY(gain_wisdom(cfg, "cmdline", skern->version.c_str(), skern->variant.c_str()));
trim(description.data);
trim(cmdline.data);
+ denewline(description.data);
+ denewline(cmdline.data);
validate_cmdline(cmdline.data);
kern.description = description.data;
M src/ops_execute.cpp => src/ops_execute.cpp +17 -17
@@ 42,6 42,22 @@ std::optional<std::string> klapki::ops::execute(const klapki::ops::dump &, const
"Boot order: {}\n"
"{} boot entries\n"
"Desired boot position: {}\n"
+ "Boot variants: ");
+
+ if(state.statecfg.variants.empty())
+ fmt::print("(none)");
+ else {
+ bool first = true;
+ for(auto && el : state.statecfg.variants) {
+ if(!first)
+ fmt::print(", ");
+ else
+ first = false;
+
+ fmt::print("{}", el);
+ }
+ }
+ fmt::print("\n"
"Wanted entries: [",
state.order, state.entries.size(), state.statecfg.boot_position);
@@ 58,25 74,9 @@ std::optional<std::string> klapki::ops::execute(const klapki::ops::dump &, const
fmt::print("]\n"
"\n"
"{}\n"
- "\n"
- "Boot variants: ",
+ "\n",
context);
- if(state.statecfg.variants.empty())
- fmt::print("(none)");
- else {
- bool first = true;
- for(auto && el : state.statecfg.variants) {
- if(!first)
- fmt::print(", ");
- else
- first = false;
-
- fmt::print("{}", el);
- }
- }
- fmt::print("\n\n");
-
return {};
}